使用Python深入了解PCA(主成分分析)

在決定選擇哪些特徵以使您的機器學習模型免受過度擬合的影響時,您是否感到困惑?有什麼方法可以減少特徵空間的維度嗎?

PCA肯定能幫到你。

我們將通過一個簡單的解釋癌症數據集的主成分分析,並看到特徵空間維度減少到數據可視化的例子。

讓我們從導入癌症數據集開始

from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()

我們可以使用它DESCR來了解機器學習數據集的基本描述

print cancer.DESCR

從這裡,您現在知道這個機器學習數據集有30個特性,比如smoothness、radius等。實例的數量是569個,其中212個是惡性的,其餘的是良性的。目標變量被列出為0和1,為了確保0代表惡性,反之亦然,我們可以

print len(cancer.data[cancer.target==1])

>> 357

要了解有關特徵如何影響目標的更多信息,我們可以繪製惡性和良性類別的直方圖。如果基於該特徵分離兩個直方圖,那麼我們可以說該特徵對於辨別實例很重要。Python代碼如下:

import numpy as np 

import matplotlib.pyplot as plt
# from matplotlib.pyplot import matplotlib

fig,axes =plt.subplots(10,3, figsize=(12, 9)) # 3 columns each containing 10 figures, total 30 features

malignant=cancer.data[cancer.target==0] # define malignant
benign=cancer.data[cancer.target==1] # define benign

ax=axes.ravel()# flat axes with numpy ravel

for i in range(30):
_,bins=np.histogram(cancer.data[:,i],bins=40)
ax[i].hist(malignant[:,i],bins=bins,color='r',alpha=.5)# red color for malignant class
ax[i].hist(benign[:,i],bins=bins,color='g',alpha=0.3)# alpha is for transparency in the overlapped region
ax[i].set_title(cancer.feature_names[i],fontsize=9)
ax[i].axes.get_xaxis().set_visible(False) # the x-axis co-ordinates are not so useful, as we just want to look how well separated the histograms are
ax[i].set_yticks(())

ax[0].legend(['malignant','benign'],loc='best',fontsize=8)
plt.tight_layout()# let's make good plots
plt.show()

它看起來像下圖

使用Python深入瞭解PCA(主成分分析)

基於癌症數據集的30個特徵的惡性和良性類別的直方圖

現在從這些直方圖中我們看到,像mean fractal dimension這樣的特徵在辨別良性惡性方面幾乎沒有作用,但worst concave points 或 worst perimeter是有用的特徵,可以給我們強有力的暗示癌症數據集的類別。直方圖在我們的天體物理學研究中是必不可少的,因為它們通常用於分離機器學習模型。如果您的數據只有一個特徵,例如worst perimeter,那麼將惡性與良性病例分開就足夠了。

在將PCA用於這些癌症機器學習數據集之前,讓我們非常簡單地理解PCA實際上做了什麼。我們知道,在數據集中,某些特徵的相關性很高。讓我們看一下癌症數據集的一些示例圖 -

使用Python深入瞭解PCA(主成分分析)

散點圖具有癌症數據集的幾個特徵

現在希望你已經可以理解哪個圖表顯示了這些特徵之間的強相關性。下面是我用來繪製這些圖的Python代碼

imoprt pandas as pd
cancer_df=pd.DataFrame(cancer.data,columns=cancer.feature_names)# just convert the scikit learn data-set to pandas data-frame.
plt.subplot(1,2,1)#fisrt plot
plt.scatter(cancer_df['worst symmetry'], cancer_df['worst texture'], s=cancer_df['worst area']*0.05, color='magenta', label='check', alpha=0.3)
plt.xlabel('Worst Symmetry',fontsize=12)
plt.ylabel('Worst Texture',fontsize=12)
plt.subplot(1,2,2)# 2nd plot
plt.scatter(cancer_df['mean radius'], cancer_df['mean concave points'], s=cancer_df['mean area']*0.05, color='purple', label='check', alpha=0.3)
plt.xlabel('Mean Radius',fontsize=12)
plt.ylabel('Mean Concave Points',fontsize=12)
plt.tight_layout()
plt.show()

PCA本質上是一種減小特徵空間的維度的方法,使得新變量彼此正交(即它們是獨立的或不相關的)。

無論如何,從癌症數據集我們看到它有30個特徵,所以讓我們將它減少到只有3個主要特徵,然後我們可以看到這些新的自變量的散點圖。

在應用PCA之前,我們會縮放數據,使每個特徵都具有單位方差。這是必要的,因為擬合算法高度依賴於特徵的縮放。在這裡,我們使用StandardScaler模塊進行特徵縮放。StandardScaler從每個特徵中減去均值,然後縮放到單位方差。

我們首先實例化模塊然後擬合數據,Python實現如下:

scaler=StandardScaler()#instantiate
scaler.fit(cancer.data) # compute the mean and standard which will be used in the next command
X_scaled=scaler.transform(cancer.data)# fit and transform can be applied together and I leave that for simple exercise
# we can check the minimum and maximum of the scaled features which we expect to be 0 and 1
print "after scaling minimum", X_scaled.min(axis=0)

現在我們準備在這個縮放的數據集上應用PCA。我們像以前一樣開始StandardScaler實例化,然後擬合併最終轉換縮放數據。

pca=PCA(n_components=3)#very similar to instantiate K nearest neighbor classifier. 
pca.fit(X_scaled) # find the principal components
X_pca=pca.transform(X_scaled)
#let's check the shape of X_pca array
print "shape of X_pca", X_pca.shape

現在我們已經看到數據只有3個特徵。PCA的缺點是幾乎不可能分辨出初始特徵(這裡有30個特徵)如何組合形成主成分的。現在需要注意的一點是,我選擇了3個components 而不是2個,這可能會減少數據集的維數。

您可以通過測量主成分的方差比來檢查。Python示例代碼如下:

ex_variance=np.var(X_pca,axis=0)
ex_variance_ratio = ex_variance/np.sum(ex_variance)
print ex_variance_ratio
>> [0.60950217 0.2611802 0.12931763]

所以在這裡你可以看到前兩個components佔總方差的87%。所以只選擇2個components就足夠了。現在有了前兩個components,我們可以跳到PCA最重要的應用之一,即數據可視化。現在,由於PCA成分相互正交且不相關,我們可以預期惡性和良性分類是不同的。讓我們根據前兩個主成分繪製良、惡性類別,Python代碼如下:

Xax=X_pca[:,0]
Yax=X_pca[:,1]
#labels=cancer.target
labels=['Malignant','Benign']
cdict={0:'red',1:'green'}
labl={0:'Malignant',1:'Benign'}
marker={0:'*',1:'o'}
alpha={0:.3, 1:.5}
fig,ax=plt.subplots(figsize=(7,5))
fig.patch.set_facecolor('white')
for l in np.unique(labels):
ix=np.where(labels==l)
ax.scatter(Xax[ix],Yax[ix],c=cdict[l],label=labl[l],s=40,marker=marker[l],alpha=alpha[l])

plt.xlabel("First Principal Component",fontsize=14)
plt.ylabel("Second Principal Component",fontsize=14)
plt.legend()
plt.show()

# please check the scatter plot of the remaining component and you will see and understand the difference

使用上面的Python代碼,繪圖如下所示

使用Python深入瞭解PCA(主成分分析)

基於癌症特徵的前2個主成分的乳腺癌類別的圖

這兩個類完全分開,前兩個主成分作為新特徵。即使是線性分類器也可以很好地從測試集中識別出一個類。

這些主成分僅根據特徵計算,不考慮類中的信息。因此,PCA是無監督的方法,並且難以解釋兩個軸,因為它們是原始特徵的一些複雜混合。我們可以製作一個熱圖來了解這些特徵是如何混合起來創建components的。

plt.matshow(pca.components_,cmap='viridis')
plt.yticks([0,1,2],['1st Comp','2nd Comp','3rd Comp'],fontsize=10)
plt.colorbar()
plt.xticks(range(len(cancer.feature_names)),cancer.feature_names,rotation=65,ha='left')
plt.tight_layout()
plt.show()#
使用Python深入瞭解PCA(主成分分析)

3 PCs and dependencies on original features

實際上很難理解原始特徵與該圖的相關性如何,但我們總是可以使用seaborn熱圖來映射特徵的相關性。但是,仍然要檢查之前的相關圖,看看第一主成分是如何受 mean concave points 和 worst texture影響的。

在這裡,我展示了特徵的“worst”值的相關圖。Python代碼如下:

feature_worst=list(cancer_df.columns[20:31])# select the 'worst' features
s=sns.heatmap(cancer_df[feature_worst].corr(),cmap='coolwarm') # fantastic tool to study the features
s.set_yticklabels(s.get_yticklabels(),rotation=30,fontsize=7)
s.set_xticklabels(s.get_xticklabels(),rotation=30,fontsize=7)
plt.show()
# no point in finding correlation between radius with perimeter and area.
使用Python深入瞭解PCA(主成分分析)

癌症數據集“worst”特徵的相關圖

因此,讓我們總結一下我們所做和學到的東西

  • 為什麼選擇PCA而不僅僅是特徵分析?(答案提示:大數據集有許多特徵,可以使我們減少特徵空間的維度)
  • 我們以癌症數據集開始了我們的例子,發現了30個特徵,有2個類。
  • 要在此數據集上應用PCA,首先我們縮放所有特徵,然後fit_transform在縮放特徵上應用PCA(具有3個主成分)的方法。
  • 我們證明,在這3個主要成分中,2個佔總方差的87%。
  • 基於這兩個主成分,我們可以對數據進行可視化,並在“惡性”和“良性”類之間看到非常清晰的分離。

希望這有助於您掌握一些概念並指導您在數據集上有效地應用PCA。對於鍛鍊,您可以立即嘗試波士頓房屋數據(13個特徵)並查看結果。


分享到:


相關文章: