使用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()
它看起来像下图
基于癌症数据集的30个特征的恶性和良性类别的直方图
现在从这些直方图中我们看到,像mean fractal dimension这样的特征在辨别良性恶性方面几乎没有作用,但worst concave points 或 worst perimeter是有用的特征,可以给我们强有力的暗示癌症数据集的类别。直方图在我们的天体物理学研究中是必不可少的,因为它们通常用于分离机器学习模型。如果您的数据只有一个特征,例如worst perimeter,那么将恶性与良性病例分开就足够了。
在将PCA用于这些癌症机器学习数据集之前,让我们非常简单地理解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代码,绘图如下所示
基于癌症特征的前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()#
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.
癌症数据集“worst”特征的相关图
因此,让我们总结一下我们所做和学到的东西
- 为什么选择PCA而不仅仅是特征分析?(答案提示:大数据集有许多特征,可以使我们减少特征空间的维度)
- 我们以癌症数据集开始了我们的例子,发现了30个特征,有2个类。
- 要在此数据集上应用PCA,首先我们缩放所有特征,然后fit_transform在缩放特征上应用PCA(具有3个主成分)的方法。
- 我们证明,在这3个主要成分中,2个占总方差的87%。
- 基于这两个主成分,我们可以对数据进行可视化,并在“恶性”和“良性”类之间看到非常清晰的分离。
希望这有助于您掌握一些概念并指导您在数据集上有效地应用PCA。对于锻炼,您可以立即尝试波士顿房屋数据(13个特征)并查看结果。