本篇整理了一些SVD奇異值分解在機器學習中的應用:
- SVD奇異值分解
- SVD在推薦算法中的應用
- PCD 數據降維
- 一個圖片處理的例子
SVD奇異值分解
講svd之前,先了解一下特征向理和特征值的概念。
對於一個方陣M,如果有向量v 和 數值 λ ,Mv = λv,則 v 稱為 M 的對應於特征值 λ 的特征向量。
特征分解: 方陣M可以被分解為 M =Q∗Λ∗Q−1 Q∗Λ∗Q−1Q∗Λ∗Q−1
其中Q 是N×N方陣,由特征向量組成的矩陣,且其第 i 列為 M 的第i個特征向量 。 Λ 是對角矩陣,其對角線上的元素為對應的特征值。
SVD奇異值分解和特征分解很像,區別就是此時Data 是一個m * n的矩陣,不是方陣。
矩陣Data可被分解為三個矩陣
Σ
和VT
就分別是m* m、m*n和n*n。Σ
為對角矩陣,對角元素稱為奇異值。
SVD 和 特征分解的關系:
Data * DataT
是個方陣,特征分解可得 Data *
Data
T
= U mxm *
Σ
1* U
T
mxm
Data
T
* Data
是個方陣,特征分解可得
= V nxn Data
T
* Data
*
Σ
2* VT
nxn
svd 分解中
U mxm 就是
Data * DataT
的特征向量,V nxn 就是
Data
T
* Data
的特征向量,
Σ
為 Data * DataT
特征值
的平方根。Σ
1
SVD的幾個特性
1:取特征值的前K個項,可以近似的表示矩陣Data。
2:取特征值的前k項,Vnxk可以表示為
SVD在推薦算法中的應用
在推薦算法中,根據用戶和用戶之間的相似度,就可以向用戶推薦另一個用戶沒有選擇的物品。
根據物品和物品之間的相似度,就可以向選擇該物品的用戶推薦另一種物品。相似度計算有 《歐氏距離》,《皮爾遜相關系數》,《余弦相似度》等一系列算法。
在實際的應用中,由於商品和人的數量比較多,相似度計算的復雜度比較高,推薦效果可能也不好。
更先進的方法利用SVD從數據中構建一個低維的空間,然后再在該
低維
空間下計算其相似度。
假設有一個矩陣,列表示用戶 ,行表示商品。由此主成了一個矩陣,矩陣的值表示該用戶對商品的評分,0表示未評分。
對該矩陣svd 分解以后
U =
-0.4472 -0.5373 -0.0064 -0.5037 -0.3857 -0.3298 -0.3586 0.2461 0.8622 -0.1458 0.0780 0.2002 -0.2925 -0.4033 -0.2275 -0.1038 0.4360 0.7065 -0.2078 0.6700 -0.3951 -0.5888 0.0260 0.0667 -0.5099 0.0597 -0.1097 0.2869 0.5946 -0.5371 -0.5316 0.1887 -0.1914 0.5341 -0.5485 0.2429
S =
17.7139 0 0 0 0 6.3917 0 0 0 0 3.0980 0 0 0 0 1.3290 0 0 0 0 0 0 0 0
V =
-0.5710 -0.2228 0.6749 0.4109 -0.4275 -0.5172 -0.6929 0.2637 -0.3846 0.8246 -0.2532 0.3286 -0.5859 0.0532 0.0140 -0.8085
矩陣 U 的每一行,反映的是每一個商品的特征。矩陣 V 的每一行,反映的是每一個用戶的特征。
保留2個維度的的特征,再對三個矩陣相乘。可以得到原始近似值
U(1:6,1:2) * S(1:2,1:2) * V(1:4,1:2)'
得到的新矩陣
和原始矩陣相似。
這個就是前面提到的svd特性1,但這個不是我們在推薦系統中要用到的特性,接下來的圖片處理的例子將用到這個特性。
5.2885 5.1627 0.2149 4.4591 3.2768 1.9021 3.7400 3.8058 3.5324 3.5479 -0.1332 2.8984 1.1475 -0.6417 4.9472 2.3846 5.0727 3.6640 3.7887 5.3130 5.1086 3.4019 4.6166 5.5822
為了更形象的描述 特征 矩陣能反映出商品和用戶 的特征。把前面保留2個維度的 U,V 矩陣列 表示在 一張二維圖上。
從圖中Ben 和 Fred 在差不多的位置上, 對比原始矩陣 Ben 和 Fred的評分數據也是比較相似。
s5,s6 也在差不多的位置上,對比原始矩陣它們的評分也基本相近。
所以,保留2個維度的特征,同樣可以反映出原始數據的基本特性。利用這個思想,取前K個維度的特征進行相似度計算可以大大的減少運算復雜度。(K 值怎么定?一個典型的做法就是計算出保留矩陣中90%的能量信息所需要的K值。這里不作進述)
假設一個新用戶bob ,他的評分數據為[5,5,0,0,0,5]。我們現在要對他作出個性推薦。利用前面的svd特性2,計算出bob 用戶特征 Vbob。
標進原來的坐標圖,
根據《余弦相似度》計算的話——看夾角,應該是和ben最相似。
觀察ben的評分向量為:【5 5 3 0 5 5】。
對比Bob的評分向量:【5 5 0 0 0 5】。
然后找出ben評分過而Bob未評分的item,並按分值排序,即可推薦【season 5,season 3】。
這個就是基於用戶推薦的思想。當然也可以使用 U,來計算基於商品的推薦。
svd 在里面的關鍵作用是:
1:自動幫我們划分出基於用戶 的特征,和基於商品的特征。
2:在上面的基礎上,選取一個維度K。使用我們可以在一個低維空間下計算相似度,降低運算復雜度。
PCA 數據降維
Principal Component Analysis 主成份分析,這個是機器學習常用的數據降維方法。
為什么要數據降維?在機器學習的算法訓練中,我們可能有大量的冗余的特征。這些特征不一定要訓練中能起到很好的作用,相反可能在存儲成本和計算量上都比較大。
pca 的作用就是保留主要的特征維度,去掉不必要的特征,更加有效的提高和優化我們的學習算法。
這個篇幅,則以吳恩達機器學習公開課中 一個圖片pca的例子來介紹。
pca算法原理
假設現在一個二維的訓練數據,打印出來是圖中的效果。如果想找出一條線來反映這些數據的最主要形態,那就是紅的標記這個方向。
如果所有的數據,往這個方向上投影,那么產生一個一維的數據,如右圖的紅點,它能反映出訓練數據的最主要形態,訓練樣本之間有最大方差。此時的訓練數據的特征更明顯。
如果是另一方向,所有的數據將會擠在一起,方差變的最小,不能反映訓練數據的主要特征。
訓練數據會有多維的特征,如果分別向多個主要特征的方向上投影,最終將得一個低維度的訓練數據集。在這個低維度的訓練數據集中,特征更加精准。
這就是pca的思想。
那么,如果找出主要的特征方向呢。訓練數據的 協方差矩陣 的特征向量就是我們要找的特征方向。
PCA 算法步驟,octave 代碼
先展示100張人臉,訓練數據是32*32的灰度圖片
displayData(X(1:100, :));
1:訓練數據處理,歸一化。
[X_norm, mu, sigma] = featureNormalize(X);
function [X_norm, mu, sigma] = featureNormalize(X) %FEATURENORMALIZE Normalizes the features in X % FEATURENORMALIZE(X) returns a normalized version of X where % the mean value of each feature is 0 and the standard deviation % is 1. This is often a good preprocessing step to do when % working with learning algorithms. mu = mean(X); X_norm = bsxfun(@minus, X, mu); sigma = std(X_norm); X_norm = bsxfun(@rdivide, X_norm, sigma); % ============================================================ end
2:計算協方差矩陣,計算協方差矩陣的特征值
[U, S] = pca(X_norm);
function [U, S] = pca(X) %PCA Run principal component analysis on the dataset X % [U, S, X] = pca(X) computes eigenvectors of the covariance matrix of X % Returns the eigenvectors U, the eigenvalues (on diagonal) in S % % Useful values [m, n] = size(X); % You need to return the following variables correctly. U = zeros(n); S = zeros(n); % ====================== YOUR CODE HERE ====================== % Instructions: You should first compute the covariance matrix. Then, you % should use the "svd" function to compute the eigenvectors % and eigenvalues of the covariance matrix. % % Note: When computing the covariance matrix, remember to divide by m (the % number of examples). % Sigma = (1/m) *(X'*X); [U, S, V] = svd(Sigma); % ========================================================================= end
注:這里用的協方差矩陣求的svd ,根據前面講的svd和特征分解的關系,其實可以直接用X_norm 求svd 得到 V 即為協方差矩陣svd 的U。
展示一下前面求的均值mu,一張大眾臉。我靠。
展示下特征U,每張都一個臉輪廓。
displayData(U(:, 1:36)');
3:選取K個維度的特征進行PCA降維。K的選取有公式,這里不闡述。
K = 100;
Z = projectData(X_norm, U, K)
function Z = projectData(X, U, K) %PROJECTDATA Computes the reduced data representation when projecting only %on to the top k eigenvectors % Z = projectData(X, U, K) computes the projection of % the normalized inputs X into the reduced dimensional space spanned by % the first K columns of U. It returns the projected examples in Z. % % You need to return the following variables correctly. Z = zeros(size(X, 1), K); % ====================== YOUR CODE HERE ====================== % Instructions: Compute the projection of the data using only the top K % eigenvectors in U (first K columns). % For the i-th example X(i,:), the projection on to the k-th % eigenvector is given as follows: % x = X(i, :)'; % projection_k = x' * U(:, k); % Z = X*U(:,1:K); % ============================================================= end
展示降維的效果,黑黑一片。原來的圖片是32*32像素值,現在只有100像素值。
displayData(Z(1:100,:));
4:復原圖片
K = 100; X_rec = recoverData(Z, U, K);
function X_rec = recoverData(Z, U, K) %RECOVERDATA Recovers an approximation of the original data when using the %projected data % X_rec = RECOVERDATA(Z, U, K) recovers an approximation the % original data that has been reduced to K dimensions. It returns the % approximate reconstruction in X_rec. % % You need to return the following variables correctly. X_rec = zeros(size(Z, 1), size(U, 1)); % ====================== YOUR CODE HERE ====================== % Instructions: Compute the approximation of the data by projecting back % onto the original space using the top K eigenvectors in U. % % For the i-th example Z(i,:), the (approximate) % recovered data for dimension j is given as follows: % v = Z(i, :)'; % recovered_j = v' * U(j, 1:K)'; % % Notice that U(j, 1:K) is a row vector. % X_rec = Z*(U(:,1:K)'); % ============================================================= end
復原后的效果,是不是看上去沒什么區別。
% Display normalized data subplot(1, 2, 1); displayData(X_norm(1:100,:));
一個圖片處理的例子
前面提到的 svd 的第一個特性,取特征值的前K個項,可以近似的表示矩陣Data:
那么,近似矩陣相對於原始矩陣丟失的部分是什么 ? 其實丟失這部分是一些無關信息,利用這點可以達到降噪的效果。
用一個圖片處理的例子,能很好的說明這一點。
上一張美女圖片
可以看到臉蛋中心有個小黑斑。接下來,用對這個圖片svd分解。然后取某個維度的特征進行還原。
python 代碼
# -*- coding:utf-8 -*- from numpy import linalg, mat, dot, eye from PIL import Image def main(num=5): im = Image.open('d:\\s1.jpg') box = (0, 0, im.size[0], im.size[1]) imcopy = im.crop(box) pix = imcopy.load() ma = [[], [], []] num= int(im.size[1]*1/6) for i in xrange(3): for x in xrange(im.size[0]): ma[i].append([]) for y in xrange(im.size[1]): ma[i][-1].append(pix[x, y][i]) for i in xrange(3): u, s, v = linalg.svd(ma[i]) s2 =mat(eye(num)*s[:num]) ma[i]=u[:, :num]*s2*v[:num, :] for x in xrange(im.size[0]): for y in xrange(im.size[1]): ret = [] for i in xrange(3): tmp = int(ma[i][x,y]) if tmp < 0: tmp = 0 if tmp > 255: tmp = 255 ret.append(tmp) pix[x, y] = tuple(ret) imcopy.show() # imcopy.save('d:\\s2.jpg') if __name__ == '__main__': main()
還原后效果,可以發現臉蛋中心有個小黑斑不見了。是不是起到了降噪的效果。
參考學習的鏈接
http://www.isnowfy.com/introduction-to-svd-and-lsa/
http://blog.csdn.net/redline2005/article/details/24100293
http://blog.csdn.net/moodytong/article/details/10085215
https://share.coursera.org/wiki/index.php/ML:Dimensionality_Reduction