Spark分布式矩阵乘法和伪逆计算

时间:2015-04-25 19:15:35

标签: matrix apache-spark distributed-computing

我是Apache Spark Scala的新手。你可以帮我做一些操作吗?

我在Spark Scala中有两个分布式矩阵H和Y.

我想计算H的伪逆,然后乘以H和Y.

我该怎么做?

3 个答案:

答案 0 :(得分:1)

这是反向的实现。

import org.apache.spark.mllib.linalg.{Vectors,Vector,Matrix,SingularValueDecomposition,DenseMatrix,DenseVector}
import org.apache.spark.mllib.linalg.distributed.RowMatrix

def computeInverse(X: RowMatrix): DenseMatrix = {
  val nCoef = X.numCols.toInt
  val svd = X.computeSVD(nCoef, computeU = true)
  if (svd.s.size < nCoef) {
    sys.error(s"RowMatrix.computeInverse called on singular matrix.")
  }

  // Create the inv diagonal matrix from S 
  val invS = DenseMatrix.diag(new DenseVector(svd.s.toArray.map(x => math.pow(x,-1))))

  // U cannot be a RowMatrix
  val U = new DenseMatrix(svd.U.numRows().toInt,svd.U.numCols().toInt,svd.U.rows.collect.flatMap(x => x.toArray))

  // If you could make V distributed, then this may be better. However its alreadly local...so maybe this is fine.
  val V = svd.V
  // inv(X) = V*inv(S)*transpose(U)  --- the U is already transposed.
  (V.multiply(invS)).multiply(U)
  }

答案 1 :(得分:1)

要计算非平方矩阵的伪逆,您需要能够计算转置(简单)和矩阵逆(其他已提供该功能)。有两种不同的计算方法,具体取决于M是否具有完整列级别或完整行级别。

完整列排名意味着矩阵的列是线性独立的,这要求列数小于或等于行数。 (在病态情况下,m> = n的mxn矩阵可能仍然没有完整的列级别,但我们忽略了统计不可能性。如果在您的情况下有可能,下面的矩阵求逆步骤将失败。)对于完整列排名,伪逆是

M^+ = (M^T M)^{-1} M^T

其中M^TM的转置。矩阵将M^T乘以M,然后取反,然后再次将矩阵乘以M^T。 (我假设M有实数条目;如果条目是复数,你还必须采用复数共轭。)

快速检查以确保您已正确计算伪逆是检查M^+ M。它应该是单位矩阵(最多浮点错误)。

另一方面,如果M具有完整行级别,换句话说M是mxn且m <= n,则伪逆是

M^+ = M^T (M M^T)^{-1}

要检查在这种情况下是否有正确的伪逆,请右对乘原始矩阵:M M^+。这应该等于单位矩阵,直到浮点误差。

答案 2 :(得分:0)

矩阵乘法更容易:在Matrixmultiply包中有多个org.apache.spark.mllib.linalg实施,org.apache.spark.mllib.linalg.distributed方法。挑选最符合您需求的产品。

我还没有在Spark API中的任何地方看到(伪)逆。但是RowMatrix能够计算奇异值分解,它可以用来计算矩阵的逆。这是一个非常天真的实现,受How can we compute Pseudoinverse for any Matrix的启发(警告:2x2矩阵的维度是硬编码的):

val m = new RowMatrix(sc.parallelize(Seq(Vectors.dense(4, 3), Vectors.dense(3, 2))))
val svd = m.computeSVD(2, true)
val v = svd.V
val sInvArray = svd.s.toArray.toList.map(x => 1.0 / x).toArray
val sInverse = new DenseMatrix(2, 2, Matrices.diag(Vectors.dense(sInvArray)).toArray)
val uArray = svd.U.rows.collect.toList.map(_.toArray.toList).flatten.toArray
val uTranspose = new DenseMatrix(2, 2, uArray) // already transposed because DenseMatrix is column-major
val inverse = v.multiply(sInverse).multiply(uTranspose)
  // -1.9999999999998297  2.999999999999767    
  // 2.9999999999997637   -3.9999999999996767    

不幸的是,很多从Matrix到Array的转换等都是必要的。如果您需要完全分布式实施,请尝试使用DistributedMatrix代替DenseMatrix。如果没有,可以在这里使用Breeze。