Умножение матриц в Apache Spark

Я пытаюсь выполнить умножение матриц с помощью Apache Spark и Java.

У меня 2 основных вопроса:

  1. Как создать RDD, который может представлять матрицу в Apache Spark?
  2. Как перемножить два таких СДР?

person Jigar    schedule 06.11.2015    source источник


Ответы (1)


Все зависит от входных данных и измерений, но, вообще говоря, вам нужна не RDD, а одна из распределенных структур данных из org.apache.spark.mllib.linalg.distributed. На данный момент он предоставляет четыре различных реализации DistributedMatrix

  • IndexedRowMatrix — можно создать напрямую из RDD[IndexedRow], где IndexedRow состоит индекса строки и 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 — аналогично IndexedRowMatrix, но без значимых индексов строк. Может быть создан непосредственно из RDD[org.apache.spark.mllib.linalg.Vector]

    import org.apache.spark.mllib.linalg.distributed.RowMatrix
    
    val rowMatrix = new RowMatrix(rows.map(_.vector))      
    
  • BlockMatrix – можно создать из RDD[((Int, Int), Matrix)] где первый элемент кортежа содержит координаты блока, а второй является локальным 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 — может быть создано из RDD[MatrixEntry], где MatrixEntry состоят из строки, столбца и значения.

    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)
    

Первые две реализации поддерживают умножение на локальный 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]))

а третье можно умножить на другое BlockMatrix, если количество столбцов на блок в этой матрице совпадает с количеством строк в блоке другой матрицы. CoordinateMatrix не поддерживает умножения, но его довольно легко создать и преобразовать в другие типы распределенных матриц:

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

Каждый тип имеет свои сильные и слабые стороны, и есть некоторые дополнительные факторы, которые следует учитывать при использовании разреженных или плотных элементов (Vectors или блока Matrices). Обычно предпочтительнее умножение на локальную матрицу, поскольку оно не требует дорогостоящей перетасовки.

Дополнительные сведения о каждом типе можно найти в руководстве по типам данных MLlib.

person zero323    schedule 06.11.2015
comment
Это отличный обзор того, как создавать различные типы матриц — думаю, я добавлю это в закладки! - person Brian Risk; 08.07.2016
comment
Для чего используются параметры BlockMatrix? Также я вижу, что умножение может принимать параметр int? У меня возникли проблемы с умножением 250k x 30k X 30k x 30k - person Dan Ciborowski - MSFT; 27.03.2018
comment
Вот вопрос, хотя вы можете делать умножение матриц в искре, не так ли? Кажется, что многие другие библиотеки в мире C делают матричное умножение намного лучше, например, библиотеки глубокого обучения и тому подобное. В некоторых случаях они даже используют распределенную обработку GPU. Насколько менее эффективны матричные операции в искре? - person oneirois; 01.09.2018
comment
Я нашел это очень полезным. Пользователи, закрывшие этот вопрос, оказывают медвежью услугу. - person Dean Schulze; 06.02.2019
comment
Я хотел бы знать, какой из них лучше масштабируется, если, например, вы будете использовать его для columnSimilarities? - person Maziyar; 02.12.2019