矩陣分解之:主成分分析(PCA)

本文是在參考主成分分析(PCA)原理詳解 的基礎上 添加一些自己的理解。

1.相關背景

在許多領域的研究與應用中,通常需要對含有多個變量的數據進行觀測,收集大量數據後進行分析尋找規律。多變量大數據集無疑會爲研究和應用提供豐富的信息,但是也在一定程度上增加了數據採集的工作量。更重要的是在很多情形下,許多變量之間可能存在相關性,從而增加了問題分析的複雜性。如果分別對每個指標進行分析,分析往往是孤立的,不能完全利用數據中的信息,因此盲目減少指標會損失很多有用的信息,從而產生錯誤的結論。

因此需要找到一種合理的方法,在減少需要分析的指標同時,儘量減少原指標包含信息的損失,以達到對所收集數據進行全面分析的目的。由於各變量之間存在一定的相關關係,因此可以考慮將關係緊密的變量變成儘可能少的新變量,使這些新變量是兩兩不相關的,那麼就可以用較少的綜合指標分別代表存在於各個變量中的各類信息。主成分分析與因子分析就屬於這類降維算法。
 

2. 數據降維

降維就是一種對高維度特徵數據預處理方法。降維是將高維度的數據保留下最重要的一些特徵,去除噪聲和不重要的特徵,從而實現提升數據處理速度的目的。在實際的生產和應用中,降維在一定的信息損失範圍內,可以爲我們節省大量的時間和成本。降維也成爲應用非常廣泛的數據預處理方法。

降維具有如下一些優點

1) 使得數據集更易使用。
2) 降低算法的計算開銷。
3) 去除噪聲。
4) 使得結果容易理解。
降維的算法有很多,比如奇異值分解(SVD)、主成分分析(PCA)、因子分析(FA)、獨立成分分析(ICA)。

3. PCA原理詳解

3.1 PCA的概念

PCA(Principal Component Analysis),即主成分分析方法,是一種使用最廣泛的數據降維算法。PCA的主要思想是將n維特徵映射到k維上,這k維是全新的正交特徵也被稱爲主成分,是在原有n維特徵的基礎上重新構造出來的k維特徵。PCA的工作就是從原始的空間中順序地找一組相互正交的座標軸,新的座標軸的選擇與數據本身是密切相關的。其中,第一個新座標軸選擇是原始數據中方差最大的方向,第二個新座標軸選取是與第一個座標軸正交的平面中使得方差最大的,第三個軸是與第1,2個軸正交的平面中方差最大的。依次類推,可以得到n個這樣的座標軸。通過這種方式獲得的新的座標軸,我們發現,大部分方差都包含在前面k個座標軸中,後面的座標軸所含的方差幾乎爲0。於是,我們可以忽略餘下的座標軸,只保留前面k個含有絕大部分方差的座標軸。事實上,這相當於只保留包含絕大部分方差的維度特徵,而忽略包含方差幾乎爲0的特徵維度,實現對數據特徵的降維處理。

思考:我們如何得到這些包含最大差異性的主成分方向呢?

答案:事實上,通過計算數據矩陣的協方差矩陣,然後得到協方差矩陣的特徵值特徵向量,選擇特徵值最大(即方差最大)的k個特徵所對應的特徵向量組成的矩陣。這樣就可以將數據矩陣轉換到新的空間當中,實現數據特徵的降維。

由於得到協方差矩陣的特徵值特徵向量有兩種方法:特徵值分解協方差矩陣、奇異值分解協方差矩陣,所以PCA算法有兩種實現方法:基於特徵值分解協方差矩陣實現PCA算法、基於SVD分解協方差矩陣實現PCA算法

既然提到協方差矩陣,那麼就簡單介紹一下方差和協方差的關係。然後概括介紹一下特徵值分解矩陣原理、奇異值分解矩陣的原理。概括介紹是因爲在我之前的《矩陣分解之: 特徵值分解(EVD)、奇異值分解(SVD》文章中已經詳細介紹了特徵值分解原理和奇異值分解原理,這裏就不再重複講解了。

3.2 協方差和散度矩陣

樣本均值:

樣本方差:

樣本X和樣本Y的協方差:

由上面的公式,我們可以得到以下結論:

(1) 方差的計算公式是針對一維特徵,即針對同一特徵不同樣本的取值來進行計算得到;而協方差則必須要求至少滿足二維特徵;方差是協方差的特殊情況。

(2) 方差和協方差的除數是n-1,這是爲了得到方差和協方差的無偏估計。

協方差爲正時,說明X和Y是正相關關係;協方差爲負時,說明X和Y是負相關關係;協方差爲0時,說明X和Y是相互獨立。Cov(X,X)就是X的方差。當樣本是n維數據時,它們的協方差實際上是協方差矩陣(對稱方陣)。例如,對於3維數據(x,y,z),計算它的協方差就是:

散度矩陣定義爲:

對於數據X的散度矩陣爲。其實協方差矩陣和散度矩陣關係密切,散度矩陣就是協方差矩陣乘以(總數據量-1)。因此它們的特徵值和特徵向量是一樣的。這裏值得注意的是,散度矩陣是SVD奇異值分解的一步,因此PCA和SVD是有很大聯繫。

3.3 特徵值分解矩陣原理

(1) 特徵值與特徵向量

如果一個向量v是矩陣A的特徵向量,將一定可以表示成下面的形式:


其中,λ是特徵向量v對應的特徵值,一個矩陣的一組特徵向量是一組正交向量。
(2) 特徵值分解矩陣

對於矩陣A,有一組特徵向量v,將這組向量進行正交化單位化,就能得到一組正交單位向量。特徵值分解,就是將矩陣A分解爲如下式:

其中,Q是矩陣A的特徵向量組成的矩陣,則是一個對角陣,對角線上的元素就是特徵值。

具體瞭解這一部分內容看我的《機器學習中SVD總結》文章。地址:機器學習中SVD總結

3.4 SVD分解矩陣原理

奇異值分解是一個能適用於任意矩陣的一種分解的方法,對於任意矩陣A總是存在一個奇異值分解:

假設A是一個m*n的矩陣,那麼得到的U是一個m*m的方陣,U裏面的正交向量被稱爲左奇異向量。Σ是一個m*n的矩陣,Σ除了對角線其它元素都爲0,對角線上的元素稱爲奇異值。是v的轉置矩陣,是一個n*n的矩陣,它裏面的正交向量被稱爲右奇異值向量。而且一般來講,我們會將Σ上的值按從大到小的順序排列。

SVD分解矩陣A的步驟:

(1) 求AA^{T}的特徵值和特徵向量,用單位化的特徵向量構成 U。

(2) 求A^{T}A的特徵值和特徵向量,用單位化的特徵向量構成 V。

(3) 將AA^{T}或者A^{T}A的特徵值求平方根,然後構成 Σ。

3.5 PCA算法兩種實現方法

(1) 基於特徵值分解 協方差矩陣 實現PCA算法
輸入:數據集,需要降到k維。
1) 去平均值(即去中心化),即每一位特徵減去各自的平均值。

2) 計算協方差矩陣 , 注:這裏除或不除樣本數量n或n-1,其實對求出的特徵向量沒有影響。

3) 用特徵值分解方法求協方差矩陣的特徵值與特徵向量。

4) 對特徵值從大到小排序,選擇其中最大的k個。然後將其對應的k個特徵向量分別作爲行向量組成特徵向量矩陣P。

5) 將數據轉換到k個特徵向量構建的新空間中,即Y=PX。

總結:

1)關於這一部分爲什麼用,這裏面含有很複雜的線性代數理論推導,想了解具體細節的可以看下面這篇文章。
CodingLabs - PCA的數學原理

2)關於爲什麼用特徵值分解矩陣,是因爲是方陣,能很輕鬆的求出特徵值與特徵向量。當然,用奇異值分解也可以,是求特徵值與特徵向量的另一種方法。

舉個例子:


以X爲例,我們用PCA方法將這兩行數據降到一行。

1)因爲X矩陣的每行已經是零均值,所以不需要去平均值。

2)求協方差矩陣:

3)求協方差矩陣的特徵值與特徵向量。

求解後的特徵值爲:

對應的特徵向量爲:

其中對應的特徵向量分別是一個通解,和可以取任意實數。那麼標準化後的特徵向量爲:

4)矩陣P爲:

5)最後我們用P的第一行乘以數據矩陣X,就得到了降維後的表示:

結果如圖1所示:

圖1:數據矩陣X降維投影結果

 注意:如果我們通過特徵值分解協方差矩陣,那麼我們只能得到一個方向的PCA降維。這個方向就是對數據矩陣X從行(或列)方向上壓縮降維。

(2) 基於SVD分解協方差矩陣實現PCA算法
輸入:數據集,需要降到k維。

1) 去平均值,即每一位特徵減去各自的平均值。

2) 計算協方差矩陣。

3) 通過SVD計算協方差矩陣的特徵值與特徵向量。

4) 對特徵值從大到小排序,選擇其中最大的k個。然後將其對應的k個特徵向量分別作爲列向量組成特徵向量矩陣。

5) 將數據轉換到k個特徵向量構建的新空間中。

在PCA降維中,我們需要找到樣本協方差矩陣的最大k個特徵向量,然後用這最大的k個特徵向量組成的矩陣來做低維投影降維。可以看出,在這個過程中需要先求出協方差矩陣,當樣本數多、樣本特徵數也多的時候,這個計算還是很大的。當我們用到SVD分解協方差矩陣的時候,SVD有兩個好處

(1) 有一些SVD的實現算法可以先不求出協方差矩陣也能求出我們的右奇異矩陣V。也就是說,我們的PCA算法可以不用做特徵分解而是通過SVD來完成,這個方法在樣本量很大的時候很有效。實際上,scikit-learn的PCA算法的背後真正的實現就是用的SVD,而不是特徵值分解。

(2) 注意到PCA僅僅使用了我們SVD的左奇異矩陣,沒有使用到右奇異值矩陣,那麼右奇異值矩陣有什麼用呢?

假設我們的樣本是m*n的矩陣X,如果我們通過SVD找到了矩陣最大的k個特徵向量組成的k*n的矩陣, 則我們可以做如下處理:

可以得到一個m*k的矩陣X',這個矩陣和我們原來m*n的矩陣X相比,列數從n減到了k,可見對列數進行了壓縮。也就是說,左奇異矩陣可以用於對行數的壓縮;右奇異矩陣可以用於對列(即特徵維度)的壓縮這就是我們用SVD分解協方差矩陣實現PCA可以得到兩個方向的PCA降維(即行和列兩個方向)。

4. PCA實例

(1)PCA的Python實現:

##Python實現PCA
import numpy as np
def pca(X,k):#k is the components you want
  #mean of each feature
  n_samples, n_features = X.shape
  mean=np.array([np.mean(X[:,i]) for i in range(n_features)])
  #normalization
  norm_X=X-mean
  #scatter matrix
  scatter_matrix=np.dot(np.transpose(norm_X),norm_X)
  #Calculate the eigenvectors and eigenvalues
  eig_val, eig_vec = np.linalg.eig(scatter_matrix)
  eig_pairs = [(np.abs(eig_val[i]), eig_vec[:,i]) for i in range(n_features)]
  # sort eig_vec based on eig_val from highest to lowest
  eig_pairs.sort(reverse=True)
  # select the top k eig_vec
  feature=np.array([ele[1] for ele in eig_pairs[:k]])
  #get new data
  data=np.dot(norm_X,np.transpose(feature))
  return data
 
X = np.array([[-1, 1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
 
print(pca(X,1))


上面代碼實現了對數據X進行特徵的降維。結果如下:

(2)用sklearn的PCA與我們的PCA做個比較:

##用sklearn的PCA
from sklearn.decomposition import PCA
import numpy as np
X = np.array([[-1, 1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
pca=PCA(n_components=1)pca.fit(X)
print(pca.transform(X))

結果如下:

搞了半天結果不是很一樣啊!分析一下吧!

sklearn中的PCA是通過svd_flip函數實現的,sklearn對奇異值分解結果進行了一個處理,因爲ui*σi*vi=(-ui)*σi*(-vi),也就是u和v同時取反得到的結果是一樣的,而這會導致通過PCA降維得到不一樣的結果(雖然都是正確的)。具體瞭解可以看參考文章9或者自己分析一下sklearn中關於PCA的源碼。

5. PCA的理論推導

PCA有兩種通俗易懂的解釋:(1)最大方差理論;(2)最小化降維造成的損失。這兩個思路都能推導出同樣的結果。

我在這裏只介紹最大方差理論:

在信號處理中認爲信號具有較大的方差,噪聲有較小的方差,信噪比就是信號與噪聲的方差比,越大越好。樣本在u1上的投影方差較大,在u2上的投影方差較小,那麼可認爲u2上的投影是由噪聲引起的。

因此我們認爲,最好的k維特徵是將n維樣本點轉換爲k維後,每一維上的樣本方差都很大。

比如我們將下圖中的5個點投影到某一維上,這裏用一條過原點的直線表示(數據已經中心化):

假設我們選擇兩條不同的直線做投影,那麼左右兩條中哪個好呢?根據我們之前的方差最大化理論,左邊的好,因爲投影后的樣本點之間方差最大(也可以說是投影的絕對值之和最大)。

計算投影的方法見下圖:

圖中,紅色點表示樣例,藍色點表示在u上的投影,u是直線的斜率也是直線的方向向量,而且是單位向量。藍色點是在u上的投影點,離原點的距離是<x,u>(即或者)。

6. 選擇降維後的維度K(主成分的個數)
如何選擇主成分個數K呢?先來定義兩個概念:

選擇不同的K值,然後用下面的式子不斷計算,選取能夠滿足下列式子條件的最小K值即可。

其中t值可以由自己定,比如t值取0.01,則代表了該PCA算法保留了99%的主要信息。當你覺得誤差需要更小,你可以把t值設置的更小。上式還可以用SVD分解時產生的S矩陣來表示,如下面的式子:

Reference:

(1) 主成分分析(PCA)原理詳解

http://blog.csdn.net/zhongkelee/article/details/44064401

(2) 機器學習之PCA主成分分析 - steed灬 - 博客園

https://www.cnblogs.com/steed/p/7454329.html

(3) 簡單易學的機器學習算法——主成分分析(PCA)

https://blog.csdn.net/google19890102/article/details/27969459

(4) 機器學習實戰之PCA - 笨鳥多學 - 博客園

https://www.cnblogs.com/zy230530/p/7074215.html

(5) 機器學習中的數學(5)-強大的矩陣奇異值分解(SVD)及其應用 - LeftNotEasy - 博客園

http://www.cnblogs.com/LeftNotEasy/archive/2011/01/19/svd-and-applications.html

(6) 從PCA和SVD的關係拾遺

https://blog.csdn.net/Dark_Scope/article/details/53150883

(7) CodingLabs - PCA的數學原理

http://blog.codinglabs.org/articles/pca-tutorial.html

(8) PCA(主成分分析)python實現

https://www.jianshu.com/p/4528aaa6dc48

(9) 主成分分析PCA(Principal Component Analysis)在sklearn中的應用及部分源碼分析

https://www.cnblogs.com/lochan/p/7001907.html

 

發佈了120 篇原創文章 · 獲贊 134 · 訪問量 60萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章