机器学习-降维之奇异值分解SVD算法原理及实战
生活随笔
收集整理的這篇文章主要介紹了
机器学习-降维之奇异值分解SVD算法原理及实战
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
奇異值分解
- 簡(jiǎn)介
- PCA是通過(guò)特征值分解來(lái)進(jìn)行特征提取的,但它要求矩陣必須是方陣,但在實(shí)際應(yīng)用場(chǎng)景中,經(jīng)常遇到的矩陣都不是方陣,如N個(gè)學(xué)生,每個(gè)學(xué)生有M門(mén)課程,其中N!=M, 這就組成了一個(gè)M*N的非方陣矩陣,這種情況下無(wú)法使用主成分分析,也限制了特征值分解方法的使用。而奇異值分解(SVD),是線性代數(shù)中重要的一種矩陣分解,該方法對(duì)矩陣的形狀沒(méi)有要求。
- 原理
- 在很多情況下,數(shù)據(jù)的一小段攜帶了數(shù)據(jù)集中大部分信息,而剩下的信息則要么是噪聲,要么是毫不相關(guān)的信息。利用SVD實(shí)現(xiàn),能夠用小得多的數(shù)據(jù)集來(lái)表示原始數(shù)據(jù)集。這樣做,實(shí)際上是去除了噪聲和冗余數(shù)據(jù)。同樣,當(dāng)用戶試圖節(jié)省空間時(shí),去除信息也是很有用的。
- 假設(shè)是一個(gè)階矩陣,則存在一個(gè)分解使得:Mm×n=Um×n∑m×nVn×nTM_{m \times n} = U_{m \times n} \sum_{m \times n} V_{n \times n}^T Mm×n?=Um×n?m×n∑?Vn×nT?
- 式子中,為m×mm\times mm×m階酉矩陣;∑\sum∑為半正定m×nm\times nm×n階對(duì)角矩陣;而VTV^TVT,即V的共軛轉(zhuǎn)置,是n*n階酉矩陣。這樣的分解就稱為M的奇異值分解。∑\sum∑對(duì)角線上的元素∑i\sum i∑i,其中i即為M的奇異值。常見(jiàn)的做法是奇異值從大到小排列。
- 奇異值的優(yōu)點(diǎn)是:可以簡(jiǎn)化數(shù)據(jù),壓縮維度,去除噪聲數(shù)據(jù),提升算法結(jié)果。加快模型計(jì)算性能,可以針對(duì)任一普通矩陣進(jìn)行分解(包括樣本數(shù)小于特征數(shù)),不受限于方陣。
- 奇異值的缺點(diǎn)是:轉(zhuǎn)化后的數(shù)據(jù)難以理解,如何與具體業(yè)務(wù)知識(shí)對(duì)應(yīng)起來(lái)是難點(diǎn)。
- 那么在解決實(shí)際問(wèn)題時(shí)如何知道保留多少個(gè)奇異值呢?
- 一個(gè)典型的做法就是保留矩陣中90%的能量信息。為了計(jì)算總能量信息,將所有的奇異值求其平方和。于是可以將奇異值的平方和累加到總值的90%為止。
- 實(shí)戰(zhàn)
- 使用奇異值分解進(jìn)行圖像壓縮
- u, sigma, v = np.linalg.svd(M)
- 其中u和v返回矩陣M的左右奇異向量,sigma返回奇異值從大到小排列的一個(gè)向量。
- 前置知識(shí)
- 一般彩色圖像就是RGB三個(gè)圖層上矩陣的疊加,每個(gè)元素值為0~255,plt可以直接讀取圖像,對(duì)三個(gè)圖層一一處理即可。
- SVD進(jìn)行壓縮步驟
- 讀取圖片,分解為RGB三個(gè)矩陣。
- 對(duì)三個(gè)矩陣分別進(jìn)行SVD分解,得到對(duì)應(yīng)的奇異值和奇異向量。
- 按照一定的標(biāo)準(zhǔn)進(jìn)行奇異值篩選(整體數(shù)量的一定百分比,或者奇異值和的一定百分比)。
- 恢復(fù)矩陣。
- 保存圖像。
- 代碼
- # -*-coding:utf-8-*-import numpy as npfrom matplotlib import pyplot as pltdef svdimage(filename, percent):"""讀取原始圖像數(shù)據(jù):param filename::param percent::return:"""original = plt.imread(filename) # 讀取圖像R0 = np.array(original[:, :, 0]) # 獲取第一層矩陣數(shù)據(jù)G0 = np.array(original[:, :, 1]) # 獲取第二層矩陣數(shù)據(jù)B0 = np.array(original[:, :, 2]) # 獲取第三層矩陣數(shù)據(jù)u0, sigma0, v0 = np.linalg.svd(R0) # 對(duì)第一層數(shù)據(jù)進(jìn)行SVD分解u1, sigma1, v1 = np.linalg.svd(G0) # 對(duì)第二層數(shù)據(jù)進(jìn)行SVD分解u2, sigma2, v2 = np.linalg.svd(B0) # 對(duì)第三層數(shù)據(jù)進(jìn)行SVD分解R1 = np.zeros(R0.shape)G1 = np.zeros(G0.shape)B1 = np.zeros(B0.shape)total0 = sum(sigma0)total1 = sum(sigma1)total2 = sum(sigma2)# 對(duì)三層矩陣逐一分解sd = 0for i, sigma in enumerate(sigma0): # 用奇異值總和的百分比來(lái)進(jìn)行篩選R1 += sigma * np.dot(u0[:, i].reshape(-1, 1), v0[i, :].reshape(1, -1))sd += sigmaif sd >= percent * total0:breaksd = 0for i, sigma in enumerate(sigma1): # 用奇異值總和的百分比來(lái)進(jìn)行篩選G1 += sigma * np.dot(u1[:, i].reshape(-1, 1), v1[i, :].reshape(1, -1))sd += sigmaif sd >= percent * total1:breaksd = 0for i, sigma in enumerate(sigma2): # 用奇異值總和的百分比來(lái)進(jìn)行篩選B1 += sigma * np.dot(u2[:, i].reshape(-1, 1), v2[i, :].reshape(1, -1))sd += sigmaif sd >= percent * total2:breakfinal = np.stack((R1, G1, B1), 2)final[final > 255] = 255final[final < 0] = 0final = np.rint(final).astype('uint8')return finalif __name__ == '__main__':filename = 'data/example.jpg'for p in np.arange(.1, 1, .1):print('percent is {}'.format(p))after = svdimage(filename, p)plt.imsave('data/' + str(p) + '_1.jpg', after)
- 運(yùn)行效果(不同壓縮比下)
- 補(bǔ)充說(shuō)明
- 參考書(shū)為《Python3數(shù)據(jù)分析與機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》,對(duì)部分錯(cuò)誤修改
- 具體數(shù)據(jù)集和代碼見(jiàn)我的Github,歡迎Star或者Fork
總結(jié)
以上是生活随笔為你收集整理的机器学习-降维之奇异值分解SVD算法原理及实战的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 机器学习-降维之主成分分析PCA算法原理
- 下一篇: 机器学习-聚类之K均值(K-means)