降维操作1-奇异值分解(SVD)

降维(Dimensionality Reduction)

是机器学习中的一种重要的特征处理手段,
它可以减少计算过程中考虑到的随机变量(即特征)的个数,
其被广泛应用于各种机器学习问题中,用于消除噪声、对抗数据稀疏问题。
它在尽可能维持原始数据的内在结构的前提下,得到一组描述原数据的,低维度的隐式特征(或称主要特征)。

MLlib机器学习库提供了两个常用的降维方法:
奇异值分解(Singular Value Decomposition,SVD) 和 主成分分析(Principal Component Analysis,PCA)。


一、奇异值分解(SVD)
奇异值分解(SVD)来源于代数学中的矩阵分解问题,
对于一个方阵来说,我们可以利用矩阵特征值和特征向量的特殊性质(矩阵点乘特征向量等于特征值数乘特征向量),
通过求特征值与特征向量来达到矩阵分解的效果。

 

package org.onepiece.bigdata.windows.spark_ML

import org.apache.spark.sql.SparkSession
import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.mllib.linalg.distributed.RowMatrix
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.mllib.feature.PCA

/*
* 降维
* 降维是机器学习中的一种重要的特征处理手段。
* 它可以减少计算过程中考虑到随机变量(即特征)的个数,
* 其被广泛应用于各种机器学习问题中,用于消除噪声、对抗数据稀疏问题。
* */
object ml_5_DimensionalityReduction {

  /*
  * 奇异值分解
  * */
  def test1_SVD_Singular_Value_Decomposition(): Unit = {
    val spark = SparkSession.builder()
      .master("local[*]").appName("spark-ml")
      .getOrCreate()

    /*
    val data = spark.sparkContext.textFile("F:\\files\\spark_ml\\svd.data")
    val dv = data
      .map(_.split(" ").map(_.toDouble))
      .map(line => Vectors.dense(line))
    println(dv.foreach(println))
    */

    val array = Array(
      "1 2 3 4 5 6 7 8 9",
      "5 6 7 8 9 0 8 6 7",
      "9 0 8 7 1 4 3 2 1",
      "6 4 2 1 3 4 2 1 5"
    )
    //创建RDD[Vectors]向量
    val dv2 = spark.sparkContext.parallelize(array)
      .map(x => x.split(" ").map(y => y.toDouble))
      .map(line => Vectors.dense(line))
    println(dv2.foreach(println))
    /*
[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0]
[9.0,0.0,8.0,7.0,1.0,4.0,3.0,2.0,1.0]
[6.0,4.0,2.0,1.0,3.0,4.0,2.0,1.0,5.0]
[5.0,6.0,7.0,8.0,9.0,0.0,8.0,6.0,7.0]
()
    * */

//通过RDD[Vectors]创建行矩阵 val rm = new RowMatrix(dv2) println(rm.rows.foreach(x => println(x))) /* [5.0,6.0,7.0,8.0,9.0,0.0,8.0,6.0,7.0] [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0] [9.0,0.0,8.0,7.0,1.0,4.0,3.0,2.0,1.0] [6.0,4.0,2.0,1.0,3.0,4.0,2.0,1.0,5.0] () * */

//调用RowMatrix自带的computeSVD()方法计算分解结果 val svd = rm.computeSVD(3, true) //保留前3个奇异值 println(svd) /* SingularValueDecomposition(org.apache.spark.mllib.linalg.distributed.RowMatrix@30e6a763,[28.741265581939565,10.847941223452608,7.089519467626695],-0.32908987300830383 0.6309429972945555 0.16077051991193514 -0.2208243332000108 -0.1315794105679425 -0.2368641953308101 -0.35540818799208057 0.39958899365222394 -0.147099615168733 -0.37221718676772064 0.2541945113699779 -0.25918656625268804 -0.3499773046239524 -0.24670052066546988 -0.34607608172732196 -0.21080978995485605 0.036424486072344636 0.7867152486535043 -0.38111806017302313 -0.1925222521055529 -0.09403561250768909 -0.32751631238613577 -0.3056795887065441 0.09922623079118417 -0.3982876638452927 -0.40941282445850646 0.26805622896042314 ) * */

//奇异值向量 println(svd.s) /* [28.741265581939565,10.847941223452608,7.089519467626695] * */

//右奇异矩阵 println(svd.V) /* -0.32908987300830383 0.6309429972945555 0.16077051991193514 -0.2208243332000108 -0.1315794105679425 -0.2368641953308101 -0.35540818799208057 0.39958899365222394 -0.147099615168733 -0.37221718676772064 0.2541945113699779 -0.25918656625268804 -0.3499773046239524 -0.24670052066546988 -0.34607608172732196 -0.21080978995485605 0.036424486072344636 0.7867152486535043 -0.38111806017302313 -0.1925222521055529 -0.09403561250768909 -0.32751631238613577 -0.3056795887065441 0.09922623079118417 -0.3982876638452927 -0.40941282445850646 0.26805622896042314 * */

//左奇异矩阵(svd.U) println(svd.U.numRows()) //4 println(svd.U.numCols()) //3 svd.U.rows.foreach(println) /* [-0.6745646555920789,-0.11656888718737751,-0.7215920740644672] [-0.5293129129905766,-0.5447516959291742,0.528523087995918] [-0.31018926198064944,0.09038775073125829,0.39831323610336433] [-0.4105764086248388,0.8255224641643187,0.20326039960470754] * */

/* 由于限定了前三个奇异值, 所以奇异值向量s包含三个从大到小排列的奇异值, 而右奇异矩阵V中的每一列都代表了对应的右奇异向量。 在实际应用中,只需要V和S两个成员。即可通过矩阵计算达到降维的效果。 * */ } }

 

posted @ 2020-10-15 00:00  茗::流  阅读(496)  评论(0)    收藏  举报
如有雷同,纯属参考。如有侵犯你的版权,请联系我。