主成分分析 —PCA


一.定義

  主成分分析(principal components analysis)是一種無監督的降維算法,一般在應用其他算法前使用,廣泛應用於數據預處理中。其在保證損失少量信息的前提下,把多個指標轉化為幾個綜合指標的多元統計方法。這樣可達到簡化數據結構,提高分信息效率的目的。
  通常,把轉化生成的綜合指標稱為主成分,其中每個成分都是原始變量的線性組合,且每個主成分之間互不相關,使得主成分比原始變量具有某些更優越的性能。
  一般,經主成分分析分析得到的主成分與原始變量之間的關系有:

  • (1)每個主成分都是各原始變量的線性組合
  • (2)主成分的數目大大騷魚原始變量的數目
  • (3)主成分保留了原始變量的絕大多數信息
  • (4)各主成分之間互不相關

二.過程

  其過程是對坐標系旋轉的過程,各主成分表達式就是新坐標系與原坐標系的轉換關系,在新坐標系中,各坐標軸的方向就是原始數據變差最大的方向。(參見《多元統計分析》P114-117,新坐標軸Y1和Y2,用X1和X2的線性組合表示,幾何上是將坐標軸按逆時針方向旋轉一定的角度而得出)
  詳細版:數據從原來的坐標系轉換到新的坐標系。轉換坐標系時,以方差最大的方向作為新坐標軸方向(數據的最大方差給出了數據的最重要的信息)。第一個新坐標軸選擇的是原始數據中方差最大的方法,第二個新坐標軸選擇的是與第一個新坐標軸正交且方差次大的方向。重復以上過程,重復次數為原始數據的特征維數。
  在重復中,我們不斷地得到新的坐標系。Generally,方差集中於前面幾個綜合變量中,且綜合變量在總方差中所占的比重依次遞減,而后面新的坐標軸所包含的方差越來越小,甚至接近0。實際應用中,一般只要挑選前幾個方差較大的主成分即可。
  那么,我們如何得到這些包含最大差異性的主成分方向呢?事實上,通過計算數據矩陣的協方差矩陣,然后得到協方差矩陣的特征值及特征向量,選擇特征值最大(也即包含方差最大)的N個特征所對應的特征向量組成的矩陣,我們就可以將數據矩陣轉換到新的空間當中,實現數據特征的降維(N維)。
  由於得到協方差矩陣的特征值特征向量有兩種方法:特征值分解協方差矩陣、奇異值分解協方差矩陣,所以PCA算法有兩種實現方法:基於特征值分解協方差矩陣實現PCA算法、基於SVD分解協方差矩陣實現PCA算法。(特征值分解最大的問題是只能針對方陣,即n*n的矩陣。而在實際的應用中,我們分解的大部分都不是方陣,所以產生了SVD。)

三.Python實現

1.sklearn.decomposition.PCA

  sklearn.decomposition.PCA(n_components=None, copy=True, whiten=False, svd_solver=’auto’, tol=0.0, iterated_power=’auto’, random_state=None)
它利用SVD分解協方差矩陣實現PCA算法,實現降維效果。
  注意:此類不適用於稀疏數據。
  參數:
  (1)n_components : 整型, 浮點型, None or 字符串類型。設置最后保留下來的主成分個數。
如果不設置該參數,則保留所有主成分。
賦值為string,如n_components='mle',將自動選取特征個數n,使得滿足所要求的方差百分比。

  (2)copy : 布爾值 (默認值 True)。表示在運算時,是否將原始數據復制一遍。
True:運算后,原始數據不會變化,因為運算是在原始數據的副本上進行的。
False:算法運算將在原始數據上運行,原始數據最終發生變化。

  (3)whiten : 布爾值(默認 False)
True:對降維后的主成分進行歸一化,使所有主成分的方差為1。
一般不白化,使用默認的False即可。

  (4)svd_solver :指定奇異值分解SVD的方法。字符串,{auto、 full、arpack、 randomized}
auto :默認值。該類會自行選擇以下三種中最佳的一種來實現算法。一般使用默認值即可。
full :傳統意義的SVD,使用了scipy庫的對應實現法。
arpack :用於數據量較大、維度較多,最后主成分較少的情況。
randomized :一般用於數據量大,數據維度多,且主成分較少的情況。

  (5)random_state :設置復現的參數。

2.屬性:

(1)components_ :返回降維后各主成分方向,並按照各主成分的方差值大小排序。
(2)explained_variance_ :降維后各主成分的方差值
(3)explained_variance_ratio_ :返回各個成分的方差百分比(貢獻率)
(4)n_components_ :返回所保留的成分個數n。

3.例1:iris數據集

import numpy as np
import pandas as pd
from sklearn import datasets
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.decomposition import PCA     #主成分分析用
from mpl_toolkits.mplot3d import Axes3D  #畫三維圖
# 導入鳶尾花數據
iris = datasets.load_iris()
x, y = iris.data, iris.target
print("x:", x.shape)
print("y:", y.shape)
print("原始變量名:", iris.feature_names)
print("標簽分類:",iris.target_names)
x: (150, 4)
y: (150,)
原始變量名: ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
標簽分類: ['setosa' 'versicolor' 'virginica']

有150個樣本,每個樣本有四個特征:萼片長度、萼片寬度、花瓣長度、花瓣寬度,根據上訴四個特征,將150個樣本分成三類。

pca0 = PCA(n_components=4)
pca0.fit(x).transform(x)
print("四個主成分方向:\n", pca.components_)
四個主成分方向:
 [[ 0.36158968 -0.08226889  0.85657211  0.35884393]
 [ 0.65653988  0.72971237 -0.1757674  -0.07470647]
 [-0.58099728  0.59641809  0.07252408  0.54906091]
 [ 0.31725455 -0.32409435 -0.47971899  0.75112056]]

假設原始變量為x1、x2、x3、x4, Y1為新的第一個主成分,則可認為Y1 = 0.36158968x1 - 0.08226889x2 + 0.85657211x3 + 0.35884393x4,以此類推,可寫出Y2、Y3、Y4。

print("各主成分的方差值:\n",pca.explained_variance_)
print("各主成分的方差值占比:\n",pca.explained_variance_ratio_)
各主成分的方差值:
 [ 4.22484077  0.24224357  0.07852391  0.02368303]
各主成分的方差值占比:
 [ 0.92461621  0.05301557  0.01718514  0.00518309]

第一個主成分占方差百分比的92.5%,第二個主成分占百分比的5.3%,第三個主成分占百分比的0.2%,前面三個主成分已包含原始變量中99%的信息,現在剔除最后一個主成分,僅保留前三個主成分。

pca1 = PCA(n_components=3)
pca1.fit(x)
x1_new = pca1.transform(x)
print("前三個主成分方向:\n",pca1.components_)
print("各主成分的方差值:\n",pca1.explained_variance_)
print("各主成分的方差值占比:\n",pca1.explained_variance_ratio_)
前三個主成分方向:
 [[ 0.36158968 -0.08226889  0.85657211  0.35884393]
 [ 0.65653988  0.72971237 -0.1757674  -0.07470647]
 [-0.58099728  0.59641809  0.07252408  0.54906091]]
各主成分的方差值:
 [ 4.22484077  0.24224357  0.07852391]
各主成分的方差值占比:
 [ 0.92461621  0.05301557  0.01718514]
fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(x1_new[:,0],x1_new[:,1],x1_new[:,2],c=y)
<mpl_toolkits.mplot3d.art3d.Path3DCollection at 0xe352bb35c0>

png

下面從多個角度來看各主成分的分布情況:

for i in [0,90,180,270]:
    fig = plt.figure()
    ax = Axes3D(fig,elev=0, azim=i)
    ax.scatter(x1_new[:,0],x1_new[:,1],x1_new[:,2],c=y)

png

png

png

png

for i in [0,90,180,270]:
    fig = plt.figure()
    ax = Axes3D(fig,elev=i, azim=0)
    ax.scatter(x1_new[:,0],x1_new[:,1],x1_new[:,2],c=y)

png

png

png

png

pca2 = PCA(n_components=2)
pca2.fit(x)
x2_new = pca2.transform(x)
print("2個主成分方向:\n", pca2.components_)
print("2個主成分的解釋方差值:\n", pca2.explained_variance_)
print("2個主成分解釋方差占比:\n", pca2.explained_variance_ratio_)
plt.scatter(x2_new[:,0],x2_new[:,1],c=y)
2個主成分方向:
 [[ 0.36158968 -0.08226889  0.85657211  0.35884393]
 [ 0.65653988  0.72971237 -0.1757674  -0.07470647]]
2個主成分的解釋方差值:
 [ 4.22484077  0.24224357]
2個主成分解釋方差占比:
 [ 0.92461621  0.05301557]





<matplotlib.collections.PathCollection at 0xe353a2af98>

png

四.PCA的缺點

1.各個主成分的含義具有模糊性,不具有原始變量的清晰含義。
2.方差小的主成分可能含有對樣本差異的重要信息,那么降維后可能影響后續的數據分析。


免責聲明!

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



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