sklearn中的PCA(真實的數據集)
(在notebook中)
加載好需要的內容,手寫數字數據集
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,random_state=666)
相應的在X_train中用shape可以看出來,其中有1347個樣本,每個樣本有64個特征
結果如下
我們用KNN來訓練,引入方法,進行初始化以后進行fit
%%time
from sklearn.neighbors import KNeighborsClassifier
knn_clf = KNeighborsClassifier()
knn_clf.fit(X_train,y_train)
結果如下
看一下這樣的准確度是多少
knn_clf.score(X_test,y_test)
結果如下
這就是我們使用全部的數據集進行訓練以后進行識別得到的結果
然后我們嘗試用sklearn中的PCA來進行降維
引入並進行實例化,維度設置為2,然后進行fit操作,傳入以后就可以得到X_train_reduction(對訓練數據集降維以后的結果),同樣,對測試數據集一樣進行降維
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)
這樣就可以生成一個新的KNN識別器,同樣的操作以后
%%time
knn_clf = KNeighborsClassifier()
knn_clf.fit(X_train_reduction,y_train)
結果如下
可以發現計算的時間降低了非常多,這就是對於高維數據來說,將其降維到低維以后將會大大的節省計算的時間
那么我們再來看一下這個識別器的精度如何
knn_clf.score(X_test_reduction,y_test)
結果如下
可以發現,這個精度降低了很多,這不是能接受的,這樣就有了一個矛盾,速度提升了許多但是同時精度也降低了很多,很顯然兩維太低了,那么我們怎么找到好一些的維度數呢,在pca中有pca.explained_variance_ratio_,這個數據就告訴我們維持的方差,那么想要方差維持最大,這就可以找到
pca.explained_variance_ratio_
結果如下(這個意思就是有兩個比例,一個0.14上下,一個0.13上下,其就是兩個軸,第一個軸可以解釋原數據的14.5%的方差,第二個可以解釋原數據13.7%的方差,也就是這個二維一共包含了方差的28%上下,剩下的全部都丟失了)
那么我們怎么找呢
首先實例一下pca,然后傳入訓練數據集對應的特征數,然后進行fit操作,並打印出
pca.explained_variance_ratio_
pca = PCA(n_components=X_train.shape[1])
pca.fit(X_train)
pca.explained_variance_ratio_
結果如下(這就是對於主成分來說,依次的可以解釋的方差是多少,這就可以表示成每一個軸的重要程度)
這里我們做一個折線圖,橫軸是維度,縱軸是前i個軸解釋的方差的和
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])])
圖像如下(通過這個圖就可以看出來相應的需要的維度數以及重要程度)
在sklearn中的PCA,如果說希望數據保持95%以上的信息,可以直接傳入一個0到1的數字,即就是解釋多少的方差,然后進行fit
pca = PCA(0.95)
pca.fit(X_train)
結果如下
使用pca.n_components_看一下需要多少的維度
結果如下(即28個維度就可以保持95%以上)
這時候來運行一下,同時看一下要多長時間
X_train_reduction = pca.transform(X_train)
X_test_reduction = pca.transform(X_test)
%%time
knn_clf = KNeighborsClassifier()
knn_clf.fit(X_train_reduction,y_train)
結果如下
同時我們看一下這個准確度如何
knn_clf.score(X_test_reduction,y_test)
結果如下
可以說這樣的操作比全樣本快,精確度雖然低,這是可以接受的,有時候是可以犧牲精度來換取時間的
將數據降到二維也不是說一點用沒有,其還可以進行可視化
pca = PCA(n_components=2)
pca.fit(X)
X_reduction = pca.transform(X)
X_reduction.shape
結果如下
此時就可以對數據進行繪制
for i in range(10):
plt.scatter(X_reduction[y==i,0],X_reduction[y==i,1],alpha=0.8)
結果如下
可以發現,有些數據到了二維也有很好的區分度,那么如果要使用這種數據的話,實際上用二維也是可以的