2015-11-06 45 views
12

Tôi đang cố gắng thực hiện phép nhân ma trận bằng cách sử dụng Apache Spark và Java.Phép nhân ma trận trong Apache Spark

Tôi có 2 câu hỏi chính:

  1. Làm thế nào để tạo RDD có thể đại diện cho ma trận trong Apache Spark?
  2. Làm cách nào để nhân hai RDD như vậy?

Trả lời

27

Tất cả phụ thuộc vào dữ liệu đầu vào và thứ nguyên nhưng nói chung những gì bạn muốn không phải là RDD nhưng là một trong các cấu trúc dữ liệu được phân phối từ org.apache.spark.mllib.linalg.distributed. Tại thời điểm này nó cung cấp bốn hiện thực khác nhau của DistributedMatrix

  • IndexedRowMatrix - có thể được tạo ra trực tiếp từ một RDD[IndexedRow] nơi IndexedRow bao gồm chỉ số hàng và 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 - tương tự như IndexedRowMatrix nhưng không chỉ số hàng có ý nghĩa. Có thể được tạo ra trực tiếp từ RDD[org.apache.spark.mllib.linalg.Vector]

    import org.apache.spark.mllib.linalg.distributed.RowMatrix 
    
    val rowMatrix = new RowMatrix(rows.map(_.vector))  
    
  • BlockMatrix - có thể được tạo ra từ RDD[((Int, Int), Matrix)] nơi yếu tố đầu tiên của tuple chứa tọa độ của khối và điều thứ hai là một địa phương 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 - có thể được tạo từ RDD[MatrixEntry] trong đó MatrixEntry bao gồm hàng, cột và giá trị.

    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) 
    

hai triển khai đầu tiên hỗ trợ nhân của một địa phương 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])) 

và một trong những thứ ba có thể được nhân với một BlockMatrix khác miễn là số cột cho mỗi khối trong các trận đấu ma trận này số hàng cho mỗi khối của ma trận khác. CoordinateMatrix không hỗ trợ phép nhân nhưng là khá dễ dàng để tạo và chuyển đổi với các loại ma trận phân phối:

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

Mỗi loại có mặt mạnh và điểm yếu riêng của mình và có một số yếu tố bổ sung để xem xét khi bạn sử dụng thưa thớt hoặc yếu tố dày đặc (Vectors hoặc chặn Matrices). Nhân với một ma trận cục bộ thường là thích hợp hơn vì nó không đòi hỏi xáo trộn đắt tiền.

Bạn có thể tìm thêm chi tiết về từng loại trong the MLlib Data Types guide.

+2

Đây là một bản tóm tắt tuyệt vời về cách tạo các loại ma trận khác nhau - Tôi nghĩ tôi sẽ đánh dấu trang này! –

Các vấn đề liên quan