(無監督數據降維)主成分分析法 - PCA


SKlearn官網 - sklearn.decomposition.PCA

一,數學原理

參考:通俗易懂的主成分分析法(PCA)詳解

二,PCA的使用

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

1,參數

n_components:intfloatNone or str
			  當其大於1,且爲正數時:需要保留的維度
			  當0 < n_components < 1時:需要保留原數據可解釋的度的百分之幾	
	
copy:bool, default=True
	  如果爲False,則傳遞給fit的數據將被覆蓋,並且運行
	  fit(X).transform(X)將不會產生預期的結果,請改用
	  fit_transform(X)。

whiten:bool, 可選(default False)
		如果爲True(默認情況下爲False),則將components_矢量
		乘以n_samples的平方根,然後除以奇異值,以確保具有單位
		分量方差的不相關輸出。

		泛白會從轉換後的信號中刪除一些信息(組件的相對方差標
		度),但有時可以通過使下游估算器的數據符合某些硬性假設
		來提高下游估算器的預測準確性。

2,屬性(方法)

components_:array, shape (n_components, n_features)
			 特徵空間中的主軸,表示數據中最大方差的方向。組件
			 按排序 explained_variance_。

explained_variance_:array, shape (n_components,)
					 每個選定組件說明的方差量。
					 等於X的協方差矩陣的n_components個最大特徵值。

explained_variance_ratio_:array, shape (n_components,)
						   每個選定組件解釋的方差百分比。
						   如果n_components未設置,則將存儲
						   所有分量,並且比率之和等於1.0。

singular_values_:array, shape (n_components,)
				  對應於每個選定組件的奇異值。奇異值等於
				  n_components 低維空間中變量的2範數。

mean_:array, shape (n_features,)
	   根據訓練集估算的每特徵經驗均值。
	   等於X.mean(axis=0)。

n_components_:int
			   估計的組件數。
			   當n_components設置爲'mle'01之間的數字
			   (svd_solver =='full')時,將從輸入數據中估計
			   該數字。否則等於參數n_components,如果
			   n_components爲None,則等於n_features和
			   n_samples的較小值。

n_features_:int
			 訓練數據中的特徵數量。

n_samples_:int
		    訓練數據中的樣本數量。

noise_variance_:float
				 根據Tipping and Bishop 1999的概率PCA模型估計的噪聲協方差。
				 需要計算估計的數據協方差和分數樣本。
				 等於X協方差矩陣的(min(n_features,n_samples)-n_components)個最小特徵值的平均值。

3,示例

這裏使用數字識別的數據,以及kNN算法

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
digits = datasets.load_digits()
x = digits.data
y = digits.target
from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2) 

可以看出此時,數據維度爲64

x_train.shape
>>>(1437, 64)

保留所有維度(特徵)做kNN算法

%%time
from sklearn.neighbors import KNeighborsClassifier

kNN_classifier = KNeighborsClassifier()
kNN_classifier.fit(x_train, y_train)
>>> Wall time: 78 ms

保留所有維度時的準確度

kNN_classifier.score(x_test, y_test)
>>> 0.9777777777777777

重點
進行PCA降維(從64維降至2維)
注意:對測試集降維時,不可以重新擬合PCA算法,要使用x_train擬合的PCA進行降爲

from sklearn.decomposition import PCA

pca = PCA(n_components=2)
pca.fit(x_train)
x_train_reduction = pca.transform(x_train)
x_test_reduction = pca.transform(x_test)
%%time

kNN_classifier = KNeighborsClassifier()
kNN_classifier.fit(x_train_reduction, y_train)
>>> Wall time: 2 ms

可以看出當只保留2個維度時準確度過低

kNN_classifier.score(x_test_reduction, y_test)
>>> 0.6194444444444445
'''表示只保留的(14.7+13.7)%的方差信息(特徵信息)
-降維到2維度是可信度太低'''
pca.explained_variance_ratio_
>>> array([0.14766332, 0.13708212])

我們來看一下,每一個特徵所佔可信的百分比

pca = PCA(n_components=x_train.shape[1])
pca.fit(x_train)
pca.explained_variance_ratio_
array([1.47663319e-01, 1.37082118e-01, 1.18096318e-01, 8.30528497e-02,
       5.82234857e-02, 4.93950699e-02, 4.31673479e-02, 3.71697003e-02,
       3.37564927e-02, 3.08558779e-02, 2.38410022e-02, 2.27033177e-02,
       1.86248506e-02, 1.71280718e-02, 1.45014087e-02, 1.39292791e-02,
       1.34209616e-02, 1.25513680e-02, 1.00296802e-02, 8.88825053e-03,
       8.70986633e-03, 8.03133349e-03, 7.65322153e-03, 7.26124768e-03,
       6.94377770e-03, 5.95562460e-03, 5.85075759e-03, 5.22376048e-03,
       4.96122747e-03, 4.26953249e-03, 3.82713368e-03, 3.54858246e-03,
       3.33788387e-03, 3.25852623e-03, 3.05706857e-03, 2.92001586e-03,
       2.62094836e-03, 2.27552797e-03, 2.16452071e-03, 2.14005187e-03,
       1.87783108e-03, 1.59226127e-03, 1.51161475e-03, 1.41757015e-03,
       1.19523457e-03, 1.10190613e-03, 9.62019170e-04, 8.47896454e-04,
       5.48248494e-04, 3.79242817e-04, 2.22769625e-04, 8.51191406e-05,
       5.14896740e-05, 4.97757855e-05, 3.96997516e-05, 1.52010302e-05,
       5.29455625e-06, 3.23397983e-06, 1.23259991e-06, 5.61055922e-07,
       4.19614970e-07, 6.18786317e-34, 6.18786317e-34, 5.57495373e-34])

隨着維度的增加可信度的變化(x:維度,y:可信度%)

plt.plot([i for i in range(x_train.shape[1])],[np.sum(pca.explained_variance_ratio_[:i+1]) for i in range(x_train.shape[1])])
plt.show()

在這裏插入圖片描述
重點
當我們不知道該選擇幾個維度比較好時,我們可以直接填入想保留的可信度(%)

pca = PCA(0.95)
pca.fit(x_train)
>>> PCA(copy=True, iterated_power='auto', n_components=0.95, random_state=None,
    svd_solver='auto', tol=0.0, whiten=False)

當可信度爲95%時,保留了29個維度(特徵)

pca.n_components_
>>> 29

可以看出,此時的精確度有明顯的提高

kNN_classifier.score(x_test_reduction, y_test)
>>> 0.975

下面將所有的數據降維到2維

pca = PCA(n_components=2)
pca.fit(x)
x_reduction = pca.transform(x)
x_reduction.shape
>>> (1797, 2)
for i in range(10):
    plt.scatter(x_reduction[y==i, 0], x_reduction[y==i, 1], alpha=0.8)
plt.show()

在這裏插入圖片描述
可以看出如果區分個別類別是,僅使用2維的數據就已經可以進行很好的區分了(例如區分藍色與粉色)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章