它能夠將一個任意形狀的矩陣分解成一個正交矩陣和一個對角矩陣以及另一個正交矩陣的乘積。
SVD分解具有非常深刻的幾何含義。矩陣實際上對應著一種線性變換,一個矩陣作用到一個向量上,會得到一個新的向量。任何一個矩陣的操作效果可以分解成一次旋轉,一次拉伸和維度改變,以及另外一次旋轉三者作用效果的合成。
SVD分解通常用於數據壓縮和數據降維。用於數據降維時,既可以對列降維,也可以對行降維,其中對列的降維等價於PCA的降維。
不僅如此,SVD算法還可以用於在聲音和圖像處理中剝離背景信號,在推薦算法中也經常出現它的身影。
公眾號後臺回復關鍵字: 源碼,獲取本文全部代碼和對應插圖PPT。
SVD分解將任意矩陣分解成一個正交矩陣和一個對角矩陣以及另一個正交矩陣的乘積。
對角矩陣的對角元稱為矩陣的奇異值,可以證明,奇異值總是大於等於0的。
當對角矩陣的奇異值按從大到小排列時,SVD分解是唯一的。
SVD分解有著非常深刻的幾何含義。
矩陣實際上是對應著一種線性變換。一個矩陣作用到一個向量上,會得到一個新的向量。任何一個矩陣的操作效果可以分解成一次旋轉,一次拉伸和維度改變,以及另外一次旋轉三者作用效果的合成。
注意正交矩陣和作用到向量後是不會改變向量長度的,所以對應著旋轉變換。
二,SVD分解的數學推演可以推出
依然是對角矩陣,又U為正交矩陣。
所以 為AA^T的相似對角矩陣,其對角元為AA^T的特徵值,U由其對應特徵向量構成,這些向量稱為A的左奇異向量。
因此的對角元為AA^T特徵值的平方根,稱之為矩陣A的奇異值。
類似地V由A^TA的特徵向量構成,這些向量稱為A的右奇異向量。
三,SVD分解和數據壓縮奇異值描述了矩陣對應的拉伸變換在各個方向的比例,是矩陣的重要特徵。
奇異值的分布通常非常不均,在很多的情況下前10%甚至1%的奇異值之和就佔了全部奇異值之和的99%以上。
因此我們可以用前個大的奇異值來近似的描述矩陣。
這就是SVD分解用來進行數據壓縮的原理。
假設 m = 10000,n = 8000,原來存儲矩陣A需要存儲8000萬個數字,如果經過奇異值分解發現前100個奇異值貢獻了99%的奇異值之和,於是可以近似只保留這100個奇異值及對應的左右奇異向量,那麼只需要保留100+10000×100+100×8000= 180.01萬個數字,只有原來的不到2.3%。# 下面的範例示範SVD分解用於圖片數據壓縮。
%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 = ur@np.diag(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()
PCA降維可以看成是SVD分解的一個應用。PCA降維使用的變換矩陣恰好是SVD分解的右奇異矩陣。
實際上,由於SVD分解存在著無需通過計算特徵值和特徵向量的可並行的數值迭代計算算法,sklearn的PCA降維算法正是通過SVD分解計算的。
下面證明SVD分解的右奇異向量構成的矩陣恰好是PCA算法所需要的正交變換矩陣。假定PCA對應的正交變換矩陣為,根據PCA算法的數學原理,
由協方差矩陣 的各個特徵向量組成,它能夠將協方差矩陣相似對角化。
其中為的相似對角矩陣,且對角元由大到小排列。
利用的SVD矩陣分解:
我們有
根據SVD分解的數學原理,也是 的相似對角矩陣,且對角元由大到小排列。
於是有:
於是右奇異向量構成的矩陣 𝑉 恰好是PCA算法所需要的正交變換矩陣 𝑊。
注意到PCA算法實際上是一種列降維的方法,實際上利用SVD分解的左奇異矩陣也可以對矩陣進行行降維。
# 演示SVD用於PCA降維的計算
%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]))
# 註:降維結果中正負號的差異是因為PCA調整了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]]
公眾號後臺回復關鍵字: 源碼,獲取本文全部代碼和對應插圖PPT。