Python數模筆記-Sklearn(3)主成分分析

youcans發表於2021-05-11

主成分分析(Principal Components Analysis,PCA)是一種資料降維技術,通過正交變換將一組相關性高的變數轉換為較少的彼此獨立、互不相關的變數,從而減少資料的維數。


1、資料降維

1.1 為什麼要進行資料降維?

  為什麼要進行資料降維?降維的好處是以略低的精度換取問題的簡化。

  人們在研究問題時,為了全面、準確地反映事物的特徵及其發展規律,往往要考慮很多相關指標的變化和影響。尤其在資料探勘和分析工作中,前期收集資料階段總是儘量收集能夠獲得的各種資料,能收盡收,避免遺漏。多變數、大樣本的資料為後期的研究和應用提供了豐富的資訊,從不同角度反映了問題的特徵和資訊,但也給資料處理和分析工作帶來了很多困難。

  為了避免遺漏資訊需要獲取儘可能多的特徵變數,但是過多的變數又加劇了問題的複雜性。由於各種變數都是對同一事物的反映,變數之間經常會存在一定的相關性,這就造成大量的資訊重複、重疊,有時會淹沒甚至扭曲事物的真正特徵與內在規律。因此,我們希望資料分析中涉及的變數較少,而得到的資訊量又較多。這就需要通過降維方法,在減少需要分析的變數數量的同時,儘可能多的保留眾多原始變數所包含的有效資訊。

  變數之間具有一定的相關關係,意味著相關變數所反映的資訊有一定程度的重疊,就有可能用較少的綜合指標聚合、反映眾多原始變數所包含的全部資訊或主要資訊。 因此,需要研究特徵變數之間的相關性、相似性,以減少特徵變數的數量,便於分析影響系統的主要因素。例如,對學生的評價指標有很多,作業、考勤、活動、獎懲、考試、考核,根據各種指標的關聯度和相似性,最終可以聚合為德智體美等幾個主要的類別指標反映眾多指標中大部分資訊。
  
  降維方法可以從事物之間錯綜複雜的關係中找出一些主要因素,從而能有效利用大量統計資料進行定量分析,解釋變數之間的內在關係,得到對事物特徵及其發展規律的一些深層次的啟發。

1.2 常用的降維思想和方法

  降維的數學本質是將高維特徵空間對映到低維特徵空間,有線性對映和非線性對映兩類主要方法。

  線性對映方法主要有主成分分析(PCA)和線性判別函式(LDA)。主成分分析(PCA)的思想是按均方誤差損失最小化原則,將高維原始空間變換到低維特徵向量空間。線性判別函式(LDA)的思想是向線性判別超平面的法向量上投影,使得區分度最大(高內聚,低耦合) 。

  非線性對映方法主要有:基於核的非線性降維, 將高維向量的內積轉換成低維的核函式表示,如核主成分分析(KPCA)、核線性判別函式(KLDA) ;二維化和張量化, 將資料對映到二維空間上,如二維主成分分析(2DPCA)、二維線性判別分析(2DLDA)、二維典型相關分析(2DCCA);流形學習方法, 從高維取樣資料中恢復低維流形結構並求出相應的嵌入對映,如等距對映 (ISOMap) , 拉普拉斯特徵對映 (LE), 區域性線性嵌入 (LPP)。本質上,非線性對映的思想和演算法與神經網路是相通的。

  此外,還可以通過聚類分析、神經網路方法進行資料降維。

1.3 SKlearn 中的降維分析方法

  SKlearn 工具包提供了多種降維分析方法。

  • 主成分分析  
    • decomposition.PCA  主成分分析
    • decomposition.IncrementalPCA  增量主成分分析
    • decomposition.KernelPCA  核主成分分析
    • decomposition.SparsePCA  稀疏主成分分析
    • decomposition.MiniBatchSparsePCA  小批量稀疏主成分分析
    • decomposition.TruncatedSVD  截斷奇異值分解
  • 字典學習
    • decomposition.DictionaryLearning  字典學習
    • decomposition.MiniBatchDictionaryLearning  小批量字典學習
    • decomposition.dict_learning  字典學習用於矩陣分解
    • decomposition.dict_learning_online  線上字典學習用於矩陣分解
  • 因子分析
    • decomposition.FactorAnalysis  因子分析(FA)
  • 獨立成分分析
    • decomposition.FastICA  快速獨立成分分析
  • 非負矩陣分解
    • decomposition.NMF  非負矩陣分解
  • 隱式狄利克萊分佈
    • decomposition.LatentDirichletAllocation  線上變分貝葉斯演算法(隱式狄利克萊分佈)

2、主成分分析(PCA)方法

2.1 基本思想和原理

  主成分分析是最基礎資料降維方法,它只需要特徵值分解,就可以對資料進行壓縮、去噪,應用十分廣泛。

  主成分分析的目的是減少資料集變數數量,同時要保留儘可能多的特徵資訊;方法是通過正交變換將原始變數組轉換為數量較少的彼此獨立的特徵變數,從而減少資料集的維數。

  主成分分析方法的思想是,將高維特徵(n維)對映到低維空間(k維)上,新的低維特徵是在原有的高維特徵基礎上通過線性組合而重構的,並具有相互正交的特性,即為主成分。

  通過正交變換構造彼此正交的新的特徵向量,這些特徵向量組成了新的特徵空間。將特徵向量按特徵值排序後,樣本資料集中所包含的全部方差,大部分就包含在前幾個特徵向量中,其後的特徵向量所含的方差很小。因此,可以只保留前 k個特徵向量,而忽略其它的特徵向量,實現對資料特徵的降維處理。

  主成分分析方法得到的主成分變數具有幾個特點:(1)每個主成分變數都是原始變數的線性組合;(2)主成分的數目大大少於原始變數的數目;(3)主成分保留了原始變數的絕大多數資訊;(4)各主成分變數之間彼此相互獨立。

2.2 演算法步驟

  主成分分析的基本步驟是:對原始資料歸一化處理後求協方差矩陣,再對協方差矩陣求特徵向量和特徵值;對特徵向量按特徵值大小排序後,依次選取特徵向量,直到選擇的特徵向量的方差佔比滿足要求為止。
  演算法的基本流程如下:

  • (1)歸一化處理,資料減去平均值;
  • (2)通過特徵值分解,計算協方差矩陣;
  • (3)計算協方差矩陣的特徵值和特徵向量;
  • (4)將特徵值從大到小排序;
  • (5)依次選取特徵值最大的k個特徵向量作為主成分,直到其累計方差貢獻率達到要求;
  • (6)將原始資料對映到選取的主成分空間,得到降維後的資料。

  在演算法實現的過程中,SKlearn 工具包針對實際問題的特殊性,又發展了各種改進演算法,例如:

  • 增量主成分分析:針對大型資料集,為了解決記憶體限制問題,將資料分成多批,通過增量方式逐步呼叫主成分分析演算法,最終完成整個資料集的降維。
  • 核主成分分析:針對線性不可分的資料集,使用非線性的核函式把樣本空間對映到線性可分的高維空間,然後在這個高維空間進行主成分分析。
  • 稀疏主成分分析:針對主成分分析結果解釋性弱的問題,通過提取最能重建資料的稀疏分量, 凸顯主成分中的主要組成部分,容易解釋哪些原始變數導致了樣本之間的差異。 

2.3 優點和缺點

  主成分分析方法的主要優點是:
  1)僅以方差衡量資訊量,不受資料集以外的因素影響; 
  2)各主成分之間正交,可消除原始資料各變數之間的相互影響;
  3)方法簡單,易於實現。

  主成分分析方法的主要缺點是:
  1)各個主成分的含義具有模糊,解釋性弱,通常只有資訊量而無實際含義;
  2)在樣本非正態分佈時得到的主成分不是最優的,因此特殊情況下方差小的成分也可能含有重要資訊。  


3、SKlearn 中的主成分分析(PCA) 方法

3.1 PCA 演算法(decomposition.PCA)

  sklearn.decomposition.PCA 類是 PCA演算法的具體實現,官網介紹詳見:https://scikit-learn.org/stable/modules/decomposition.html#principal-component-analysis-pca

sklearn.decomposition.PCA(n_components=None, copy=True, whiten=False)

class sklearn.decomposition.PCA(n_components=None, *, copy=True, whiten=False, svd_solver='auto', tol=0.0, iterated_power='auto', random_state=None)

  PCA 類的主要引數:

  • n_components: int,float  n 為正整數,指保留主成分的維數;n 為 (0,1] 範圍的實數時,表示主成分的方差和所佔的最小閾值。
  • whiten:bool, default=False  是否對降維後的主成分變數進行歸一化。預設值 False。
  • svd_solver:{‘auto’, ‘full’, ‘arpack’, ‘randomized’}  指定奇異值分解SVD的演算法。'full' 呼叫 scipy庫的 SVD;'arpack'呼叫scipy庫的 sparse SVD;'randomized' SKlearn的SVD,適用於資料量大、變數維度多、主成分維數低的場景。預設值 'auto'。

  PCA 類的主要屬性:

  • components_:   方差最大的 n-components 個主成分
  • explained_variance_:  各個主成分的方差值
  • explained_variance_ratio_:  各個主成分的方差值佔主成分方差和的比例

  PCA 類的主要方法:

  • fit(X,y=None)  表示用資料 X 訓練PCA模型
    fit() 是scikit-learn中的通用方法,實現訓練、擬合的步驟。PCA是無監督學習,y=None。
  • fit_transform(X)  表示用資料 X 訓練PCA模型,並返回降維後的資料
  • transform(X)  將資料 X 轉換成降維後的資料,用訓練好的 PCA模型對新的資料集進行降維。
  • inverse_transform()  將降維後的資料轉換成原始資料

3.2 decomposition.PCA 使用例程

from sklearn.decomposition import PCA  # 匯入 sklearn.decomposition.PCA 類
import numpy as np

X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
modelPCA = PCA(n_components=2)  # 建立模型,設定保留主成分數 K=2
modelPCA.fit(X)  # 用資料集 X 訓練 模型 modelPCA
print(modelPCA.n_components_)  # 返回 PCA 模型保留的主成份個數
# 2
print(modelPCA.explained_variance_ratio_)  # 返回 PCA 模型各主成份佔比
# [0.9924 0.0075]  # print 顯示結果
print(modelPCA.singular_values_) # 返回 PCA 模型各主成份的奇異值
# [6.3006 0.5498]  # print 顯示分類結果

X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
modelPCA2 = PCA(n_components=0.9) # 建立模型,設定主成份方差佔比 0.9
# 用資料集 X 訓練 模型 modelPCA2,並返回降維後的資料
Xtrans = modelPCA2.fit_transform(X)
print(modelPCA2.n_components_)  # 返回 PCA 模型保留的主成份個數
# 1
print(modelPCA2.explained_variance_ratio_)  # 返回 PCA 模型各主成份佔比
# [0.9924]  # print 顯示結果
print(modelPCA2.singular_values_)  # 返回 PCA 模型各主成份佔比
# [6.3006]  # print 顯示結果
print(Xtrans)  # 返回降維後的資料 Xtrans
# [[1.3834], [2.2219], [3.6053], [-1.3834], [-2.2219], [-3.6053]]

  注意:建立模型時,PCA(n_components=2) 中的 n_components為正整數,表示設定保留的主成份維數為 2;PCA(n_components=0.9) 中的 n_components 為 (0,1] 的小數,表示並不直接設定保留的主成份維數,而是設定保留的主成份應滿足其方差和佔比 >0.9。

3.3 改進演算法:增量主成分分析(decomposition.IncrementalPCA)

  對於樣本集巨大的問題,例如樣本量大於 10萬、特徵變數大於100,PCA 演算法耗費的記憶體很大,甚至無法處理。   
  class sklearn.decomposition.IncrementalPCA 類是增量主成分分析演算法的具體實現,官網介紹詳見:https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.IncrementalPCA.html#sklearn.decomposit
 

class sklearn.decomposition.IncrementalPCA(n_components=None, *, whiten=False, copy=True, batch_size=None)

  主要引數:
inverse_transform()  將降維後的資料轉換成原始資料

  IncrementalPCA 的使用例程如下:

# Demo of sklearn.decomposition.IncrementalPCA

from sklearn.datasets import load_digits
from sklearn.decomposition import IncrementalPCA, PCA
from scipy import sparse

X, _ = load_digits(return_X_y=True)
print(type(X))  # <class 'numpy.ndarray'>
print(X.shape)      # (1797, 64)

modelPCA = PCA(n_components=6)  # 建立模型,設定保留主成分數 K=6
modelPCA.fit(X)  # 用資料集 X 訓練 模型 modelPCA
print(modelPCA.n_components_)  # 返回 PCA 模型保留的主成份個數
# 6
print(modelPCA.explained_variance_ratio_)  # 返回 PCA 模型各主成份佔比
# [0.1489 0.1362 0.1179 0.0841 0.0578 0.0492]
print(sum(modelPCA.explained_variance_ratio_))  # 返回 PCA 模型各主成份佔比
# 0.5941
print(modelPCA.singular_values_) # 返回 PCA 模型各主成份的奇異值
# [567.0066  542.2518 504.6306 426.1177 353.3350 325.8204]

# let the fit function itself divide the data into batches
Xsparse = sparse.csr_matrix(X)  # 壓縮稀疏矩陣,並非 IPCA 的必要步驟
print(type(Xsparse))  # <class 'scipy.sparse.csr.csr_matrix'>
print(Xsparse.shape)  # (1797, 64)
modelIPCA = IncrementalPCA(n_components=6, batch_size=200)
modelIPCA.fit(Xsparse)  # 訓練模型 modelIPCA
print(modelIPCA.n_components_)  # 返回 PCA 模型保留的主成份個數
# 6
print(modelIPCA.explained_variance_ratio_)  # 返回 PCA 模型各主成份佔比
# [0.1486 0.1357 0.1176 0.0838 0.0571 0.0409]
print(sum(modelIPCA.explained_variance_ratio_))  # 返回 PCA 模型各主成份佔比
# 0.5838
print(modelIPCA.singular_values_) # 返回 PCA 模型各主成份的奇異值
#[566.4544 541.334 504.0643 425.3197 351.1096 297.0412]

本例程呼叫了 SKlearn內建的資料集 .datasets.load_digits,並給出了 PCA 演算法與 IPCA 演算法的對比,兩種演算法的結果非常接近,說明 IPCA 的效能降低很小。

3.4 改進演算法:核主成分分析(decomposition.KernelPCA)

對於線性不可分的資料集,使用非線性的核函式可以把樣本空間對映到線性可分的高維空間,然後在這個高維空間進行主成分分析。

class sklearn.decomposition.KernelPCA 類是演算法的具體實現,官網介紹詳見:https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.KernelPCA.html#sklearn.decomposition.KernelPCA
  

class sklearn.decomposition.KernelPCA(n_components=None, *, kernel='linear', gamma=None, degree=3, coef0=1, kernel_params=None, alpha=1.0, fit_inverse_transform=False, eigen_solver='auto', tol=0, max_iter=None, remove_zero_eig=False, random_state=None, copy_X=True, n_jobs=None)

KernelPCA 的使用例程如下:

# Demo of sklearn.decomposition.KernelPCA

from sklearn.datasets import load_iris
from sklearn.decomposition import KernelPCA, PCA
import matplotlib.pyplot as plt
import numpy as np

X, y = load_iris(return_X_y=True)
print(type(X))  # <class 'numpy.ndarray'>

modelPCA = PCA(n_components=2)  # 建立模型,設定保留主成分數 K=2
Xpca = modelPCA.fit_transform(X)  # 用資料集 X 訓練 模型 modelKPCA

modelKpcaP = KernelPCA(n_components=2, kernel='poly') # 建立模型,核函式:多項式
XkpcaP = modelKpcaP.fit_transform(X)  # 用資料集 X 訓練 模型 modelKPCA

modelKpcaR = KernelPCA(n_components=2, kernel='rbf') # 建立模型,核函式:徑向基函式
XkpcaR = modelKpcaR.fit_transform(X)  # 用資料集 X 訓練 模型 modelKPCA

modelKpcaS = KernelPCA(n_components=2, kernel='cosine') # 建立模型,核函式:餘弦函式
XkpcaS = modelKpcaS.fit_transform(X)  # 用資料集 X 訓練 模型 modelKPCA

fig = plt.figure(figsize=(8,6))
ax1 = fig.add_subplot(2,2,1)
ax2 = fig.add_subplot(2,2,2)
ax3 = fig.add_subplot(2,2,3)
ax4 = fig.add_subplot(2,2,4)
for label in np.unique(y):
    position = y == label
    ax1.scatter(Xpca[position, 0], Xpca[position, 1], label='target=%d' % label)
    ax1.set_title('PCA')
    ax2.scatter(XkpcaP[position, 0], XkpcaP[position, 1], label='target=%d' % label)
    ax2.set_title('kernel= Poly')
    ax3.scatter(XkpcaR[position, 0], XkpcaR[position, 1], label='target=%d' % label)
    ax3.set_title('kernel= Rbf')
    ax4.scatter(XkpcaS[position, 0], XkpcaS[position, 1], label='target=%d' % label)
    ax4.set_title('kernel= Cosine')
plt.suptitle("KernalPCA")
plt.show()

本例程呼叫了 SKlearn內建的資料集 .datasets.load_iris,並給出了 PCA 演算法與 3種核函式的KernelPCA 演算法的對比,結果如下圖所示。不同演算法的降維後對映到二維平面的結果有差異,進一步的討論已經超出本文的內容。


版權說明:
本文內容及例程為作者原創,並非轉載書籍或網路內容。
本文中案例問題來自:
1 SciKit-learn 官網:https://scikit-learn.org/stable/index.html

YouCans 原創作品
Copyright 2021 YouCans, XUPT
Crated:2021-05-10

相關文章