Spark分布式矩阵乘法和伪逆计算
Spark distributed matrix multiply and pseudo-inverse calculating
我是 Apache Spark Scala 的新手。你能帮我做一些手术吗?
我在 Spark Scala 中有两个分布式矩阵 H 和 Y。
我想计算 H 的伪逆,然后将 H 和 Y 相乘。
我该怎么做?
矩阵乘法是比较简单的:org.apache.spark.mllib.linalg
和[=14包中有几个Matrix
实现了multiply
方法=].选择最适合您的需求。
我在 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
不幸的是,需要进行大量从矩阵到数组的转换等等。如果您需要完全分布式的实现,请尝试使用 DistributedMatrix
而不是 DenseMatrix
。如果没有,也许在这里使用 Breeze 更可取。
这里是逆向的实现。
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)
}
要计算非方矩阵的伪逆,您需要能够计算转置(简单)和矩阵逆(其他人已经提供了该功能)。有两种不同的计算,具体取决于 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^+
。那应该等于单位矩阵,直到浮点误差。
我是 Apache Spark Scala 的新手。你能帮我做一些手术吗?
我在 Spark Scala 中有两个分布式矩阵 H 和 Y。
我想计算 H 的伪逆,然后将 H 和 Y 相乘。
我该怎么做?
矩阵乘法是比较简单的:org.apache.spark.mllib.linalg
和[=14包中有几个Matrix
实现了multiply
方法=].选择最适合您的需求。
我在 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
不幸的是,需要进行大量从矩阵到数组的转换等等。如果您需要完全分布式的实现,请尝试使用 DistributedMatrix
而不是 DenseMatrix
。如果没有,也许在这里使用 Breeze 更可取。
这里是逆向的实现。
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)
}
要计算非方矩阵的伪逆,您需要能够计算转置(简单)和矩阵逆(其他人已经提供了该功能)。有两种不同的计算,具体取决于 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^+
。那应该等于单位矩阵,直到浮点误差。