spark中利用向量及其矩阵求逆

object DemoScala {
  def computeInverse(X: RowMatrix): DenseMatrix = {//RowMatrix是一个m*n的矩阵 如果可以求逆需要m==n
     val nCoef = X.numCols.toInt

    /***
      *   computeSVD(k: Int,computeU: Boolean = false,rCond: Double = 1e-9)
      *   返回的是SingularValueDecomposition[RowMatrix, Matrix](U, s, V). U = null if computeU = false.
      *   U                 is a RowMatrix of size m x k that satisfies U' * U = eye(k),
      *   s                 is a Vector of size k, holding the singular values in descending order,
      *   V                  is a Matrix of size n x k that satisfies V' * V = eye(k).
      *
      */

    val svd = X.computeSVD(nCoef, computeU = true)//此处设置的k=nCoef
    if (svd.s.size < nCoef) {
      sys.error(s"RowMatrix.computeInverse called on singular matrix.")
    }
    println("svd.s:--------------------------------------------")
    println(svd.s)
    val invS = DenseMatrix.diag(new DenseVector(svd.s.toArray.map(x => math.pow(x,-1))))
    println("svd.U--------------------------------------------")
    println(svd.U)
    val U = new DenseMatrix(svd.U.numRows().toInt,svd.U.numCols().toInt,svd.U.rows.collect.flatMap(x => x.toArray))


    val V = svd.V
    println("DenseMatrix:U ---------------------------------------------------")
   println(U)
    println("DenseMatrix:invS------------------------------")
    println(invS)
    println("Matrix:V------------------------------")
    println(V)
    (V.multiply(invS)).multiply(U)
  }
  def main(args: Array[String]): Unit = {
    val sparkConf: SparkConf = new SparkConf().setAppName("Matrix").setMaster("local")
    val sc=new SparkContext(sparkConf)
    val res=sc.textFile("data/spark_matrix.txt")//读取文件中的数据
    val res0=res.map(line=> line.split("\t").map(_.toDouble))//将所有数据分割然后把String转为Double类型
      val res1=res0.map(line=>Vectors.dense(line))//把每行数据转为一个向量,因为RowMatrix(RDD[Vector]),Vectors.dense()是转为Vector
    val rowMatrix=new RowMatrix(res1)
    val res2=computeInverse(rowMatrix)
    println("所求的逆矩阵-----------------------------------------")
     println(res2)
     }
 }

先说明几点:

  1. RowMatrix的computeSVD方法,由于求逆矩阵,因此我们要求的是m*n矩阵中m==n,如果用这个方法不是求逆矩阵,那么你可以随意输入一个m*n的矩阵其中m不一定等于n,没有要求的。
  2. 代码中已经对computeSVD这个方法进行了介绍,自行参考就可以
  3. val invS = DenseMatrix.diag(new DenseVector(svd.s.toArray.map(x => math.pow(x,-1))))这句代码是把向量s中的每个元素求指数,然后diag()是生成一个以其向量为对角线上元素的一个k*k矩阵,非主对角线的元素为0。
  4. val U = new DenseMatrix(svd.U.numRows().toInt,svd.U.numCols().toInt,svd.U.rows.collect.flatMap(x => x.toArray))由于U是一个RowMatrix,我们需要转为DenseMatrix,后面需要。U是RowMatrix类型的其中有变量是val rows: RDD[Vector],然后对其进行flatMap操作将Vector变为Array,这是DenseMatrix类class DenseMatrix @Since("1.3.0") (
    @Since("1.0.0") val numRows: Int,
    @Since("1.0.0") val numCols: Int,
    @Since("1.0.0") val values: Array[Double],
    @Since("1.3.0") override val isTransposed: Boolean)
  5. (V.multiply(invS)).multiply(U);multiply是Matrix类的方法其参数是DenseMatrix,这就是为什么把U,及其s转为DenseMatrix的原因
  6. n*k k*k m*k 只有k=m才可以相乘的,因为求逆所以m=n即方阵才有逆
svd.s:--------------------------------------------
[5.195206718911746,1.8916695252140212,1.0857640198140848,0.24952096164831863,0.14826765186592328,0.006329424624398848,0.005099595949648716,7.028271117586527E-6,6.244618758988449E-7]
svd.U--------------------------------------------
org.apache.spark.mllib.linalg.distributed.RowMatrix@29050de5

DenseMatrix:U ---------------------------------------------------
-0.3180577037550629   -0.33414971642156166  -0.343846652401676    ... (9 total)
0.34871749476884045   0.3746944088757517    0.2520236157443845    ...
0.26817682618737415   0.0747542145534114    0.29677049743220085   ...
0.23952876419210223   0.015131380275699935  0.07142912621949338   ...
-0.4660020986917647   -0.03489307690519072  0.08166117315464427   ...
-0.35613082938673524  -0.3526619842271069   0.45401382105939575   ...
0.29008478389195763   -0.6300314994524747   0.4814057789561659    ...
0.2815939943611738    -0.2811391638024361   -0.4420240774670674   ...
0.3747879097936675    -0.3748584836430382   -0.29176366195315495  ...
DenseMatrix:invS------------------------------
0.19248512217228436  0.0                 0.0                 ... (9 total)
0.0                  0.5286335624013719  0.0                 ...
0.0                  0.0                 0.9210104421872718  ...
0.0                  0.0                 0.0                 ...
0.0                  0.0                 0.0                 ...
0.0                  0.0                 0.0                 ...
0.0                  0.0                 0.0                 ...
0.0                  0.0                 0.0                 ...
0.0                  0.0                 0.0                 ...
Matrix:V------------------------------
-0.5763914576526998   0.002692992993133281  ... (9 total)
-0.374772970789165    0.4543280054711349    ...
-0.3605213899998586   -0.5340545202180697   ...
-0.20836671014674382  0.16633206461012237   ...
-0.16537734994208692  -0.08136930724181506  ...
-0.3652388995949415   0.4304321173753203    ...
-0.2062527920178446   0.161942506401787     ...
-0.35114201727468736  -0.505934820978886    ...
-0.16533510578206906  -0.08130211966914677  ...
所求的逆矩阵-----------------------------------------
7156.498250248537    -7155.147543761673   -5344.050701536773   ... (9 total)
-204670.12201889214  204703.69577035436   152939.9311283726    ...
-204483.02108904213  204605.87033375094   152697.1405484081    ...
-204483.02461282237  204483.01923899818   152819.99757495752   ...
-234984.97851600806  234984.9736407118    202385.71875581008   ...
204844.55221107733   -204878.15859247462  -153070.27173565445  ...
204642.95913778522   -204642.9537593831   -152939.52467475695  ...
204642.9555184821    -204771.82344239714  -152810.64889889368  ...
235188.87068007782   -235188.8658008305   -202564.11400210502  ...

通过这个问题我想到了另一个问题就是如何把一个m*n的矩阵变为m*m的矩阵,通过看源码了解了一些 但是我还是无法实现,希望大家可以帮忙解决写个代码看看。
比如上面代码的svd.U是一个RowMatrix矩阵,是m*k的我想变为m*m,无非两种情况要不是增加列要不是 删除列。

class CoordinateMatrix @Since("1.0.0") (
    @Since("1.0.0") val entries: RDD[MatrixEntry],
    private var nRows: Long,
    private var nCols: Long) extends DistributedMatrix 

以下指示自己表达想法 不是实现的 看看就可以了:

1.第一种方法: RowMatrix可以转为CoordinateMatrix ,然后里面希望可以有一个add的方法就是对其变量val entries: RDD[MatrixEntry]实现增加,case class MatrixEntry(i: Long, j: Long, value: Double)
这个是MatrixEntry的结构,我们只需要将增加case成MatrixEntry格式就可以,分别代表(行坐标,列坐标,值),之后便可以转为RowMatrix或者DenseMatrix等类型
2. 另外一种方法:`class RowMatrix @Since(“1.0.0”) (
@Since(“1.0.0”) val rows: RDD[Vector],
private var nRows: Long,
private var nCols: Int) extends DistributedMatrix with Logging
———————————-
class DenseMatrix @Since(“1.3.0”) (
@Since(“1.0.0”) val numRows: Int,
@Since(“1.0.0”) val numCols: Int,
@Since(“1.0.0”) val values: Array[Double],
@Since(“1.3.0”) override val isTransposed: Boolean) extends Matrix

val values: Array[Double]
* For example, the following matrix
* {{{
* 1.0 2.0
* 3.0 4.0
* 5.0 6.0
* }}}
* is stored as [1.0, 3.0, 5.0, 2.0, 4.0, 6.0]
* isTransposed默认为false时候是上面存储,如果为true则是row major

对DenseMatrix类型操作,new DenseMatrix(svd.U.numRows().toInt,svd.U.numCols().toInt,svd.U.rows.collect.flatMap(x => x.toArray))利用存储的这个数组中的值去构造,svd.U.rows.collect.flatMap(x => x.toArray)其中U是RowMatrix类型我们可以取去rows,然后变为一个Array[Double]类型的,借鉴下面的代码,我们将U变为Array[Double]后,然后按照下面的思想,当列的循环到了k时候 里面行循环我们都要赋值为自己想要赋值的值 或者0之类的了。

这是RowMatrix种的一个方法
import breeze.linalg.{DenseMatrix => BDM, DenseVector => BDV, SparseVector => BSV, axpy => brzAxpy,
svd => brzSvd, MatrixSingularException, inv}
private def triuToFull(n: Int, U: Array[Double]): Matrix = {
    val G = new BDM[Double](n, n)//DenseMatrix => BDM

    var row = 0
    var col = 0
    var idx = 0
    var value = 0.0
    while (col < n) {
      row = 0
      while (row < col) {
        value = U(idx)
        G(row, col) = value
        G(col, row) = value
        idx += 1
        row += 1
      }
      G(col, col) = U(idx)
      idx += 1
      col +=1
    }

    Matrices.dense(n, n, G.data)
  }

我自己已经写了一点了 可是不知道如何下手了 因为对这个存储不太了解还需要仔细看然后才知道如何从数组里面取值赋值给G

   //把U是m*k的矩阵变为m*m,此时的m>k只需要增加列就可以----------start------------
    val nrows=svd.U.numRows().toInt   //U是m*k的矩阵即9*7   nrows=9
    var ncols=svd.U.numCols().toInt   //ncols=7
    var value = 0.0
    var col=0
    var index=0
   val array:Array[Double]=svd.U.rows.collect.flatMap(x => x.toArray)
    val G = new BDM[Double](nrows, nrows)
    while (col < nrows) {
     var row=0


      while (row < nrows) {
        //还给加条件,想办法是的取数值时候跟new DenseMatrix原理一样 然后不能一一对应的赋值为0
        G(row, col) = array(index)
        row += 1
        index+=1
      }
    col+= 1

    }
    //------------------------end---------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值