web-dev-qa-db-fra.com

Multiplication de matrice dans Apache Spark

J'essaie d'effectuer une multiplication de matrice en utilisant Apache Spark et Java.

J'ai 2 questions principales:

  1. Comment créer un RDD qui peut représenter une matrice dans Apache Spark?
  2. Comment multiplier deux de ces RDD?
19
Jigar

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]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]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 .

42
zero323