機器學習中常用的降維方法是主成分分析(PCA),而主成分分析常用奇異值分解(SVD)。那么SVD的效果到底如何呢?SVD常用來進行圖像的壓縮,我們就來實驗一下。
用到的包:
PIL
numpy
實驗
載入一張彩色圖片,分別對其RGB通道進行SVD分解。奇異值的占比公式為:
分別取和占比為[0.1, 0.2, …, 0.9]的前K個奇異值,進行圖片的恢復操作。
from PIL import Image
import numpy as np
def rebuild_img(u, sigma, v, p): #p表示奇異值的百分比
print p
m = len(u)
n = len(v)
a = np.zeros((m, n))
count = (int)(sum(sigma))
curSum = 0
k = 0
while curSum <= count * p:
uk = u[:, k].reshape(m, 1)
vk = v[k].reshape(1, n)
a += sigma[k] * np.dot(uk, vk)
curSum += sigma[k]
k += 1
print 'k:',k
a[a < 0] = 0
a[a > 255] = 255
#按照最近距離取整數(shù),并設置參數(shù)類型為uint8
return np.rint(a).astype("uint8")
if __name__ == '__main__':
img = Image.open('test.jpg', 'r')
a = np.array(img)
for p in np.arange(0.1, 1, 0.1):
u, sigma, v = np.linalg.svd(a[:, :, 0])
R = rebuild_img(u, sigma, v, p)
u, sigma, v = np.linalg.svd(a[:, :, 1])
G = rebuild_img(u, sigma, v, p)
u, sigma, v = np.linalg.svd(a[:, :, 2])
B = rebuild_img(u, sigma, v, p)
I = np.stack((R, G, B), 2)
#保存圖片在img文件夾下
Image.fromarray(I).save("img\svd_" + str(p * 100) + ".jpg")
效果
一共10張圖,從上到下奇異值和占比為[0.1, 0.2, …, 0.9, 1.0],奇異值和占比[0.7, 0.8, 0.9]的恢復圖像還是比較清楚,然而對應的奇異值個數(shù)卻非常少,如下表所示:
奇異值和占比 奇異值個數(shù) 奇異值個數(shù)占比
0.7 ? 45 ? 0.10 ?
0.8 ? 73 ? 0.16 ?
0.9 ? 149 ? 0.33 ?
1.0 ? 450 ? 1.00
?
小結(jié)
奇異值分解能夠有效的降低數(shù)據(jù)的維數(shù),以本文的圖片為例,從450維降到149維后,還保留了90%的信息
雖然奇異值分解很有效,但是不能濫用,一般情況下要求降維后信息的損失度不能超過5%,甚至是1%
Ng的視頻中提到常見的錯誤使用降維的情況,在這里也貼出來:
使用降維解決過擬合問題
不論什么情況,先用降維處理一下數(shù)據(jù),即把降維當做模型訓練的必須步驟
評論
查看更多