最近在看《Spark for Data Science》这本书,阅读到《Machine Learning》这一节的时候被稀疏矩阵的存储格式CSC给弄的晕头转向的。因此专门写一篇文章记录一下我对这种格式的理解。html
Compressed Sparse Column Format (CSC)
的目的是为了压缩矩阵,减小矩阵存储所占用的空间。这很好理解,手法没法就是经过增长一些"元信息"来描述矩阵中的非零元素存储的位置(基于列),而后结合非零元素的值来表示矩阵。这样在一些场景下能够减小矩阵存储的空间。apache
在Spark中咱们通常建立这样的稀疏矩阵的API为:api
package org.apache.spark.ml.linalg /** * Creates a column-major sparse matrix in Compressed Sparse Column (CSC) format. * * @param numRows number of rows * @param numCols number of columns * @param colPtrs the index corresponding to the start of a new column * @param rowIndices the row index of the entry * @param values non-zero matrix entries in column major */ @Since("2.0.0") def sparse( numRows: Int, numCols: Int, colPtrs: Array[Int], rowIndices: Array[Int], values: Array[Double]): Matrix = { new SparseMatrix(numRows, numCols, colPtrs, rowIndices, values) }
例如咱们想建立一下以下的3x3的稀疏矩阵:数组
1 0 4 0 3 5 2 0 6
咱们就可使用上面的这个api:spa
import org.apache.spark.ml.linalg.{Matrix,Matrices} val sm: Matrix = Matrices.sparse(3,3, Array(0,2,3,6), Array(0,2,1,0,1,2), Array(1.0,2.0,3.0,4.0,5.0,6.0)) 输出以下: sm: org.apache.spark.ml.linalg.Matrix = 3 x 3 CSCMatrix (0,0) 1.0 (2,0) 2.0 (1,1) 3.0 (0,2) 4.0 (1,2) 5.0 (2,2) 6.0
也就是说上面的3x3的矩阵,能够表示为下面3个数组:scala
Array(0, 2, 3, 6) Array(0, 2, 1, 0, 1, 2) Array(1, 2, 3, 4, 5, 6)
说实话我第一次看到这个api的时候有点蒙。下面由于没太看懂上面三个Array中的第一个Array(0, 2, 3, 6)
是怎么的出来的。也翻看了比较权威的资料(本文最下方的参考资料),可是感受说的比较不清楚,所以下面谈谈我是如何理解的。code
上面的3个Array:(为了便于书写我没有写1.0,而是直接写为1)orm
Array(0, 2, 3, 6) Array(0, 2, 1, 0, 1, 2) Array(1, 2, 3, 4, 5, 6)
其中第三个Array很好理解。它的值就是按照列,依次按照顺序记录的矩阵中的非零值。htm
第二个Array也比较好理解,他表示的是每一列,非零元素所在的行号,行号从0开始。好比上面的矩阵中,第一列元素1在第0行,元素2在第2行。ip
至于第1个Array理解起来稍微麻烦一些。个人总结就是:
上面的总结可能看起来比较模糊,根据上面的例子我来分析一下:
对于下面的这个3x3的矩阵:
1 0 2 0 0 3 4 5 6
咱们能够获得3个Array为:
Array(0, 2, 3, 6) Array(0, 2, 2, 0, 1, 2) Array(1, 4, 5, 2, 3, 6)
对于下面的矩阵:
9 0 0 8 0 6
咱们能够获得3个Array来表示他:
Array(0, 1, 3) Array(0, 1, 2) Array(9, 8, 6)
对于下面的矩阵:
9 0 0 0 0 8 6 5
咱们能够表示为:
Array(0, 1, 2, 3, 4) Array(0, 1, 1, 1) Array(9, 8, 6, 5)
上面展现了如何把稀疏矩阵使用CSC表示,那么反过来应该怎么操做呢,
假设有一个2x4的矩阵,他的CSC表示为:
Array(0, 1, 2, 3, 4) Array(0, 1, 1, 1) Array(9, 8, 6, 5)
我大体描述一下还原的过程: