SKlearn官網 - sklearn.decomposition.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:int,float,None 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'或0到1之間的數字
(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維的數據就已經可以進行很好的區分了(例如區分藍色與粉色)