J'essaie d'effectuer une multiplication de matrice en utilisant Apache Spark et Java.
J'ai 2 questions principales:
Tout dépend des données d'entrée et des dimensions, mais en règle générale, ce que vous voulez n'est pas un RDD
mais l'une des structures de données distribuées de org.Apache.spark.mllib.linalg.distributed
. En ce moment, il fournit quatre implémentations différentes de DistributedMatrix
IndexedRowMatrix
- peut être créé directement à partir d'un RDD[IndexedRow]
où IndexedRow
se compose d'un index de ligne et org.Apache.spark.mllib.linalg.Vector
import org.Apache.spark.mllib.linalg.{Vectors, Matrices}
import org.Apache.spark.mllib.linalg.distributed.{IndexedRowMatrix,
IndexedRow}
val rows = sc.parallelize(Seq(
(0L, Array(1.0, 0.0, 0.0)),
(0L, Array(0.0, 1.0, 0.0)),
(0L, Array(0.0, 0.0, 1.0)))
).map{case (i, xs) => IndexedRow(i, Vectors.dense(xs))}
val indexedRowMatrix = new IndexedRowMatrix(rows)
RowMatrix
- similaire à IndexedRowMatrix
mais sans indice de ligne significatif. Peut être créé directement à partir de RDD[org.Apache.spark.mllib.linalg.Vector]
import org.Apache.spark.mllib.linalg.distributed.RowMatrix
val rowMatrix = new RowMatrix(rows.map(_.vector))
BlockMatrix
- peut être créé à partir de RDD[((Int, Int), Matrix)]
où le premier élément du Tuple contient les coordonnées du bloc et le second est un org.Apache.spark.mllib.linalg.Matrix
local
val eye = Matrices.sparse(
3, 3, Array(0, 1, 2, 3), Array(0, 1, 2), Array(1, 1, 1))
val blocks = sc.parallelize(Seq(
((0, 0), eye), ((1, 1), eye), ((2, 2), eye)))
val blockMatrix = new BlockMatrix(blocks, 3, 3, 9, 9)
CoordinateMatrix
- peut être créé à partir de RDD[MatrixEntry]
où MatrixEntry
se compose d'une ligne, d'une colonne et d'une valeur.
import org.Apache.spark.mllib.linalg.distributed.{CoordinateMatrix,
MatrixEntry}
val entries = sc.parallelize(Seq(
(0, 0, 3.0), (2, 0, -5.0), (3, 2, 1.0),
(4, 1, 6.0), (6, 2, 2.0), (8, 1, 4.0))
).map{case (i, j, v) => MatrixEntry(i, j, v)}
val coordinateMatrix = new CoordinateMatrix(entries, 9, 3)
Les deux premières implémentations prennent en charge la multiplication par un Matrix
local:
val localMatrix = Matrices.dense(3, 2, Array(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
indexedRowMatrix.multiply(localMatrix).rows.collect
// Array(IndexedRow(0,[1.0,4.0]), IndexedRow(0,[2.0,5.0]),
// IndexedRow(0,[3.0,6.0]))
et la troisième peut être multipliée par un autre BlockMatrix
tant que le nombre de colonnes par bloc dans cette matrice correspond au nombre de lignes par bloc de l'autre matrice. CoordinateMatrix
ne prend pas en charge les multiplications mais est assez facile à créer et à transformer en d'autres types de matrices distribuées:
blockMatrix.multiply(coordinateMatrix.toBlockMatrix(3, 3))
Chaque type a ses propres côtés forts et faibles et il existe des facteurs supplémentaires à prendre en compte lorsque vous utilisez des éléments clairsemés ou denses (Vectors
ou block Matrices
). La multiplication par une matrice locale est généralement préférable car elle ne nécessite pas de réarrangement coûteux.
Vous pouvez trouver plus de détails sur chaque type dans le guide MLlib Data Types .