精簡易懂,30 分鐘學(xué)會 SVD 矩陣分解,很強(qiáng)!
點(diǎn)擊上方“小白學(xué)視覺”,選擇加"星標(biāo)"或“置頂”
重磅干貨,第一時(shí)間送達(dá)
它能夠?qū)⒁粋€(gè)任意形狀的矩陣分解成一個(gè)正交矩陣和一個(gè)對角矩陣以及另一個(gè)正交矩陣的乘積。
SVD分解具有非常深刻的幾何含義。矩陣實(shí)際上對應(yīng)著一種線性變換,一個(gè)矩陣作用到一個(gè)向量上,會得到一個(gè)新的向量。任何一個(gè)矩陣的操作效果可以分解成一次旋轉(zhuǎn),一次拉伸和維度改變,以及另外一次旋轉(zhuǎn)三者作用效果的合成。
SVD分解通常用于數(shù)據(jù)壓縮和數(shù)據(jù)降維。用于數(shù)據(jù)降維時(shí),既可以對列降維,也可以對行降維,其中對列的降維等價(jià)于PCA的降維。
不僅如此,SVD算法還可以用于在聲音和圖像處理中剝離背景信號,在推薦算法中也經(jīng)常出現(xiàn)它的身影。
一,SVD矩陣分解簡介
SVD分解將任意矩陣分解成一個(gè)正交矩陣和一個(gè)對角矩陣以及另一個(gè)正交矩陣的乘積。
對角矩陣的對角元稱為矩陣的奇異值,可以證明,奇異值總是大于等于0的。
當(dāng)對角矩陣的奇異值按從大到小排列時(shí),SVD分解是唯一的。


SVD分解有著非常深刻的幾何含義。
矩陣實(shí)際上是對應(yīng)著一種線性變換。一個(gè)矩陣作用到一個(gè)向量上,會得到一個(gè)新的向量。任何一個(gè)矩陣的操作效果可以分解成一次旋轉(zhuǎn),一次拉伸和維度改變,以及另外一次旋轉(zhuǎn)三者作用效果的合成。
注意正交矩陣和作用到向量后是不會改變向量長度的,所以對應(yīng)著旋轉(zhuǎn)變換。
二,SVD分解的數(shù)學(xué)推演
可以推出


依然是對角矩陣,又U為正交矩陣。
所以
為AA^T的相似對角矩陣,其對角元為AA^T的特征值,U由其對應(yīng)特征向量構(gòu)成,這些向量稱為A的左奇異向量。
因此
的對角元為AA^T特征值的平方根,稱之為矩陣A的奇異值。
類似地V由A^TA的特征向量構(gòu)成,這些向量稱為A的右奇異向量。
三,SVD分解和數(shù)據(jù)壓縮
奇異值描述了矩陣對應(yīng)的拉伸變換在各個(gè)方向的比例,是矩陣的重要特征。
奇異值的分布通常非常不均,在很多的情況下前10%甚至1%的奇異值之和就占了全部奇異值之和的99%以上。
因此我們可以用前個(gè)大的奇異值來近似的描述矩陣。
這就是SVD分解用來進(jìn)行數(shù)據(jù)壓縮的原理。

# 下面的范例示范SVD分解用于圖片數(shù)據(jù)壓縮。
%matplotlib inline
%config InlineBackend.figure_format = 'svg'
import numpy as np
from matplotlib import pyplot as plt
from skimage import data
def compressBySVD(img,r):
u,s,vt = np.linalg.svd(img)
ur = u[:,0:r]
sr = s[0:r]
vtr = vt[0:r,:]
return (ur,sr,vtr)
def rebuildFromSVD(ur,sr,vtr):
img = [email protected](sr)@vtr
return(img)
img = data.camera()/255.0
plt.figure(figsize=(10,8))
for i,r in enumerate([5,10,20,30,40,50,100,200],start = 1):
ur,sr,vtr = compressBySVD(img,r)
compress_ratio = (np.product(ur.shape) + len(sr) +
np.product(vtr.shape))/np.product(img.shape)
img_rebuild = rebuildFromSVD(ur,sr,vtr)
ax=plt.subplot(3,3,i)
ax.imshow(img_rebuild,cmap = "gray")
ax.set_title("r=%d"%r+", compress_ratio=%.2f"%compress_ratio)
ax.set_xticks([])
ax.set_yticks([])
ax = plt.subplot(3,3,9)
ax.imshow(img,cmap = "gray")
ax.set_title("r = 512, original image")
ax.set_xticks([])
ax.set_yticks([])
plt.show()

四,SVD分解和PCA降維
PCA降維可以看成是SVD分解的一個(gè)應(yīng)用。PCA降維使用的變換矩陣恰好是SVD分解的右奇異矩陣。
實(shí)際上,由于SVD分解存在著無需通過計(jì)算特征值和特征向量的可并行的數(shù)值迭代計(jì)算算法,sklearn的PCA降維算法正是通過SVD分解計(jì)算的。

假定PCA對應(yīng)的正交變換矩陣為,根據(jù)PCA算法的數(shù)學(xué)原理,
由協(xié)方差矩陣
的各個(gè)特征向量組成,它能夠?qū)f(xié)方差矩陣相似對角化。

其中為
的相似對角矩陣,且對角元由大到小排列。
利用的SVD矩陣分解:
我們有
根據(jù)SVD分解的數(shù)學(xué)原理,也是
的相似對角矩陣,且對角元由大到小排列。
于是有:

于是右奇異向量構(gòu)成的矩陣 ?? 恰好是PCA算法所需要的正交變換矩陣 ??。

注意到PCA算法實(shí)際上是一種列降維的方法,實(shí)際上利用SVD分解的左奇異矩陣也可以對矩陣進(jìn)行行降維。

# 演示SVD用于PCA降維的計(jì)算
%matplotlib inline
%config InlineBackend.figure_format = 'svg'
import numpy as np
from sklearn.decomposition import PCA
from matplotlib import pyplot as plt
from skimage import data
X = np.array([[-1.0, -3, -2], [-2, -1, -3], [-3, -2, -5], [2, 1, 3], [6, 1, 3], [2, 2, 3]])
pca = PCA(n_components= 2)
X_new = pca.fit_transform(X)
print("\ndecomposition by pca:")
print("singular value:")
print(pca.singular_values_)
print("X_new:")
print(X_new)
print("\ndecomposition by svd:")
U,S,Vt = np.linalg.svd(X-X.mean(axis = 0))
print("singular value:\n",S[:2])
print("X_new:")
print(np.dot(X-X.mean(axis = 0),np.transpose(Vt)[:,0:2]))
# 注:降維結(jié)果中正負(fù)號的差異是因?yàn)镻CA調(diào)整了SVD分解后的U和Vt符號以保持各列最大值取正
輸出如下:
decomposition by pca:
singular value:
[11.31375337 2.89544001]
X_new:
[[ 3.23378083 1.06346839]
[ 3.88607412 -0.50763321]
[ 6.25267378 0.08479886]
[-3.50509914 -0.96584476]
[-6.02398361 1.89494314]
[-3.84344598 -1.56973242]]
decomposition by svd:
singular value:
[11.31375337 2.89544001]
X_new:
[[-3.23378083 -1.06346839]
[-3.88607412 0.50763321]
[-6.25267378 -0.08479886]
[ 3.50509914 0.96584476]
[ 6.02398361 -1.89494314]
[ 3.84344598 1.56973242]]交流群
歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動駕駛、計(jì)算攝影、檢測、分割、識別、醫(yī)學(xué)影像、GAN、算法競賽等微信群(以后會逐漸細(xì)分),請掃描下面微信號加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進(jìn)入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~

