我是Apache Spark Scala的新手。你可以帮我做一些操作吗?
我在Spark Scala中有两个分布式矩阵H和Y.
我想计算H的伪逆,然后乘以H和Y.
我该怎么做?
答案 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^T
是M
的转置。矩阵将M^T
乘以M
,然后取反,然后再次将矩阵乘以M^T
。 (我假设M
有实数条目;如果条目是复数,你还必须采用复数共轭。)
快速检查以确保您已正确计算伪逆是检查M^+ M
。它应该是单位矩阵(最多浮点错误)。
另一方面,如果M
具有完整行级别,换句话说M
是mxn且m <= n,则伪逆是
M^+ = M^T (M M^T)^{-1}
要检查在这种情况下是否有正确的伪逆,请右对乘原始矩阵:M M^+
。这应该等于单位矩阵,直到浮点误差。
答案 2 :(得分:0)
矩阵乘法更容易:在Matrix
和multiply
包中有多个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。