一、簡(jiǎn)介
????????奇異值分解是一種十分重要但又難以理解的矩陣處理技術(shù),在機(jī)器學(xué)習(xí)中是最重要的分解沒有之一的存在。那么,奇異值分解到底是在干什么呢?
????????矩陣?A?表示的是高維數(shù)據(jù),通常情況下高維數(shù)據(jù)分布并不是雨露均沾的,而往往是厚此薄彼,集中分布在某些維度上,如下圖
????????雖然原始數(shù)據(jù)的的確確是二維數(shù)據(jù),但是其實(shí)主要集中分布在直線?L?(一維空間)附近,在這里,SVD(奇異值分解)其實(shí)就是在尋找直線?L?,然后將數(shù)據(jù)映射到直線?L?上,實(shí)現(xiàn)數(shù)據(jù)降維的過程,即如下圖
????????于是,通過SVD(奇異值分解),就可以利用降維后的數(shù)據(jù)近似地替代原始數(shù)據(jù)。所以,SVD(奇異值分解)其實(shí)就是在尋找數(shù)據(jù)分布的主要維度,將原始的高維數(shù)據(jù)映射到低維子空間中實(shí)現(xiàn)數(shù)據(jù)降維。
二、概念
????????奇異值分解(singular Value Decomposition),簡(jiǎn)稱SVD,線性代數(shù)中矩陣分解的方法。假如有一個(gè)矩陣A,對(duì)它進(jìn)行奇異值分解,可以得到三個(gè)矩陣:
????????矩陣除了對(duì)角元素不為0,其他元素都為0,并且對(duì)角元素是從大到小排列的,前面的元素比較大,后面的很多元素接近0。這些對(duì)角元素就是奇異值。
????????中有n個(gè)奇異值,但是由于排在后面的很多接近0,所以我們可以僅保留比較大的r個(gè)奇異值:
????????實(shí)際應(yīng)用中,我們僅需保留著三個(gè)比較小的矩陣,就能表示A,不僅節(jié)省存儲(chǔ)量,在計(jì)算的時(shí)候更是減少了計(jì)算量。SVD在信息檢索(隱性語義索引)、圖像壓縮、推薦系統(tǒng)、金融等領(lǐng)域都有應(yīng)用。
????????SVD一個(gè)重要的應(yīng)用就是圖像壓縮存儲(chǔ),因?yàn)閿?shù)字圖像本身就是個(gè)矩陣,通過一個(gè)近似的低秩矩陣替代原矩陣,可以大大減少存儲(chǔ)量。SVD還有很多用途,比如機(jī)器學(xué)習(xí)中的主成分分析,這才是直接利用低維矩陣?M?替代原矩陣?A?實(shí)現(xiàn)降維。
三、np.linalg.svd(a,full_matrices=1,compute_uv=1)用法描述
參數(shù):
a是一個(gè)形如(M,N)矩陣
full_matrices的取值是為0或者1,默認(rèn)值為1,這時(shí)u的大小為(M,M),v的大小為(N,N) 。否則u的大小為(M,K),v的大小為(K,N) ,K=min(M,N)。
compute_uv的取值是為0或者1,默認(rèn)值為1,表示計(jì)算u,s,v。為0的時(shí)候只計(jì)算s。
返回值:
總共有三個(gè)返回值u,s,v
u大小為(M,M),s大小為(M,N),v大小為(N,N)。
A = u*s*v
????????其中s是對(duì)矩陣a的奇異值分解。s除了對(duì)角元素不為0,其他元素都為0,并且對(duì)角元素從大到小排列。s中有n個(gè)奇異值,一般排在后面的比較接近0,所以僅保留比較大的r個(gè)奇異值。?
例子:
>>> from numpy import *
>>> data = mat([[1,2,3],[4,5,6]])
>>> U,sigma,VT = np.linalg.svd(data)
>>> print U
[[-0.3863177 ?-0.92236578]
?[-0.92236578 ?0.3863177 ]]
>>> print sigma
[9.508032 ? 0.77286964]
>>> print VT
[[-0.42866713 -0.56630692 -0.7039467 ]
?[ 0.80596391 ?0.11238241 -0.58119908]
?[ 0.40824829 -0.81649658 ?0.40824829]]
????????因?yàn)閟igma是除了對(duì)角元素不為0,其他元素都為0。所以返回的時(shí)候,作為一維矩陣返回。本來sigma應(yīng)該是由3個(gè)值的,但是因?yàn)樽詈笠粋€(gè)值為0,所以直接省略了。?
四、例子
>>> a = np.random.randn(9, 6) + 1j*np.random.randn(9, 6)
>>> b = np.random.randn(2, 7, 8, 3) + 1j*np.random.randn(2, 7, 8, 3)
基于全 SVD 的重構(gòu),2D 案例:
>>> u, s, vh = np.linalg.svd(a, full_matrices=True)
>>> u.shape, s.shape, vh.shape
((9, 9), (6,), (6, 6))
# numpy的allclose方法,比較兩個(gè)array是不是每一元素都相等,默認(rèn)在1e-05的誤差范圍內(nèi)
>>> np.allclose(a, np.dot(u[:, :6] * s, vh))
True
>>> smat = np.zeros((9, 6), dtype=complex)
>>> smat[:6, :6] = np.diag(s)
>>> np.allclose(a, np.dot(u, np.dot(smat, vh)))
True
基于簡(jiǎn)化 SVD 的重建,2D 案例:
>>> u, s, vh = np.linalg.svd(a, full_matrices=False)
>>> u.shape, s.shape, vh.shape
((9, 6), (6,), (6, 6))
>>> np.allclose(a, np.dot(u * s, vh))
True
>>> smat = np.diag(s)
>>> np.allclose(a, np.dot(u, np.dot(smat, vh)))
True
基于全SVD、4D案例的重構(gòu):
>>> u, s, vh = np.linalg.svd(b, full_matrices=True)
>>> u.shape, s.shape, vh.shape
((2, 7, 8, 8), (2, 7, 3), (2, 7, 3, 3))
>>> np.allclose(b, np.matmul(u[..., :3] * s[..., None, :], vh))
True
>>> np.allclose(b, np.matmul(u[..., :3], s[..., None] * vh))
True
基于簡(jiǎn)化 SVD 的重建,4D 案例:
>>> u, s, vh = np.linalg.svd(b, full_matrices=False)
>>> u.shape, s.shape, vh.shape
((2, 7, 8, 3), (2, 7, 3), (2, 7, 3, 3))
>>> np.allclose(b, np.matmul(u * s[..., None, :], vh))
True
>>> np.allclose(b, np.matmul(u, s[..., None] * vh))
True
參考文獻(xiàn):
SVD(奇異值分解)到底在干什么 - 知乎
這次終于徹底理解了奇異值分解(SVD)原理及應(yīng)用
數(shù)據(jù)科學(xué)中需要知道的5個(gè)關(guān)于奇異值分解(SVD)的應(yīng)用
奇異值分解的物理意義_SilenceHell的博客-CSDN博客_奇異值分解的意義文章來源:http://www.zghlxwxcb.cn/news/detail-400953.html
奇異值分解的揭秘(一):矩陣的奇異值分解過程 - 知乎文章來源地址http://www.zghlxwxcb.cn/news/detail-400953.html
到了這里,關(guān)于奇異值分解(SVD)和np.linalg.svd()函數(shù)用法的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!