Apache Spark中IndexedRowmatrix的行/列总和的有效方式

时间:2015-10-23 15:02:49

标签: scala matrix apache-spark apache-spark-mllib rowsum

我在Scala中有一个CoordinateMatrix格式的矩阵。矩阵是稀疏的,而且整体看起来像(在coo_matrix.entries.collect上),

Array[org.apache.spark.mllib.linalg.distributed.MatrixEntry] = Array(
  MatrixEntry(0,0,-1.0), MatrixEntry(0,1,-1.0), MatrixEntry(1,0,-1.0),
  MatrixEntry(1,1,-1.0), MatrixEntry(1,2,-1.0), MatrixEntry(2,1,-1.0), 
  MatrixEntry(2,2,-1.0), MatrixEntry(0,3,-1.0), MatrixEntry(0,4,-1.0), 
  MatrixEntry(0,5,-1.0), MatrixEntry(3,0,-1.0), MatrixEntry(4,0,-1.0), 
  MatrixEntry(3,3,-1.0), MatrixEntry(3,4,-1.0), MatrixEntry(4,3,-1.0),
  MatrixEntry(4,4,-1.0))

这只是一个小样本。矩阵的大小为N×N(其中N = 1百万),尽管其中大部分是稀疏的。在Spark Scala中获取此矩阵的行总和的有效方法之一是什么?目标是创建一个由行和组成的新RDD,即大小为N,其中第一个元素是row1的行和,依此类推。

我总是可以将此coordinateMatrix转换为IndexedRowMatrix并运行for循环,一次一次迭代计算rowums,但这不是最有效的方法。

非常感谢任何想法。

1 个答案:

答案 0 :(得分:2)

由于改组(这是你在这里无法避免的部分),这将是相当昂贵的,但你可以将条目转换为PairRDD并按键减少:

import org.apache.spark.mllib.linalg.distributed.{MatrixEntry, CoordinateMatrix}
import org.apache.spark.rdd.RDD

val mat: CoordinateMatrix = ???
val rowSums: RDD[Long, Double)] = mat.entries
  .map{case MatrixEntry(row, _, value) => (row, value)}
  .reduceByKey(_ + _)

与基于indexedRowMatrix的解决方案不同:

import org.apache.spark.mllib.linalg.distributed.IndexedRow

mat.toIndexedRowMatrix.rows.map{
  case IndexedRow(i, values) => (i, values.toArray.sum)
}

它不需要groupBy转换或中间SparseVectors