2015-11-06 24 views
12

Próbuję wykonać mnożenie macierzy za pomocą Apache Spark i Java.Mnożenie macierzy w Apache Spark

Mam 2 główne pytania:

  1. Jak stworzyć RDD, które mogą reprezentować matrycy w Apache Spark?
  2. Jak pomnożyć dwa takie RDD?

Odpowiedz

27

Wszystko zależy od danych wejściowych i wymiarach, ale ogólnie rzecz biorąc to, co chcesz nie jest RDD ale jednym z rozproszonych struktur danych z org.apache.spark.mllib.linalg.distributed. W tym momencie dostarcza cztery różne implementacje DistributedMatrix

  • IndexedRowMatrix - może być utworzony bezpośrednio w RDD[IndexedRow] gdzie IndexedRow składa się z indeksem wiersza a 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 - podobnie IndexedRowMatrix bez znaczące indeksy wierszy. Mogą być tworzone bezpośrednio z RDD[org.apache.spark.mllib.linalg.Vector]

    import org.apache.spark.mllib.linalg.distributed.RowMatrix 
    
    val rowMatrix = new RowMatrix(rows.map(_.vector))  
    
  • BlockMatrix - mogą być tworzone z RDD[((Int, Int), Matrix)] gdzie pierwszym elementem krotki zawierający współrzędne bloku, a drugi jest lokalnym 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 - można utworzyć z RDD[MatrixEntry], gdzie MatrixEntry składa się z wiersza, kolumny i wartości.

    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) 
    

Pierwsze dwie implementacje wspierać mnożenie przez miejscowego 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])) 

a trzeci może być pomnożona przez innego BlockMatrix tak długo, jak liczba kolumn na blok w tym meczów macierzy liczba wierszy na blok innej macierzy. CoordinateMatrix nie obsługuje mnożenia, ale jest dość łatwo tworzyć i przekształcać się w inne rodzaje matryc rozproszonych:

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

Każdy typ ma swoje mocne i słabe strony i istnieje kilka dodatkowych czynników do rozważenia podczas korzystania skąpe lub gęste elementy (Vectors lub blok Matrices). Mnożenie przez lokalną matrycę jest zwykle lepsze, ponieważ nie wymaga kosztownego tasowania.

Więcej szczegółowych informacji o każdym typie można uzyskać pod numerem the MLlib Data Types guide.

+2

To jest świetne podsumowanie tego, jak utworzyć różne typy macierzy - myślę, że zamierzam to dodać do zakładek! –