最近在看《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)
我大體描述一下還原的過程: