矩陣SVD在機器學習中的應用


本篇整理了一些SVD奇異值分解在機器學習中的應用:

  • SVD奇異值分解
  • SVD在推薦算法中的應用
  • PCD 數據降維
  • 一個圖片處理的例子

SVD奇異值分解

講svd之前,先了解一下特征向理和特征值的概念。

對於一個方陣M,如果有向量v 和 數值 λ ,Mv = λv,則 v 稱為 M 的對應於特征值 λ 的特征向量。

 

特征分解: 方陣M可以被分解為 M =Q∗Λ∗Q−1 QΛQ1QΛQ1

其中QN×N方陣,由特征向量組成的矩陣,且其第 i 列為 M 的第i個特征向量 。 Λ 是對角矩陣,其對角線上的元素為對應的特征值。

 

SVD奇異值分解和特征分解很像,區別就是此時Data 是一個m * n的矩陣,不是方陣。

矩陣Data可被分解為三個矩陣

  ΣVT就分別是m* m、m*n和n*n。Σ為對角矩陣,對角元素稱為奇異值。

SVD特征分解的關系:

Data * DataT 是個方陣,特征分解可得  Data * DataT  = U mxm *Σ1* UT mxm 

DataT * Data  是個方陣,特征分解可得 DataT * Data = V nxn *Σ2* VTnxn

svd 分解中 U mxm 就是Data * DataT 的特征向量,V nxn 就是DataT * 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM