python scipy 稀疏矩阵的使用说明


Posted in Python onMay 26, 2021

稀疏矩阵格式 coo_matrix

coo_matrix

是最简单的稀疏矩阵存储方式,采用三元组(row, col, data)(或称为ijv format)的形式来存储矩阵中非零元素的信息。

在实际使用中,一般coo_matrix用来创建矩阵,因为coo_matrix无法对矩阵的元素进行增删改操作;创建成功之后可以转化成其他格式的稀疏矩阵(如csr_matrix、csc_matrix)进行转置、矩阵乘法等操作。

python scipy 稀疏矩阵的使用说明

coo_matrix可以通过四种方式实例化,除了可以通过coo_matrix(D), D代表密集矩阵;coo_matrix(S), S代表其他类型稀疏矩阵或者coo_matrix((M, N), [dtype])构建一个shape为M*N的空矩阵,默认数据类型是d,还可以通过(row, col, data)三元组初始化:

>>> import numpy as np
>>> from scipy.sparse import coo_matrix
>>> _row  = np.array([0, 3, 1, 0])
>>> _col  = np.array([0, 3, 1, 2])
>>> _data = np.array([4, 5, 7, 9])
>>> coo = coo_matrix((_data, (_row, _col)), shape=(4, 4), dtype=np.int)
>>> coo.todense()  # 通过toarray方法转化成密集矩阵(numpy.matrix)
>>> coo.toarray()  # 通过toarray方法转化成密集矩阵(numpy.ndarray)
array([[4, 0, 9, 0],
       [0, 7, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 5]])

上面通过triplet format的形式构建了一个coo_matrix对象,我们可以看到坐标点(0,0)对应值为4,坐标点(1,1)对应值为7等等,这就是coo_matrix。coo_matrix对象有很多方法,大多数是elementwise的操作函数;coo_matrix对象有以下属性:

dtype dtype

矩阵中元素的数据类型

shape 2-tuple

获取矩阵的shape

ndim int

获取矩阵的维度,当然值是2咯

nnz

存储值的个数,包括显示声明的零元素(注意)

data

稀疏矩阵存储的值,是一个一维数组,即上面例子中的_data

row

与data同等长度的一维数组,表征data中每个元素的行号

col

与data同等长度的一维数组,表征data中每个元素的列号

在实际应用中,coo_matrix矩阵文件通常存成以下形式,表示稀疏矩阵是coo_matrix(coordinate),由13885行1列组成,共有949个元素值为非零,数据类型为整形。

python scipy 稀疏矩阵的使用说明

​ 下面给出coo_matrix矩阵文件读写示例代码,mmread()用于读取稀疏矩阵,mmwrite()用于写入稀疏矩阵,mminfo()用于查看稀疏矩阵文件元信息。(这三个函数的操作不仅仅限于coo_matrix)

from scipy.io import mmread, mmwrite, mminfo
HERE = dirname(__file__)
coo_mtx_path = join(HERE, 'data/matrix.mtx')
coo_mtx = mmread(coo_mtx_path)
print(mminfo(coo_mtx_path))
# (13885, 1, 949, 'coordinate', 'integer', 'general')
# (rows, cols, entries, format, field, symmetry)
mmwrite(join(HERE, 'data/saved_mtx.mtx'), coo_mtx)

coo_matrix的优点:

有利于稀疏格式之间的快速转换(tobsr()、tocsr()、to_csc()、to_dia()、to_dok()、to_lil())

允许又重复项(格式转换的时候自动相加)

能与CSR / CSC格式的快速转换

coo_matrix的缺点:

不能直接进行算术运算

csr_matrix ​

csr_matrix,全称Compressed Sparse Row matrix,即按行压缩的稀疏矩阵存储方式,由三个一维数组indptr, indices, data组成。

这种格式要求矩阵元按行顺序存储,每一行中的元素可以乱序存储。

那么对于每一行就只需要用一个指针表示该行元素的起始位置即可。

indptr存储每一行数据元素的起始位置,indices这是存储每行中数据的列号,与data中的元素一一对应。

python scipy 稀疏矩阵的使用说明

csr_matrix可用于各种算术运算:它支持加法,减法,乘法,除法和矩阵幂等操作。

其有五种实例化方法,其中前四种初始化方法类似coo_matrix,即通过密集矩阵构建、通过其他类型稀疏矩阵转化、构建一定shape的空矩阵、通过(row, col, data)构建矩阵。

其第五种初始化方式这是直接体现csr_matrix的存储特征:csr_matrix((data, indices, indptr), [shape=(M, N)]),意思是,矩阵中第i行非零元素的列号为indices[indptr[i]:indptr[i+1]],相应的值为data[indptr[i]:indptr[i+1]]

举个例子:

>>> import numpy as np
>>> from scipy.sparse import csr_matrix
>>> indptr = np.array([0, 2, 3, 6])
>>> indices = np.array([0, 2, 2, 0, 1, 2])
>>> data = np.array([1, 2, 3, 4, 5, 6])
>>> csr = csr_matrix((data, indices, indptr), shape=(3, 3)).toarray()
array([[1, 0, 2],
       [0, 0, 3],
       [4, 5, 6]])

csr_matrix同样有很多方法,其中tobytes(),tolist(), tofile(),tostring()值得注意,其他具体参考官方文档,csr_matrix对象属性前五个同coo_matrix,另外还有属性如下:

indices

与属性data一一对应,元素值代表在某一行的列号

indptr

csr_matrix各行的起始值,length(csr_object.indptr) == csr_object.shape[0] + 1

has_sorted_indices

判断每一行的indices是否是有序的,返回bool值

csr_matrix的优点:

高效的算术运算CSR + CSR,CSR * CSR等高效的行切片快速矩阵运算

csr_matrix的缺点:

列切片操作比较慢(考虑csc_matrix)稀疏结构的转换比较慢(考虑lil_matrix或doc_matrix)

csc_matrix

​ csc_matrix和csr_matrix正好相反,即按列压缩的稀疏矩阵存储方式,同样由三个一维数组indptr, indices, data组成,如下图所示:

python scipy 稀疏矩阵的使用说明

其实例化方式、属性、方法、优缺点和csr_matrix基本一致,这里不再赘述,它们之间唯一的区别就是按行或按列压缩进行存储。

而这一区别决定了csr_matrix擅长行操作;csc_matrix擅长列操作,进行运算时需要进行合理存储结构的选择。

lil_matrix

​ lil_matrix,即List of Lists format,又称为Row-based linked list sparse matrix。它使用两个嵌套列表存储稀疏矩阵:data保存每行中的非零元素的值,rows保存每行非零元素所在的列号(列号是顺序排序的)。

这种格式很适合逐个添加元素,并且能快速获取行相关的数据。

其初始化方式同coo_matrix初始化的前三种方式:通过密集矩阵构建、通过其他矩阵转化以及构建一个一定shape的空矩阵。

python scipy 稀疏矩阵的使用说明

lil_matrix可用于算术运算:支持加法,减法,乘法,除法和矩阵幂。其属性前五个同coo_matrix,另外还有rows属性,是一个嵌套List,表示矩阵每行中非零元素的列号。

LIL matrix本身的设计是用来方便快捷构建稀疏矩阵实例,而算术运算、矩阵运算则转化成CSC、CSR格式再进行,构建大型的稀疏矩阵还是推荐使用COO格式。

LIL format优点

支持灵活的切片操作行切片操作效率高,列切片效率低

稀疏矩阵格式之间的转化很高效(tobsr()、tocsr()、to_csc()、to_dia()、to_dok()、to_lil())

LIL format缺点

加法操作效率低 (consider CSR or CSC)

列切片效率低(consider CSC)

矩阵乘法效率低 (consider CSR or CSC)

dok_matrix ​

dok_matrix,即Dictionary Of Keys based sparse matrix,是一种类似于coo matrix但又基于字典的稀疏矩阵存储方式,key由非零元素的的坐标值tuple(row, column)组成,value则代表数据值。

dok matrix非常适合于增量构建稀疏矩阵,并一旦构建,就可以快速地转换为coo_matrix。

其属性和coo_matrix前四项同;其初始化方式同coo_matrix初始化的前三种:通过密集矩阵构建、通过其他矩阵转化以及构建一个一定shape的空矩阵。

对于dok matrix,可用于算术运算:它支持加法,减法,乘法,除法和矩阵幂;允许对单个元素进行快速访问( O(1) ); 不允许重复。

>>> import numpy as np
>>> from scipy.sparse import dok_matrix
>>> np.random.seed(10)
>>> matrix = random(3, 3, format='dok', density=0.4)
>>> matrix[1, 1] = 33
>>> matrix[2, 1] = 10
>>> matrix.toarray()
array([[ 0.        ,  0.        ,  0.        ],
       [ 0.        , 33.        ,  0.        ],
       [ 0.19806286, 10.        ,  0.22479665]])
>>> dict(matrix)
{(2, 0): 0.19806286475962398, (2, 1): 10.0, (2, 2): 0.22479664553084766, (1, 1): 33.0}
>>> isinstance(matrix, dict)
True

在上面代码最后可以看到,实际上dok_matrix实例也是dict实例,在实现上继承了dict类。

dia_matrix

​ dia_matrix,全称Sparse matrix with DIAgonal storage,是一种对角线的存储方式。

如下图中,将稀疏矩阵使用offsets和data两个矩阵来表示。offsets表示data中每一行数据在原始稀疏矩阵中的对角线位置k(k>0, 对角线往右上角移动;k<0, 对角线往左下方移动;k=0,主对角线)。

该格式的稀疏矩阵可用于算术运算:它们支持加法,减法,乘法,除法和矩阵幂。

python scipy 稀疏矩阵的使用说明

​dia_matrix五个属性同coo matrix, 另外还有属性offsets;dia_matrix有四种初始化方式,其中前三种初始化方式同coo_matrix前三种初始化方式,即:通过密集矩阵构建、通过其他矩阵转化以及构建一个一定shape的空矩阵。

第四种初始化方式如下:

dia_matrix((data, offsets), shape=(M, N)) ,

​ 其中,data[k,:]存储着稀疏矩阵offsets[k]对角线上的值

>>> data = np.arange(15).reshape(3, -1) + 1
>>> offsets = np.array([0, -3, 2])
>>> dia = sparse.dia_matrix((data, offsets), shape=(7, 5))
>>> dia.toarray()
array([[ 1,  0, 13,  0,  0],
       [ 0,  2,  0, 14,  0],
       [ 0,  0,  3,  0, 15],
       [ 6,  0,  0,  4,  0],
       [ 0,  7,  0,  0,  5],
       [ 0,  0,  8,  0,  0],
       [ 0,  0,  0,  9,  0]])

不是很常用,了解即可

bsr_matrix

​ bsr_matrix,全称Block Sparse Row matrix,这种压缩方式极其类似CSR格式,但使用分块的思想对稀疏矩阵进行按行压缩。所以,BSR适用于具有dense子矩阵的稀疏矩阵。该种矩阵有五种初始化方式,分别如下:

bsr_matrix(D, [blocksize=(R,C)])

D是一个M*N的二维dense矩阵;blocksize需要满足条件:M % R = 0和N % C = 0,若不给定该参数,内部将会应用启发式的算法自动决定一个合适的blocksize.

bsr_matrix(S, [blocksize=(R,C)])

S是指其他类型的稀疏矩阵

bsr_matrix((M, N), [blocksize=(R,C), dtype])

构建一个shape为M*N的空矩阵

bsr_matrix((data, ij), [blocksize=(R,C), shape=(M, N)])

data 和ij 满足条件: a[ij[0, k], ij[1, k]] = data[k]

bsr_matrix((data, indices, indptr), [shape=(M, N)])

data.shape一般是k*R*C,其中R、C分别代表block的行和列长,k代表有几个小block矩阵;第i行的块列索引存储在indices[indptr[i]:indptr[i+1]],其值是data[ indptr[i]: indptr[i+1] ]。

bsr_matrix可用于算术运算:支持加法,减法,乘法,除法和矩阵幂。如下面的例子,对于许多稀疏算术运算,BSR比CSR和CSC更有效:

>>> from scipy.sparse import bsr_matrix
>>> import numpy
>>> indptr = np.array([0, 2, 3, 6])
>>> indices = np.array([0, 2, 2, 0, 1, 2])
>>> data = np.array([1, 2, 3, 4, 5, 6]).repeat(4).reshape(6, 2, 2)
>>> bsr_matrix((data,indices,indptr), shape=(6, 6)).toarray()
array([[1, 1, 0, 0, 2, 2],
       [1, 1, 0, 0, 2, 2],
       [0, 0, 0, 0, 3, 3],
       [0, 0, 0, 0, 3, 3],
       [4, 4, 5, 5, 6, 6],
       [4, 4, 5, 5, 6, 6]])

可以通过热图观察矩阵有没有明显分块模式再决定使不使用该方式

bsr matrix对象拥有9个属性,前四个属性与coo matrix相同,另外还有以下属性(注意csr matrix和bsr matrix之间的区别与联系):

data

即稀疏矩阵的数组,data.shape一般是k*R*C

indices

与属性data中的k个二维矩阵一一对应,元素值代表在某一行的列号

indptr

bsr各行起始起始值

blocksize

即tuple(R,C)

has_sorted_indices

判断每一行的indices是否是有序的,返回bool值

实用函数

构造特殊稀疏矩阵

scipy.sparse模块还包含一些便捷函数,用于快速构建单位矩阵、对角矩阵等,下面做一个简单的汇总:

方法 用途
identity(n[, dtype, format]) 生成稀疏单位矩阵
kron(A, B[, format]) sparse matrices A 和 B的克罗内克积
kronsum(A, B[, format]) sparse matrices A 和 B的克罗内克和
diags(diagonals[, offsets, shape, format, dtype]) 构建稀疏对角阵
spdiags(data, diags, m, n[, format]) 构建稀疏对角阵,同上,但不可指定shape
block_diag(mats[, format, dtype]) mats为iterable, 包含多个矩阵,根据mats构建块对角稀疏矩阵。
tril(A[, k, format]) 以稀疏格式返回矩阵的下三角部分
triu(A[, k, format]) 以稀疏格式返回矩阵的上三角部分
bmat(blocks[, format, dtype]) 从稀疏子块构建稀疏矩阵
hstack(blocks[, format, dtype]) 水平堆叠稀疏矩阵(column wise)
vstack(blocks[, format, dtype]) 垂直堆叠稀疏矩阵 (row wise)
rand(m, n[, density, format, dtype, …]) 使用均匀分布的值生成给定形状和密度的稀疏矩阵
random(m, n[, density, format, dtype, …]) 使用随机分布的值生成给定形状和密度的稀疏矩阵
eye(m[, n, k, dtype, format]) 生成稀疏单位对角阵(默认DIAgonal format)

​ scipy.sparse.bmat举例:

In [1]: A = np.arange(8).reshape(2, 4)
In [2]: T = np.tri(5, 4)
In [3]: L = [[8] * 4] * 2
In [4]: I = sparse.identity(4)
In [5]: Z = sparse.coo_matrix((2, 3))
In [6]: sp.bmat([[   A,    Z,    L],
    ...:          [None, None,    I],
    ...:          [   T, None, None]], dtype=int)
Out[7]:
<11x11 sparse matrix of type '<class 'numpy.int64'>'
        with 33 stored elements in COOrdinate format>
In [8]: _.toarray()  # ipython previous output
Out[9]:
array([[0, 1, 2, 3, 0, 0, 0, 8, 8, 8, 8],
       [4, 5, 6, 7, 0, 0, 0, 8, 8, 8, 8],
       [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
       [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
       [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]])

稀疏矩阵类型判断

scipy.sparse模块还包含一些判断稀疏矩阵类型的函数,这里需要注意的是,issparse() 和 isspmatrix() 是相同的函数,也许是由于历史原因保留下来了两个。

isspars(x)
isspmatrix(x)
isspmatrix_csc(x)
isspmatrix_csr(x)
isspmatrix_bsr(x)
isspmatrix_lil(x)
isspmatrix_dok(x)
isspmatrix_coo(x)
isspmatrix_dia(x)

稀疏矩阵存取

load_npz(file) 从.npz文件中读取稀疏矩阵

save_npz(file, matrix[,compressed]) 将稀疏矩阵写入.npz文件中

其他

find(A) 返回稀疏矩阵中非零元素的索引以及值

经验总结

要有效地构造矩阵,请使用dok_matrix或lil_matrix

lil_matrix类支持基本切片和花式索引,其语法与NumPy Array类似;lil_matrix形式是基于row的,因此能够很高效的转为csr,但是转为csc效率相对较低。

强烈建议不要直接使用NumPy函数运算稀疏矩阵

如果你想将NumPy函数应用于这些矩阵,首先要检查SciPy是否有自己的给定稀疏矩阵类的实现,或者首先将稀疏矩阵转换为NumPy数组(使用类的toarray()方法)。

要执行乘法或转置等操作,首先将矩阵转换为CSC或CSR格式,效率高

CSR格式特别适用于快速矩阵矢量产品

CSR,CSC和COO格式之间的所有转换都是线性复杂度。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现哈希表
Feb 07 Python
Python 正则表达式(转义问题)
Dec 15 Python
Django中模型Model添加JSON类型字段的方法
Jun 17 Python
django model去掉unique_together报错的解决方案
Oct 18 Python
Python进阶篇之字典操作总结
Nov 16 Python
python 获取一个值在某个区间的指定倍数的值方法
Nov 12 Python
Python实现的多进程拷贝文件并显示百分比功能示例
Apr 09 Python
python opencv将图片转为灰度图的方法示例
Jul 31 Python
Python如何使用函数做字典的值
Nov 30 Python
Python ORM编程基础示例
Feb 02 Python
python代码xml转txt实例
Mar 10 Python
Django跨域请求原理及实现代码
Nov 14 Python
python中os.path.join()函数实例用法
May 26 #Python
python实现简单的井字棋
May 26 #Python
python 办公自动化——基于pyqt5和openpyxl统计符合要求的名单
Python 循环读取数据内存不足的解决方案
May 25 #Python
python基于机器学习预测股票交易信号
Python数据可视化之绘制柱状图和条形图
总结Python常用的魔法方法
You might like
PHP 的几个配置文件函数
2006/12/21 PHP
windows环境下php配置memcache的具体操作步骤
2013/06/09 PHP
php实现的css文件背景图片下载器代码
2014/11/11 PHP
php对数组内元素进行随机调换的方法
2015/05/12 PHP
PHP+MySQL之Insert Into数据插入用法分析
2015/09/27 PHP
PHP实现的简单异常处理类示例
2017/05/04 PHP
php插件Xajax使用方法详解
2017/08/31 PHP
PHP判断json格式是否正确的实现代码
2017/09/20 PHP
jQuery实现可关闭固定于底(顶)部的工具条菜单效果
2015/11/06 Javascript
基于Bootstrap3表格插件和分页插件实例详解
2016/05/17 Javascript
Javascript基础学习笔记(菜鸟必看篇)
2016/07/22 Javascript
vue实现列表的添加点击
2016/12/29 Javascript
node.js监听文件变化的实现方法
2019/04/17 Javascript
JS求1到任意数之间的所有质数的方法详解
2019/05/20 Javascript
node.js基础知识汇总
2020/08/25 Javascript
JavaScript WeakMap使用详解
2021/02/05 Javascript
[03:55]显微镜下的DOTA2特别篇——430灰烬之灵神级操作
2014/06/24 DOTA
python选择排序算法的实现代码
2013/11/21 Python
Python常用随机数与随机字符串方法实例
2015/04/09 Python
Python中使用Beautiful Soup库的超详细教程
2015/04/30 Python
Python 动态导入对象,importlib.import_module()的使用方法
2019/08/28 Python
tensorflow 实现打印pb模型的所有节点
2020/01/23 Python
Python发送邮件封装实现过程详解
2020/05/09 Python
Python新手学习函数默认参数设置
2020/06/03 Python
详解CSS3中强大的filter(滤镜)属性
2017/06/29 HTML / CSS
html5使用canvas绘制太阳系效果
2014/12/15 HTML / CSS
伦敦最著名的老字号百货公司:Selfridges(塞尔福里奇百货)
2016/07/25 全球购物
花园仓库建筑:Garden Buildings Direct
2018/02/16 全球购物
欧洲著名的二手奢侈品网站:Vestiaire Collective
2020/03/07 全球购物
教师自我评价范例
2013/09/24 职场文书
化学学院毕业生自荐信范文
2013/12/17 职场文书
服装设计行业个人的自我评价
2013/12/20 职场文书
法人代表证明书格式
2014/10/01 职场文书
校园会短篇的广播稿
2014/10/21 职场文书
python图片灰度化处理的几种方法
2021/06/23 Python
24年收藏2000多部退役军用电台
2022/02/18 无线电