【SciPy】Sparse稀疏矩阵主要存储格式总结(转载)

发布时间 2023-04-03 23:50:43作者: Cisco_coco

原文:【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]])
'''