降维是减少所需要考虑变量个数的过程。它能从原始的有噪音的特征或压缩数据中提取隐藏特征,同时保留原有的结构,MLlib提供RowMatrix用于降维。
1.奇异值分解(SVD)
奇异值分解将一个矩阵分解成为U、∑和V3个子矩阵,它们满足如下几点。
1)U是一个正交矩阵,其每一个列被称为一个左奇异向量。
2)∑是一个对角矩阵,其对角线上元素非负且按降序排列,对角线上的元素被称为奇异值。
3)V是一个正交矩阵,其每一个列被称为一个右奇异向量。
对于大的矩阵,通常并不需要进行完全的因式分解,而只需要求值靠前的部分奇异值和对应的奇异向量即可。这样能降低存储需求,去噪声而且降低了子矩阵的阶数。
假设保留前k个奇异值,那么相应的子矩阵的维度如下。
U:m×k
∑:k×k
V:n×k
(1)性能分析
假设n比m要小。奇异值和右奇异矩阵可从格拉姆矩阵ATA的共轭值和共轭向量的求解而得出。如果用户通过输入computeU这一参数指定了需求解左奇异矩阵U,则该矩阵可通过U=A(VS-1)这一矩阵乘积得出。实际计算时,程序会自动根据计算的复杂度来选择不同的方法来得出结果。
如果n较小或者k相对n来说比较大,那么会先计算格拉姆矩阵,然后在driver本地计算它的前K个奇异值和特征值。其代价包括一次在driver和各个executor本地上的一次复杂度为O(n2)的存储,外加一次driver本地进行的复杂度为O(n2k)的存储。否则,我们将分布式计算,然后将其作为输入通过ARPACK来计算(ATA)的前k各特征值和特征矩阵。ARPACK的计算在driver上进行。这个过程的时间复杂度为O(k),在每个executor上存储的复杂度为O(n),以及driver上存储的复杂度为O(nk)。
(2)SVD示例程序
MLlib可对行矩阵进行SVD运算。RowMatrix类包含了该类矩阵。如【例4-64】所示。
【例4-64】SVD应用模型示例。
import org.apache.spark.mllib.linalg.Matrix
import org.apache.spark.mllib.linalg.distributed.RowMatrix
import org.apache.spark.mllib.linalg.SingularValueDecomposition
val mat:RowMatrix=...
//计算前二十个奇异值和对应的奇异向量
val svd:SingularValueDecomposition[RowMatrix,Matrix]=mat.computeSVD(20,computeU=true)
val U:RowMatrix=svd.U//U是一个RowMatrix(www.xing528.com)
val s:Vector=svd.s//奇异值被存储在一个本地密集向量中
val V:Matrix=svd.V//V是一个本地密集矩阵
如果U定义为IndexedRowMatrix,则以上代码同样适用于IndexedRowMatrix。
2.主成分分析
主成份分析是使用统计方法求矩阵一个旋转的方法。该旋转需要能最大化矩阵第一坐标的方差,这同时也将使得后续坐标的方差也最大化。旋转后矩阵的每一个列被称作一个主成份。主成份分析被广泛用于降维中。
MLlib的SVD计算适用于行数远多于列数的矩阵。在矩阵中每一行代表一条面向行格式的存储记录。
【例4-65】演示如何对一个RowMatrix进行主成份分析,然后利用分析结果将原始的向量投影到一个低维空间中。
【例4-65】RowMatrix主成分分析应用模型示例。
【例4-66】演示了如何在源向量上计算主成分和使用它们来将项目相关的向量降到低维空间,并同时保持标签。
【例4-66】源向量(source vectors)主成分分析应用模型示例。
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.mllib.feature.PCA
val data:RDD[LabeledPoint]=...
val pca=new PCA(10).fit(data.map(_.features))
val projected=data.map(p=>p.copy(features=pca.transform(p.features)))
【例4-66】演示了如何在源向量上计算主成分和使用它们来将项目相关的向量降到低维空间,并同时保持标签。
【例4-66】源向量(source vectors)主成分分析应用模型示例。
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.mllib.feature.PCA
val data:RDD[LabeledPoint]=...
val pca=new PCA(10).fit(data.map(_.features))
val projected=data.map(p=>p.copy(features=pca.transform(p.features)))
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。