PCA 主成分分析
前一篇提到的人脸识别中 , 我们在使用SVM支持向量机做人脸分类之前使用到PCA提取人脸数据中的主要成分 , 降低计算的维度 , 那么具体PCA是如何提取的呢?下文了解一下 。
PCAisamethodtoprojectdatainahigherdimensionalspaceintolowerdimensionalspacebymaximizingthevarianceofeachdimension--wiki
PCAismostlyusedasatoolinexploratorydataanalysisandformakingpredictivemodels.Itisoftenusedtovisualizegeneticdistanceandrelatednessbetweenpopulations.PCAiseitherdonebysingularvaluedecompositionofadesignmatrixorbydoingthefollowing2steps:
1.calculatingthedatacovariance(orcorrelation)matrixoftheoriginaldata
2.performingeigenvaluedecomposition(特征值分解)onthecovariancematrix(协方差矩阵).
--wiki
主成分分析 , 是一种统计方法 , 通过正交变换将一组可能存在相关性的变量转换为一组线性不相关的变量 , 转换后的这组变量叫主成分 。 对于这些成分 , 有些就显得没有那么必要 。 那么我们可以从这些成分中挑取比较有用的 , 而对于我们模型的训练作用不大的可以去除掉 。 这个过程其实也是一个降维的过程 , 对高维度的数据集进行降维 , 减少一些信息含量 , 保留主要的那些维度 。 主要的那些维度是指在这些维度上具有更大的差异 , 而对于那些差异化不大的特征 , 有时候反而会影响我们的模型学习 , 而成为一种噪音 , 也会影响我们training时候的速度 。 所以在机器学习的过程中 , 去掉那些无关紧要的变量会使得我们的学习模型效率提高 。
因此我们要找到那些差异化比较大的特征 , 也就是说在表示它的特征的这一系列数中 , 它的variance(方差:是在概率论和统计方差衡量随机变量或一组数据时离散程度的度量)是比较大的 , 比较离散的 , 而对于那些不明显的特征 , 用数据来衡量他们的这种特征程度的话 , 他们更容易聚集在一起 , 而不那么离散 , 也就是variance的值很小 。 下面使用代码画图来形象地了解一下 。
%matplotlibinlineimportnumpyasnpimportmatplotlib.pyplotaspltimportseabornassns;sns.set()rng=np.random.RandomState(1)X=np.dot(rng.rand(2,2),rng.rand(2,200)).Tplt.scatter(X[:,0],X[:,1])plt.axis('equal')先画出散点图 , 观察一下我们的samples:
Numpy.random.RandomState.rand(2 , 200)randomvaluesinagivenshape,产生一个2x200的矩阵 。 矩阵中的每一个element(元)都是随机产生的介于0到1之间的一个数 。
X=np.dot(rng.rand(2,2),rng.rand(2,200)).T
这个代码的意思是先随机产生两个点 , 然后再用这两个点进行一个列变换(左乘行变换 , 右乘列变换)产生与左边矩阵具有相同行 , 与右乘的矩阵右相同列的shape为2x200的新矩阵 , 可以知道这个新的矩阵中的每个点的x或y坐标都不会大于2(1x1+1x1=2) 。 尾部的.T进行了矩阵的转置 , 使得矩阵从2x200的shape变成200x2 。
使用PCA来解出上图中散点的主成分 , 图中每个点需要两个参数(x,y坐标)才能表达准确 , 那么对于该图上的点来说 , numberofcomponents=2 , 有两个成分 。
fromsklearn.decompositionimportPCApca=PCA(n_components=2)pca.fit(X)看起来只有三行代码 , 但是相关的计算几乎全在里面了 。
Sklearn.decomposition.PCA(n_components=None,*,copy=True,whiten=False,svd_solver='auto',tol=0.0,iterated_power='auto',random_state=None)
PCA:principalcomponentanalysis(PCA)
上述代码中的主成分分析使用的是SVD(singularvaluedecomposition,奇异值分解)方法 。LineardimensionalityreductionusingSingularValueDecompositionofthedatatoprojectittoalowerdimensionalspace.
PCAskipslesssignificantcomponent.Obviously,wecanuseSVDtofindPCAbytruncatingthelessimportantbasisvectorsintheoriginalSVDmatrix.
PCA方法寻找主成分的过程 , 通过采用SVD找到所有的基础向量之后 , 再把不怎么重要的基础向量裁断掉 。 所以这里需要先使用SVD找到矩阵X的基础向量 。
从Sklearn.decomposition.PCA()的原代码中抽出计算基础向量部分:
scipy.linalg.svd(a,full_matrices=True,compute_uv=True,overwrite_a=False,check_finite=True,lapack_driver='gesdd')
SingularValueDecomposition.奇异值分解 。
A:(M,N)array_like,matrixtodecompose , 一个要分解的(m,n)矩阵 。
SVDReturn(返回值):
U:unitarymatrixhavingleftsingularvectors(左奇异矩阵)ascolumns.Ofshape(M,M)or(M,K),dependingonfull_matrices.
S:ndarray,thesingularvalues(奇异值),sortedinnon-increasingorder.Ofshape(K),withK=min(M,N).
Wh:Unitarymatrixhavingrightsingularvectors(右奇异矩阵)asrows.Ofshape(N,N)or(k,N).
任何一个矩阵A都可以拆分成如下的三个矩阵相乘 。
S长下面这样:
U:(orthogonal)(rotation) , 正交化(旋转) 。
其中U和V为正交矩阵 , 满足如下条件:
defdraw_vector(v1,v0,ax=None):ax=axorplt.gca()arrowprops=dict(arrowstyle='plt.scatter(X[:,0],X[:,1],alpha=0.3)forlength,vectorinzip(pca.explained_variance_,pca.components_):v=vector*3*np.sqrt(length)draw_vector(pca.mean_,pca.mean_+v)plt.axis('equal')
Components_=V
Principalaxesinfeaturespace,representingthedirectionofmaximumvarianceinthedata 。
特征空间中的主轴(主要成分) , 展示数据中最大方差的方向 , (要看你需要 , 需要两个主成分 , n_components=2时就是前两大) , 确定的是主成分的方向 。
Pca.explained_variance_:array,shape(n_components,)
Explained_variance_=(S**2)/(n_samples-1)
Theamountofvarianceexplainedbyeachoftheselectedcomponents.
选择的成分的方差的大小 , 确定的是对应的方向上的大小 , 也就是上图中两个黑色箭头的长短 , 排序是S中方差从大到小的排序 。
Pca.mean_:array,shape(n_feature)
Per-featureempiricalmean,estimatedfromthetrainingset.EqualtoX.mean,
计算出整个训练集中点群的中间点位置 , 即上图中两个黑色箭头的交叉点(箭头的起点) 。
因为我们给定的n_components=2 , 所以上图中有两个向量 , V确定了这两个矢量的方向 , 在计算时我们使用了sqrt(explained_variance_) , 对explained_variance开了根号 , 而explained_variance是由S的平方除以(n_samples-1)得到的 , 所以这里的结果和S是线性的关系 , 从而确定了这两个矢量的大小 , 由此画出了上图中两个黑色的既有长度 , 又有大小的箭头 。 箭头越长说明图上的散点在这个方向上越分散 , 不同的点在这个方向上更能有较大的区别 , 而sigma值更小的 , 表现出来箭头也更短 , 所以长箭头表示的方向比短箭头表示的方向在这组数据中更为主要 , 图中两个黑色箭头互相垂直 。
画箭头的function:
Ax.annotate(self,text,xy,*args,**kwargs)
Annotatethepointxywithtexttext,
ax.annotate('',v1,v0,arrowprops=arrowprops)
直线是点xy到xytext之间 , 即v1和v0这两个点连成一条直线 , 箭头的样式定义在arrowprops这个dictionary里面 。
arrowprops=dict(arrowstyle='arrowstyle箭头的类型 , arrowstyle变成’->’时 , 方向就会反过来 。 Linwidth:线条宽度 , shrink:就是要不要缩短箭头 , 我们这里就不需要了 , color:箭头颜色 。
下面看看当我们把维度降下来 , 变成一个component的时候:此时需要把n_components=1 , 之前的S里面有两个基础向量 , 现在把n_components设置为1后变成了一个 。 在S矩阵里面 , 从左上角到右下角 , 取出第一个sigma 。
pca=PCA(n_components=1)pca.fit(X)X_pca=pca.transform(X)print("originalshape:",X.shape)print("transformedshape:",X_pca.shape)
给原来的矩阵降维 , 这里设置的n_components=1 , 最终维度为1 。
Pca.inverse_transform(X_pca):transformdatabacktoitsoriginalspace.
把降维后的数据还原到原来的空间中 , 这边是把二维降维到一维后的数据还原到二维空间中 , 还原到二维空间后 , 其中一个维度的信息被丢失就不能展示出来 。
defplot_digits(data):fig,axes=plt.subplots(4,10,figsize=(10,4),subplot_kw={'xticks':[],'yticks':[]},gridspec_kw=dict(hspace=0.1,wspace=0.1))fori,axinenumerate(axes.flat):ax.imshow(data[i].reshape(8,8),cmap='binary',interpolation='nearest',clim=(0,16))plot_digits(digits.data)
每个component的方差所占比例:Explained_variance_ratio_=explained_variance_/total_var
每个component的方差所占比例求和:Np.cumsum() 。
推荐阅读
- 丙肝|全国爱肝日丨乙肝可控制,丙肝可治愈,有高危行为人群应主动筛查
- 抑郁症|育儿博主之子因抑郁症身亡,精神崩塌后的父亲和妈妈粉有何风险?
- 辣椒|关于信仰、哲学与科学的迷思|東西堂主
- 有两种谷物被称为“长寿食材”,却很少人当主食吃,从今天要改
- 既是蔬菜也是主食,小小一颗,营养多多!
- 家里的主厨要注意:4种蔬菜吃之前一定要焯水,避免食物中毒
- 怕胖的人主食别总吃米面了,多做这个吃,味道好,低热量高饱腹!
- 种族主义|《纽约时报》煽动对中国的种族主义,美网友群起斥责
- 种族主义|《纽约时报》报道煽动针对中国的种族主义,作者竟然是华人!
- 鸡蛋茶对人体好吗?富硒姐姐主食鸡蛋告诉你
