SciPySparse稀疏矩阵主要存储格式总结(转载)

Posted coco

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SciPySparse稀疏矩阵主要存储格式总结(转载)相关的知识,希望对你有一定的参考价值。

原文:【SciPy】Sparse稀疏矩阵主要存储格式总结

在数据科学和深度学习等领域常会采用矩阵格式来存储数据,但当矩阵较为庞大且非零元素较少时,运算效率和存储有效率并不高。所以,通常我们采用Sparse稀疏矩阵的方式来存储矩阵,提高存储和运算效率。下面将对SciPy中七种常见的存储方式(COO/ CSR/ CSC/ BSR/ DOK/ LIL/ DIA)的概念和用法进行介绍和对比总结。

稀疏矩阵简介

稀疏矩阵

numpy.sparse 稀疏矩阵 sparse matrix
numpy.ndarray 密集矩阵 array matrix
numpy.matrix 密集矩阵 dense matrix
  • 稀疏矩阵
    • 具有少量非零项的矩阵 - Number of Non-Zero (NNZ) < 0.5
    • (在矩阵中,若数值0的元素数目远多于非0元素的数目,并且非0元素分布没有规律)
  • 矩阵的稠密度
    • 非零元素的总数比上矩阵所有元素的总数为矩阵的稠密度。

压缩存储

存储矩阵的一般方法是采用二维数组,其优点是可以随机地访问每一个元素,因而能够容易实现矩阵的各种运算。
对于稀疏矩阵,它通常具有很大的维度,有时甚大到整个矩阵(零元素)占用了绝大部分内存
采用二维数组的存储方法既浪费大量的存储单元来存放零元素,又要在运算中浪费大量的时间来进行零元素的无效运算。因此必须考虑对稀疏矩阵进行压缩存储(只存储非零元素)。

from scipy import sparse
help(sparse)

\'\'\'
Sparse Matrix Storage Formats
There are seven available sparse matrix types:

        1. csc_matrix: Compressed Sparse Column format
        2. csr_matrix: Compressed Sparse Row format
        3. bsr_matrix: Block Sparse Row format
        4. lil_matrix: List of Lists format
        5. dok_matrix: Dictionary of Keys format
        6. coo_matrix: COOrdinate format (aka IJV, triplet format)
        7. dia_matrix: DIAgonal format
        8. spmatrix: Sparse matrix base clas
\'\'\'

矩阵属性

from scipy.sparse import csr_matrix

### 共有属性
mat.shape  # 矩阵形状
mat.dtype  # 数据类型
mat.ndim  # 矩阵维度
mat.nnz   # 非零个数
mat.data  # 非零值, 一维数组

### COO 特有的
coo.row  # 矩阵行索引
coo.col  # 矩阵列索引

### CSR\\CSC\\BSR 特有的
bsr.indices    # 索引数组
bsr.indptr     # 指针数组
bsr.has_sorted_indices  # 索引是否排序
bsr.blocksize  # BSR矩阵块大小

通用方法

import scipy.sparse as sp

### 转换矩阵格式
tobsr()、tocsr()、to_csc()、to_dia()、to_dok()、to_lil()
mat.toarray()  # 转为array
mat.todense()  # 转为dense
# 返回给定格式的稀疏矩阵
mat.asformat(format)
# 返回给定元素格式的稀疏矩阵
mat.astype(t)  

### 检查矩阵格式
issparse、isspmatrix_lil、isspmatrix_csc、isspmatrix_csr
sp.issparse(mat)

### 获取矩阵数据
mat.getcol(j)  # 返回矩阵列j的一个拷贝,作为一个(mx 1) 稀疏矩阵 (列向量)
mat.getrow(i)  # 返回矩阵行i的一个拷贝,作为一个(1 x n)  稀疏矩阵 (行向量)
mat.nonzero()  # 非0元索引
mat.diagonal()   # 返回矩阵主对角元素
mat.max([axis])  # 给定轴的矩阵最大元素

### 矩阵运算
mat += mat     # 加
mat = mat * 5  # 乘
mat.dot(other)  # 坐标点积


resize(self, *shape)
transpose(self[, axes, copy])

稀疏矩阵分类

COO - coo_matrix

Coordinate Matrix 对角存储矩阵

  • 采用三元组(row, col, data)(或称为ijv format)的形式来存储矩阵中非零元素的信息
  • 三个数组 rowcoldata 分别保存非零元素的行下标、列下标与值(一般长度相同)
  • coo[row[k]][col[k]] = data[k] ,即矩阵的第 row[k] 行、第 col[k] 列的值为 data[k]

  • row[0] = 1 , column[0] = 1 时, data[0] = 2 ,故 coo[1][1] = 2
  • row[3] = 0 , column[3] = 2 时, data[3] = 9 ,故 coo[0][3] = 9

适用场景

  • 主要用来创建矩阵,因为coo_matrix无法对矩阵的元素进行增删改等操作
  • 一旦创建之后,除了将之转换成其它格式的矩阵,几乎无法对其做任何操作和矩阵运算

优缺点

优点

  • 转换成其它存储格式很快捷简便(tobsr()tocsr()to_csc()to_dia()to_dok()to_lil()
  • 能与CSR / CSC格式的快速转换
  • 允许重复的索引(例如在1行1列处存了值2.0,又在1行1列处存了值3.0,则转换成其它矩阵时就是2.0+3.0=5.0)

缺点

  • 不支持切片和算术运算操作
  • 如果稀疏矩阵仅包含非0元素的对角线,则对角存储格式(DIA)可以减少非0元素定位的信息量
  • 这种存储格式对有限元素或者有限差分离散化的矩阵尤其有效

实例化方法

  • coo_matrix(D):D代表密集矩阵;
  • coo_matrix(S):S代表其他类型稀疏矩阵
  • coo_matrix((M, N), [dtype]):构建一个shape为M*N的空矩阵,默认数据类型是d,
  • coo_matrix((data, (i, j)), [shape=(M, N)])):三元组初始化
    • i[:] : 行索引
    • j[:] : 列索引
    • A[i[k], j[k]]=data[k]

特殊属性

  • data:稀疏矩阵存储的值,是一个一维数组
  • row:与data同等长度的一维数组,表征data中每个元素的行号
  • col:与data同等长度的一维数组,表征data中每个元素的列号

代码示例

# 数据
row = [0, 1, 2, 2]
col = [0, 1, 2, 3]
data = [1, 2, 3, 4]

# 生成coo格式的矩阵
# <class \'scipy.sparse.coo.coo_matrix\'>
coo_mat = sparse.coo_matrix((data, (row, col)), shape=(4, 4),  dtype=np.int)

# coordinate-value format
print(coo)
\'\'\'
(0, 0)        1
(1, 1)        2
(2, 2)        3
(3, 3)        4
\'\'\'

# 查看数据
coo.data
coo.row
coo.col

# 转化array
# <class \'numpy.ndarray\'>
coo_mat.toarray()
\'\'\'
array([[1, 0, 0, 0],
       [0, 2, 0, 0],
       [0, 0, 3, 4],
       [0, 0, 0, 0]])
\'\'\'

稀疏矩阵存储格式总结+存储效率对比:COO,CSR,DIA,ELL,HYB

稀疏矩阵存储格式总结+存储效率对比:COO,CSR,DIA,ELL,HYB

原文:http://www.cnblogs.com/xbinworld/p/4273506.html?utm_source=tuicool&utm_medium=referral

稀疏矩阵是指矩阵中的元素大部分是0的矩阵,事实上,实际问题中大规模矩阵基本上都是稀疏矩阵,很多稀疏度在90%甚至99%以上。因此我们需要有高效的稀疏矩阵存储格式。本文总结几种典型的格式:COO,CSR,DIA,ELL,HYB。

 

(1)Coordinate(COO)

技术分享

这是最简单的一种格式,每一个元素需要用一个三元组来表示,分别是(行号,列号,数值),对应上图右边的一列。这种方式简单,但是记录单信息多(行列),每个三元组自己可以定位,因此空间不是最优。

 

(2)Compressed Sparse Row (CSR)

技术分享

CSR是比较标准的一种,也需要三类数据来表达:数值,列号,以及行偏移。CSR不是三元组,而是整体的编码方式。数值和列号与COO一致,表示一个元素以及其列号,行偏移表示某一行的第一个元素在values里面的起始偏移位置。如上图中,第一行元素1是0偏移,第二行元素2是2偏移,第三行元素5是4偏移,第4行元素6是7偏移。在行偏移的最后补上矩阵总的元素个数,本例中是9。

 

CSC是和CSR相对应的一种方式,即按列压缩的意思。

以上图中矩阵为例:

Values:        [1 5 7 2 6 8 3 9 4]

Row Indices:[0 2 0 1 3 1 2 2 3]

Column Offsets:[0 2 5 7 9]

 

再来看一个CSR的例子[4]:

技术分享

 

(3)ELLPACK (ELL)

技术分享

用两个和原始矩阵相同行数的矩阵来存:第一个矩阵存的是列号,第二个矩阵存的是数值,行号就不存了,用自身所在的行来表示;这两个矩阵每一行都是从头开始放,如果没有元素了就用个标志比如*结束。上图中间矩阵有误,第三行应该是  0 2 3。

 

注:这样如果某一行很多元素,那么后面两个矩阵就会很胖,其他行结尾*很多,浪费。可以存成数组,比如上面两个矩阵就是:

0 1 * 1 2 * 0 2 3 * 1 3 *

1 7 * 2 8 * 5 3 9 * 6 4 *

但是这样要取一行就比较不方便了

(4)Diagonal (DIA)

技术分享

对角线存储法,按对角线方式存,列代表对角线,行代表行。省略全零的对角线。(从左下往右上开始:第一个对角线是零忽略,第二个对角线是5,6,第三个对角线是零忽略,第四个对角线是1,2,3,4,第五个对角线是7,8,9,第六第七个对角线忽略)。[3]

这里行对应行,所以5和6是分别在第三行第四行的,前面补上无效元素*。如果对角线中间有0,存的时候也需要补0,所以如果原始矩阵就是一个对角性很好的矩阵那压缩率会非常高,比如下图,但是如果是随机的那效率会非常糟糕。

技术分享技术分享

 

(5)Hybrid (HYB) ELL + COO

技术分享

为了解决(3)ELL中提到的,如果某一行特别多,造成其他行的浪费,那么把这些多出来的元素(比如第三行的9,其他每一行最大都是2个元素)用COO单独存储。

 

选择稀疏矩阵存储格式的一些经验[2]:

  1. DIA和ELL格式在进行稀疏矩阵-矢量乘积(sparse matrix-vector products)时效率最高,所以它们是应用迭代法(如共轭梯度法)解稀疏线性系统最快的格式;
  2. COO和CSR格式比起DIA和ELL来,更加灵活,易于操作;
  3. ELL的优点是快速,而COO优点是灵活,二者结合后的HYB格式是一种不错的稀疏矩阵表示格式;
  4. 根据Nathan Bell的工作,CSR格式在存储稀疏矩阵时非零元素平均使用的字节数(Bytes per Nonzero Entry)最为稳定(float类型约为8.5,double类型约为12.5),而DIA格式存储数据的非零元素平均使用的字节数与矩阵类型有较大关系,适合于StructuredMesh结构的稀疏矩阵(float类型约为4.05,double类型约为8.10),对于Unstructured Mesh以及Random Matrix,DIA格式使用的字节数是CSR格式的十几倍;
  5. 从我使用过的一些线性代数计算库来说,COO格式常用于从文件中进行稀疏矩阵的读写,如matrix market即采用COO格式,而CSR格式常用于读入数据后进行稀疏矩阵计算。

 

一些特殊类型矩阵的存储效率(数值越小说明压缩率越高,即存储效率越高):

Structured Mesh

技术分享

Unstructured Mesh

技术分享

Random matrix

技术分享

Power-Law Graph

技术分享

 

格式适用性总结:

技术分享

 

 

下面摘自[2]

6. Skyline Storage Format

The skyline storage format is important for the direct sparse solvers, and it is well suited for Cholesky or LU decomposition when no pivoting is required.

The skyline storage format accepted in Intel MKL can store only triangular matrix or triangular part of a matrix. This format is specified by two arrays:values andpointers. The following table describes these arrays:

values

A scalar array. For a lower triangular matrix it contains the set of elements from each row of the matrix starting from the first non-zero element to and including the diagonal element. For an upper triangular matrix it contains the set of elements from each column of the matrix starting with the first non-zero element down to and including the diagonal element. Encountered zero elements are included in the sets.

pointers

An integer array with dimension(m+1), where m is the number of rows for lower triangle (columns for the upper triangle).pointers(i) -pointers(1)+1gives the index of element invalues that is first non-zero element in row (column)i. The value ofpointers(m+1)is set tonnz+pointers(1), wherennz is the number of elements in the arrayvalues.

7. Block Compressed Sparse Row Format (BSR)

The Intel MKL block compressed sparse row (BSR) format for sparse matrices is specified by four arrays:values,columns,pointerB, andpointerE. The following table describes these arrays.

values

A real array that contains the elements of the non-zero blocks of a sparse matrix. The elements are stored block-by-block in row-major order. A non-zero block is the block that contains at least one non-zero element. All elements of non-zero blocks are stored, even if some of them is equal to zero. Within each non-zero block elements are stored in column-major order in the case of one-based indexing, and in row-major order in the case of the zero-based indexing.

columns

Element i of the integer array columns is the number of the column in the block matrix that contains thei-th non-zero block.

pointerB

Element j of this integer array gives the index of the element in thecolumns array that is first non-zero block in a rowj of the block matrix.

pointerE

Element j of this integer array gives the index of the element in thecolumns array that contains the last non-zero block in a rowj of the block matrix plus 1.

 

 

 

 

[1] Sparse Matrix Representations & Iterative Solvers, Lesson 1 by Nathan Bell. http://www.bu.edu/pasi/files/2011/01/NathanBell1-10-1000.pdf

[2] http://blog.csdn.net/anshan1984/article/details/8580952

[3] http://zhangjunhd.github.io/2014/09/29/sparse-matrix.html

[4] http://www.360doc.com/content/09/0204/17/96202_2458312.shtml

[5] Implementing Sparse Matrix-Vector Multiplication on Throughput-Oriented Processors, Nathan Bell and Michael Garland, Proceedings of Supercomputing ‘09

[6] Efficient Sparse Matrix-Vector Multiplication on CUDA, Nathan Bell and Michael Garland, NVIDIA Technical Report NVR-2008-004, December 2008

以上是关于SciPySparse稀疏矩阵主要存储格式总结(转载)的主要内容,如果未能解决你的问题,请参考以下文章

Scipy sparse的CSC矩阵总结

稀疏矩阵的压缩存储及快速转置

C++实现稀疏矩阵的压缩存储转置快速转置

数据结构实验报告之三元组顺序表存储的稀疏矩阵练习

稀疏矩阵定义以及存储格式(COO,CSR,CSC)

稀疏矩阵及其压缩格式