1. 程式人生 > >降維方法:PCA&SVD

降維方法:PCA&SVD

個人覺得關於PCA(主成分分析)和SVD(矩陣奇異值分解)兩篇不錯的部落格:

簡單來說:PCA是將高維資料在低維方向上投影從而達到降維的目的,SVD是將矩陣分解為低維矩陣的乘積。

兩者都是建立在矩陣的這一基石上,即:Ax=x。

1)PCA具體過程如下:

假設有一組資料{(xi,yi)|i=1,2,3....}

為這組資料得到協方差矩陣

A降維以後為B,則B=rA

r為X最大的特徵值對應的特徵向量.

2)SVD具體過程如下:

假設有矩陣A

矩陣A的SVD分解如下:A=U*S*V其中:U=的特徵向量構成的矩陣V=的特徵向量構成的矩陣S=的特徵值開根構成的矩陣

下面看一個直觀的例子,你會切身發現SVD的神奇之處:

>>> import numpy as np
>>> A=np.random.randint(0,10,size=[5,4])
>>> A
array([[1, 1, 1, 2],
       [5, 9, 9, 7],
       [3, 9, 6, 5],
       [7, 1, 6, 5],

       [0, 8, 4, 4]])

>>> from numpy import linalg as la
>>> U,S,V=la.svd(A)
>>> U
array([[-0.10392588,  0.0687753 ,  0.81642429,  0.20828833, -0.52396252],
       [-0.65996272,  0.04593935, -0.20733647, -0.58621402, -0.41917001],
       [-0.52059928, -0.26035621, -0.30230549,  0.74754328, -0.1047925 ],
       [-0.36667027,  0.81085029,  0.11978263,  0.13425103,  0.41917001],
       [-0.38493886, -0.51758669,  0.42979818, -0.19006526,  0.60255689]])
>>> S
array([23.25896126,  7.62618526,  1.13390704,  0.75912737])
>>> V
array([[-0.32384203, -0.60944962, -0.55492431, -0.46449598],
       [ 0.68098994, -0.68065743,  0.22486304,  0.14964883],
       [-0.254603  , -0.18712759, -0.3752939 ,  0.87138687],

       [ 0.60543897,  0.36091535, -0.70756633, -0.05033531]])

取S的前4列重構為S1

>>> S1=np.eye(len(S))*S
>>> S1
array([[23.25896126,  0.        ,  0.        ,  0.        ],
       [ 0.        ,  7.62618526,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  1.13390704,  0.        ],

       [ 0.        ,  0.        ,  0.        ,  0.75912737]])

>>> a=np.dot(U[:,:4],S1)

由S的前4列最終生成的B(與原始矩陣A基本一樣)

>>> B=np.dot(a,V)
>>> B
array([[ 1.000000e+00,  1.000000e+00,  1.000000e+00,  2.000000e+00],
       [ 5.000000e+00,  9.000000e+00,  9.000000e+00,  7.000000e+00],
       [ 3.000000e+00,  9.000000e+00,  6.000000e+00,  5.000000e+00],
       [ 7.000000e+00,  1.000000e+00,  6.000000e+00,  5.000000e+00],

       [-8.491496e-16,  8.000000e+00,  4.000000e+00,  4.000000e+00]])

作為對比,取S的前兩列重構為S2

>>> S2=np.eye(2)*S[:2]
>>> S2
array([[23.25896126,  0.        ],

       [ 0.        ,  7.62618526]])

由S的前兩列生成矩陣B2(B2與A相比資訊有所丟失,但仍然保留的大部分資訊)

>>> a1=np.dot(U[:,:2],S2)

>>> B2=np.dot(a1,V[:2,:])
>>> B2
array([[1.13996811, 1.11616623, 1.45930657, 1.20127315],
       [5.20956983, 9.11661759, 8.59689342, 7.18246353],
       [2.56915072, 8.73104277, 6.27288452, 5.32726381],
       [6.9728783 , 0.98863392, 6.12308396, 4.88677603],
       [0.21143607, 8.14327107, 4.08080961, 3.56806601]])