理解Compressed Sparse Column Format (CSC)


最近在看《Spark for Data Science》這本書,閱讀到《Machine Learning》這一節的時候被稀疏矩陣的存儲格式CSC給弄的暈頭轉向的。所以專門寫一篇文章記錄一下我對這種格式的理解。

目的

Compressed Sparse Column Format (CSC)的目的是為了壓縮矩陣,減少矩陣存儲所占用的空間。這很好理解,手法無法就是通過增加一些"元信息"來描述矩陣中的非零元素存儲的位置(基於列),然后結合非零元素的值來表示矩陣。這樣在一些場景下可以減少矩陣存儲的空間。

Spark API

在Spark中我們一般創建這樣的稀疏矩陣的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)
  }

使用CSC格式表示稀疏矩陣

例如我們想創建一下如下的3x3的稀疏矩陣:

	1	0	4
	0	3	5
	2	0	6

我們就可以使用上面的這個api:

	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個數組:

	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)是怎么的出來的。也翻看了比較權威的資料(本文最下方的參考資料),但是感覺說的比較不清楚,因此下面談談我是如何理解的。

我的理解

上面的3個Array:(為了便於書寫我沒有寫1.0,而是直接寫為1)

	Array(0, 2, 3, 6)
	Array(0, 2, 1, 0, 1, 2)
	Array(1, 2, 3, 4, 5, 6)

其中第三個Array很好理解。它的值就是按照,依次按照順序記錄的矩陣中的非零值。

第二個Array也比較好理解,他表示的是每一列,非零元素所在的行號,行號從0開始。比如上面的矩陣中,第一列元素1在第0行,元素2在第2行。

至於第1個Array理解起來稍微麻煩一些。我的總結就是:

  • 第一個Array的元素個數就是(矩陣的列數+1),也就是矩陣是3列,那么這個Array的個數就是4.
  • 第一個元素一直是0。第二個元素是第一列的非零元素的數量
  • 后續的值為前一個值 + 下一列非零元素的數量

上面的總結可能看起來比較模糊,根據上面的例子我來分析一下:

  • 首先矩陣的3x3的,所以第一個Array會有4個元素。第一個元素是0。得到Array(0)。
  • 矩陣第一列有2個非零元素,所以得到Array的第二個元素為2.得到Array(0, 2)
  • 矩陣的第二列有1個非零元素,那么第三個元素的數量為當前Array的最后一個元素加1,也就是2 + 1=3. 得到Array(0,2, 3)
  • 矩陣的第三列有3個非零元素,那么Array的最后一個元素的值為 3 + 3 = 6. 得到Array(0, 2, 3, 6)

驗證例子

對於下面的這個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表示法,畫出原始矩陣

上面展示了如何把稀疏矩陣使用CSC表示,那么反過來應該怎么操作呢,

假設有一個2x4的矩陣,他的CSC表示為:

	Array(0, 1, 2, 3, 4)
	Array(0, 1, 1, 1)
	Array(9, 8, 6, 5)

我大致描述一下還原的過程:

  • 首先我們知道是2x4的矩陣,並且第一個Array的第二個元素是1,而且后續的每一個元素都比前一個元素大1,說明每一列都只有1個非零元素。
  • 根據第二個數組,我們可以知道只有第一列的非零元素在第一行,2,3,4列的非零元素都在第二行
  • 根據第三個Array,我們就可以比較簡單的畫出原始矩陣。

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM