I want to reconstruct (the approximation of) the original matrix decomposed in SVD. Is there a way to do this without having to convert the V factor
local Matrix
into a DenseMatrix
?
Here is the decomposition based on the documentation (note that the comments are from the doc example)
import org.apache.spark.mllib.linalg.Matrix
import org.apache.spark.mllib.linalg.SingularValueDecomposition
import org.apache.spark.mllib.linalg.Vector
import org.apache.spark.mllib.linalg.distributed.RowMatrix
val data = Array(
Vectors.dense(1.0, 0.0, 7.0, 0.0, 0.0),
Vectors.dense(2.0, 0.0, 3.0, 4.0, 5.0),
Vectors.dense(4.0, 0.0, 0.0, 6.0, 7.0))
val dataRDD = sc.parallelize(data, 2)
val mat: RowMatrix = new RowMatrix(dataRDD)
// Compute the top 5 singular values and corresponding singular vectors.
val svd: SingularValueDecomposition[RowMatrix, Matrix] = mat.computeSVD(5, computeU = true)
val U: RowMatrix = svd.U // The U factor is a RowMatrix.
val s: Vector = svd.s // The singular values are stored in a local dense vector.
val V: Matrix = svd.V // The V factor is a local dense matrix.
To reconstruct the original matrix, I have to compute U * diagonal(s) * transpose(V).
First thing is to convert the singular value vector s
into a diagonal matrix S
.
import org.apache.spark.mllib.linalg.Matrices
val S = Matrices.diag(s)
But when I try to compute U * diagonal(s) * transpose(V): I get the following error.
val dataApprox = U.multiply(S.multiply(V.transpose))
I get the following error:
error: type mismatch; found: org.apache.spark.mllib.linalg.Matrix required: org.apache.spark.mllib.linalg.DenseMatrix
It works if I convert Matrix
V
to a DenseMatrix
Vdense
import org.apache.spark.mllib.linalg.DenseMatrix
val Vdense = new DenseMatrix(V.numRows, V.numCols, V.toArray)
val dataApprox = U.multiply(S.multiply(Vdense.transpose))
Is there a way to get the approx of the original matrix dataApprox
out of the output of svd without this conversion?