使用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个特征)并查看结果。

相关推荐