最近在看《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,我们就可以比较简单的画出原始矩阵。

参考资料

理解Compressed Sparse Column Format (CSC)的更多相关文章

  1. sparse matrix format

    see Spare Matrix wikipedia item, and scipy's documentation on different choices of sparse matrix typ ...

  2. SSIS 中将csv 文件批量导出到excel 文件,并设置excel 文件中某些列的data column format 为Text

    csv 文件是文本文件类型,但是打开csv 文件后(默认使用本地已经安装的excel 来打开excel 文件),默认显示出来的是general 类型(column data format)的数据, 这 ...

  3. SharePoint Column Format

    https://docs.microsoft.com/en-us/sharepoint/dev/declarative-customization/column-formatting . { &quo ...

  4. Only POT texture can be compressed to PVRTC format

    在图片压缩格式 报这个Warning的时候,意思是该图片必须要采用2的幂次方大小才能使用该格式. POT: Power of Two. 采取方式是在advanced里边,把Non Power of 2 ...

  5. 稀疏矩阵 part 1

    ▶ 图片参考[http://www.bu.edu/pasi/files/2011/01/NathanBell1-10-1000.pdf] ▶ 各种系数矩阵的数据结构 ● MAT,原始矩阵数据 type ...

  6. scipy稀疏矩阵

    那些零元素数目远远多于非零元素数目,并且非零元素的分布没有规律的矩阵称为稀疏矩阵(sparse matrix). 不同类型的矩阵有不同的压缩方式,比如对角矩阵只存储对角元素即可.要想充分压缩,就要找到 ...

  7. sklearn文本特征提取

    http://cloga.info/2014/01/19/sklearn_text_feature_extraction/ 文本特征提取 词袋(Bag of Words)表征 文本分析是机器学习算法的 ...

  8. Feature extraction - sklearn文本特征提取

    http://blog.csdn.net/pipisorry/article/details/41957763 文本特征提取 词袋(Bag of Words)表征 文本分析是机器学习算法的主要应用领域 ...

  9. 稀疏矩阵在Python中的表示方法

    对于一个矩阵而言,若数值为零的元素远远多于非零元素的个数,且非零元素分布没有规律时,这样的矩阵被称作稀疏矩阵:与之相反,若非零元素数目占据绝大多数时,这样的矩阵被称作稠密矩阵. 稀疏矩阵在工程应用中经 ...

随机推荐

  1. datatables中的Options总结(3)

    datatables中的Options总结(3) 十.ColReorder colReorder.fixedColumnsLeft 不允许x列重新排序(从左数) colReorder.fixedCol ...

  2. CuPlayer

    <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head> <met ...

  3. 在Visual Studio 2015 中添加SharePoint 2016 开发模板

    前言 SharePoint 2016已经发布很久了,然而,默认安装VS2015以后,却没有SharePoint 2016的开发模板.其实问题很简单,和VS2012开发SharePoint 2013一样 ...

  4. ViewPager之引导页

    一.概述 ViewPager是android-support-v4中提供的类,它是一个容器类,常用于页面之间的切换. 本文介绍ViewPager最基础的应用:在多个View之间进行切换,亦即ViewP ...

  5. JavaSE 之 final 初探

    我们先看一道面试题: 请问 final 的含义是什么?可以用在哪里?其初始化的方式有哪些? 首先我们回答一下这道题,然后再探究其所以然.  1.final 表示“最终的”.“不可改变的”,意指其修饰类 ...

  6. paramiko 的使用

    paramiko模块,该模块机遇SSH用于连接远程服务器并执行相关操作 SSHClient 用于远程连接机器执行基本命令,也可以执行shell脚本 基于用户名密码连接: def ssh_connect ...

  7. PriorityQueue和Queue的一种变体的实现

    队列和优先队列是我们十分熟悉的数据结构.提供了所谓的“先进先出”功能,优先队列则按照某种规则“先进先出”.但是他们都没有提供:“固定大小的队列”和“固定大小的优先队列”的功能. 比如我们要实现:记录按 ...

  8. 安卓Android科大讯飞语音识别代码使用详解

    科大讯飞的语音识别功能用在安卓代码中,我把语音识别写成了Service,然后在Fragment直接调用service服务.科大讯飞语音识别用的是带对话框的那个,直接调用科大讯飞的语音接口,代码采用链表 ...

  9. JAVA操作LDAP的详解(JLDAP)

    最近两周由于要学习测试LDAP,所以对于用脚本操作LDAP很感兴趣,所以就做了一些脚本,都是比较简单的脚本吧. 废话不多说了哈.直接上教程 首先声明:我使用的是JLDAP操作LDAP,所以需要从官网下 ...

  10. L1-006. 连续因子

    https://www.patest.cn/contests/gplt/L1-006 题目地址 在上面 一个正整数N的因子中可能存在若干连续的数字.例如630可以分解为3*5*6*7,其中5.6.7就 ...