2015-11-06 21 views
12

Ich versuche, Matrix-Multiplikation mit Apache Spark und Java durchzuführen.Matrix Multiplikation in Apache Spark

Ich habe 2 Hauptfragen:

  1. Wie RDD erstellen, die Matrix in Apache Funken darstellen kann?
  2. Wie multipliziert man zwei solche RDDs?

Antwort

27

Alle auf den Eingangsdaten und Dimensionen hängt aber im Allgemeinen, was Sie wollen, ist kein RDD aber eine der verteilten Datenstrukturen aus org.apache.spark.mllib.linalg.distributed. In diesem Moment gibt es vier verschiedene Implementierungen des DistributedMatrix

  • IndexedRowMatrix - kann von einem RDD[IndexedRow] direkt erstellt werden, in dem IndexedRow der Zeilenindex bestehen und 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 - ähnlich wie IndexedRowMatrix aber ohne aussagekräftige Zeilenindizes. Kann direkt aus RDD[org.apache.spark.mllib.linalg.Vector]

    import org.apache.spark.mllib.linalg.distributed.RowMatrix 
    
    val rowMatrix = new RowMatrix(rows.map(_.vector))  
    
  • BlockMatrix geschaffen werden - kann von RDD[((Int, Int), Matrix)] erstellt werden, in dem ersten Element des Tupels Koordinaten des Blocks enthält, und das zweite ist ein lokaler org.apache.spark.mllib.linalg.Matrix

    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 - kann von RDD[MatrixEntry] erstellt werden, wobei MatrixEntry aus Zeile, Spalte und Wert besteht.

    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) 
    

ersten beiden Implementierungen unterstützen Multiplikation mit einem lokalen Matrix:

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

und die dritte kann durch einen anderen BlockMatrix solange Anzahl der Spalten pro Block in dieser Matrix Einstimmungen multipliziert werden Anzahl der Zeilen pro Block der anderen Matrix. CoordinateMatrix nicht Multiplikationen unterstützen, ist aber recht einfach auf andere Arten von verteilten Matrizen zu erstellen und zu transformieren:

blockMatrix.multiply(coordinateMatrix.toBlockMatrix(3, 3)) 

Jeder Typ hat seine eigenen Stärken und Schwächen, und es gibt einige zusätzliche Faktoren zu berücksichtigen, wenn Sie spärlich verwenden oder dichte Elemente (Vectors oder Block Matrices). Die Multiplikation mit einer lokalen Matrix ist normalerweise vorzuziehen, da kein teures Mischen erforderlich ist.

Weitere Informationen zu jedem Typ finden Sie unter the MLlib Data Types guide.

+2

Dies ist eine großartige Zusammenfassung für das Erstellen der verschiedenen Matrixtypen - ich denke, ich werde dies zu einem Lesezeichen hinzufügen! –