主成分分析(PCA)
赖永炫   Tue Dec 27 2016 22:26:55 GMT+0800 (中国标准时间) [ 技术 ]     浏览次数:24222
版权声明: 本文发自http://mocom.xmu.edu.cn,为 赖永炫 老师的个人博文,文章仅代表个人观点。无需授权即可转载,转载时请务必注明作者。

返回 [Spark MLlib入门教程](http://mocom.xmu.edu.cn/article/show/5858ab782b2730e00d70fa08/0/1) ## 二、主成分分析(PCA) ### 1、概念介绍 **主成分分析(PCA)** 是一种对数据进行旋转变换的统计学方法,其本质是在线性空间中进行一个基变换,使得变换后的数据投影在一组新的“坐标轴”上的方差最大化,随后,裁剪掉变换后方差很小的“坐标轴”,剩下的新“坐标轴”即被称为 **主成分(Principal Component)** ,它们可以在一个较低维度的子空间中尽可能地表示原有数据的性质。主成分分析被广泛应用在各种统计学、机器学习问题中,是最常见的降维方法之一。PCA有许多具体的实现方法,可以通过计算协方差矩阵,甚至是通过上文提到的SVD分解来进行PCA变换。 ### 2、PCA变换 MLlib提供了两种进行PCA变换的方法,第一种与上文提到的SVD分解类似,位于`org.apache.spark.mllib.linalg`包下的`RowMatrix`中,这里,我们同样读入上文中提到的`a.mat`文件,对其进行PCA变换: ```scala scala> import org.apache.spark.mllib.linalg.Vectors scala> import org.apache.spark.mllib.linalg.distributed.RowMatrix scala> val data = sc.textFile("a.mat").map(_.split(" ").map(_.toDouble)).map(line => Vectors.dense(line)) data: org.apache.spark.rdd.RDD[org.apache.spark.mllib.linalg.Vector] = MapPartitionsRDD[3] at map at :31 //通过RDD[Vectors]创建行矩阵 scala> val rm = new RowMatrix(data) rm: org.apache.spark.mllib.linalg.distributed.RowMatrix = org.apache.spark.mllib.linalg.distributed.RowMatrix@4397952a //保留前3个主成分 scala> val pc = rm.computePrincipalComponents(3) pc: org.apache.spark.mllib.linalg.Matrix = -0.41267731212833847 -0.3096216957951525 0.1822187433607524 0.22357946922702987 -0.08150768817940773 0.5905947537762997 -0.08813803143909382 -0.5339474873283436 -0.2258410886711858 0.07580492185074224 -0.56869017430423 -0.28981327663106565 0.4399389896865264 -0.23105821586820194 0.3185548657550075 -0.08276152212493619 0.3798283369681188 -0.4216195003799105 0.3952116027336311 -0.19598446496556066 -0.17237034054712738 0.43580231831608096 -0.023441639969444372 -0.4151661847170216 0.468703853681766 0.2288352748369381 0.04103087747663084 ``` 可以看到,主成分矩阵是一个尺寸为(9,3)的矩阵,其中每一列代表一个主成分(新坐标轴),每一行代表原有的一个特征,而`a.mat`矩阵可以看成是一个有4个样本,9个特征的数据集,那么,主成分矩阵相当于把原有的9维特征空间投影到一个3维的空间中,从而达到降维的效果。 可以通过矩阵乘法来完成对原矩阵的PCA变换,可以看到原有的(4,9)矩阵被变换成新的(4,3)矩阵。 ```scala scala> val projected = rm.multiply(pc) projected: org.apache.spark.mllib.linalg.distributed.RowMatrix = org.apache.spark.mllib.linalg.distributed.RowMatrix@2a805829 scala> projected.rows.foreach(println) [12.247647483894383,-2.725468189870252,-5.568954759405281] [2.8762985358626505,-2.2654415718974685,1.428630138613534] [12.284448024169402,-12.510510992280857,-0.16048149283293078] [-1.2537294080109986,-10.15675264890709,-4.8697886049036025] ``` 需要注意的是,MLlib提供的PCA变换方法最多只能处理65535维的数据。 ### 3、“模型式”的PCA变换实现 除了矩阵类内置的PCA变换外,MLlib还提供了一种“模型式”的PCA变换实现,它位于`org.apache.spark.mllib.feature`包下的`PCA`类,它可以接受`RDD[Vectors]`作为参数,进行PCA变换。 该方法特别适用于原始数据是`LabeledPoint`类型的情况,只需取出`LabeledPoint`的`feature`成员(它是`RDD[Vector]`类型),对其做PCA操作后再放回,即可在不影响原有标签情况下进行PCA变换。 首先引入需要使用到的类: ```scala import org.apache.spark.mllib.feature.PCA import org.apache.spark.mllib.regression.LabeledPoint ``` 依然使用前文的`a.mat`矩阵,为了创造出`LabeledPoint`,我们为第一个样本标注标签为`0.0`,其他为`1.0`。 ```scala scala> val data = sc.textFile("a.mat").map(_.split(" ").map(_.toDouble)).map(line => { | LabeledPoint( if(line(0) > 1.0) 1.toDouble else 0.toDouble, Vectors.dense(line) ) | }) data: org.apache.spark.rdd.RDD[org.apache.spark.mllib.regression.LabeledPoint] = MapPartitionsRDD[16] at map at :34 scala> data.foreach(println) (0.0,[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0]) (1.0,[6.0,4.0,2.0,1.0,3.0,4.0,2.0,1.0,5.0]) (1.0,[5.0,6.0,7.0,8.0,9.0,0.0,8.0,6.0,7.0]) (1.0,[9.0,0.0,8.0,7.0,1.0,4.0,3.0,2.0,1.0]) ``` 随后,创建一个`PCA`类的对象,在构造器中给定主成分个数为3,并调用其`fit`方法来生成一个`PCAModel`类的对象`pca`,该对象保存了对应的主成分矩阵: ```scala scala> val pca = new PCA(3).fit(data.map(_.features)) pca: org.apache.spark.mllib.feature.PCAModel = org.apache.spark.mllib.feature.PCAModel@68602c26 ``` 对于`LabeledPoint`型的数据来说,可使用`map`算子对每一条数据进行处理,将`features`成员替换成PCA变换后的特征即可: ```scala scala> val projected = data.map(p => p.copy(features = pca.transform(p.features))) projected: org.apache.spark.rdd.RDD[org.apache.spark.mllib.regression.LabeledPoint] = MapPartitionsRDD[20] at map at :39 scala> projected.foreach(println) (0.0,[12.247647483894383,-2.725468189870252,-5.568954759405281]) (1.0,[2.8762985358626505,-2.2654415718974685,1.428630138613534]) (1.0,[12.284448024169402,-12.510510992280857,-0.16048149283293078]) (1.0,[-1.2537294080109986,-10.15675264890709,-4.8697886049036025]) ```


自动标签  : 成分   分析   PCA   矩阵   主成分   变换   进行PCA变换   方法   可以   数据   进行   特征   a.mat   原有    

更多 [ 技术 ] 文章

请先 登录, 查看相关评论.