【scipy.sparse包】Python稀疏矩阵详解

这篇具有很好参考价值的文章主要介绍了【scipy.sparse包】Python稀疏矩阵详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【scipy.sparse包】Python稀疏矩阵

1. 前言

  1. 数组和矩阵是数值计算的基础元素。目前为止,我们都是使用NumPy的ndarray数据结构来表示数组,这是一种同构的容器,用于存储数组的所有元素。

  2. 有一种特殊情况,矩阵的大部分元素都为零,这种矩阵被称为稀疏矩阵。对于稀疏矩阵,将所有零保存在计算机内存中的效率很低,更合适的方法是只保存非零元素以及位置信息。于是SciPy应运而生,为稀疏矩阵的表示及其线性代数运算提供了丰富易用的接口。

2. 导入包

SciPy中提供了稀疏矩阵模块scipy.sparse,为稀疏矩阵的表示及其线性代数运算提供了丰富易用的接口。

import scipy.sparse as sp
import scipy.sparse.linalg
import scipy.linalg as la

3. 稀疏矩阵总览

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
  1. sp.coo_matrix(坐标的列表)描述:将非零值及其行列信息保存在一个列表。构造简单,添加元素方便,但访问元素效率低下;
  2. sp.lil_matrix(列表的列表):将每行的非零元素列索引保存在一个列表,将对应值保存在另一个列表。支持切片操作,但不方便进行数学运算;
  3. sp.dok_matrix(值的字典):将非零值保存在字典,非零值的坐标元组作为字典的键。构造简单,可快速添加删除元素,但不方便进行数学运算;
  4. sp.dia_matrix(对角矩阵):矩阵的对角线列表 。对于对角矩阵非常有效 ,但不适用非对角矩阵;
  5. sp.csc_matrix 和 sp.csr_matrix(压缩列格式和压缩行格式):将值与行列索引的数组一起存储。对于矩阵的向量乘法很高效,但构造相对复杂;
  6. sp.bsr_matrix(块稀疏矩阵):与CSR类似,用于具有稠密子矩阵的稀疏矩阵。对于此类特殊矩阵很高效,但不适用一般矩阵。

注意:

  • 为了有效地构建矩阵,使用dok_matrix或者lil_matrix,lil_matrix类支持基本的切片和索引操作,语法与NumPy的arrays相似。
  • COO格式也能有效率地构建矩阵。尽管与NumPy有许多相似性,但是强烈不建议使用NumPy的函数直接对稀疏矩阵格式进行操作,因为可能导致不正确的结果。如果将NumPy的函数用在这些矩阵上,首先检查SciPy在对应的稀疏矩阵类上有没有已经实现的操作,或者使用toarray()方法将稀疏矩阵对象转为NumPy的array。
  • 实现乘法与转置操作,则转为CSC或CSR格式,lil_matrix格式是基于行的,所以转为为CSR比CSC更有效率。所有的转换在CSR,CSC和COO格式之间都是有效的,线性时间操作。

4. 稀疏矩阵详细介绍

4.1 coo_matrix

coo_matrix是最简单的存储方式。采用三个数组row、col和data保存非零元素的行下标,列下标与值。这三个数组的长度相同一般来说,coo_matrix主要用来创建矩阵,因为coo_matrix无法对矩阵的元素进行增删改等操作,一旦创建之后,除了将之转换成其它格式的矩阵,几乎无法对其做任何操作和矩阵运算。
scipy.sparse,使用说明,python,矩阵,scipy
为了创建sp.coo_matrix对象,需要创建非零值、行索引以及列索引的列表或数组,并将其传递给生成函数sp.coo_matrix。

values = [1, 2, 3, 4]
rows = [0, 1, 2, 3]
cols = [1, 3, 2, 0]
A = sp.coo_matrix((values, (rows, cols)), shape=[4, 4])
A

scipy.sparse,使用说明,python,矩阵,scipy

>>> A.toarray()
array([[1, 0, 0, 0],
       [0, 0, 0, 2],
       [0, 0, 3, 0],
       [4, 0, 0, 0]])
>>> type(A)
<class 'scipy.sparse.coo.coo_matrix'>
>>> type(A.toarray())
<class 'numpy.ndarray'>

SciPy的sparse模块中稀疏矩阵的属性大部分派生自NumPy的ndarray对象,同时也包括nnz(非零元素数目)和data(非零值)等属性。

A.shape, A.size, A.dtype, A.ndim

scipy.sparse,使用说明,python,矩阵,scipy

A.nnz, A.data

scipy.sparse,使用说明,python,矩阵,scipy

对于sp.coo_matrix对象,还可以使用row和col属性来访问底层的行列坐标数组。

A.row, A.col

scipy.sparse,使用说明,python,矩阵,scipy

4.2 dok_matrix

dok_matrix适用的场景是逐渐添加矩阵的元素。dok_matrix的策略是采用字典来记录矩阵中不为0的元素。所以字典的key存的是记录元素的位置信息的元祖,value是记录元素的具体值。

>>> S = sparse.dok_matrix((5, 5), dtype=np.float32)
>>> for i in range(5):
    	for j in range(5):
        	S[i,j] = i+j    # 更新元素
>>> S.toarray()
[[0. 1. 2. 3. 4.]
 [1. 2. 3. 4. 5.]
 [2. 3. 4. 5. 6.]
 [3. 4. 5. 6. 7.]
 [4. 5. 6. 7. 8.]]
  • 优点:对于递增的构建稀疏矩阵很高效,比如定义该矩阵后,想进行每行每列更新值,可用该矩阵。当访问某个单元,只需要O(1)
  • 缺点:不允许重复索引(coo中适用),但可以很高效的转换成coo后进行重复索引。

4.3 lil_matrix

lil_matrix适用的场景也是逐渐添加矩阵的元素。与dok不同,lil_matrix则是使用两个列表存储非0元素。data保存每行中的非零元素,rows保存非零元素所在的列。这种格式也很适合逐个添加元素,并且能快速获取行相关的数据。

>>> l = sparse.lil_matrix((4, 4))
>>> l[1, 1] = 1
>>> l[1, 3] =2
>>> l[2, 3] = 3
>>> l.toarray()
array([[0., 0., 0., 0.],
       [0., 1., 0., 2.],
       [0., 0., 0., 3.],
       [0., 0., 0., 0.]])
>>> l.data
array([list([]), list([1.0, 2.0]), list([3.0]), list([])], dtype=object)
>>> l.rows
array([list([]), list([1, 3]), list([3]), list([])], dtype=object)
  • 优点:适合递增的构建成矩阵、转换成其它存储方式很高效、支持灵活的切片。
  • 缺点:当矩阵很大时,考虑用coo、算术操作,列切片,矩阵向量内积操作慢。

4.4 dia_matrix

如果稀疏矩阵仅包含非0元素的对角线,则对角存储格式(DIA)可以减少非0元素定位的信息量。这种存储格式对有限元素或者有限差分离散化的矩阵尤其有效。dia_matrix通过两个数组确定: data和offsets。其中data对角线元素的值;offsets:第i个offsets是当前第i个对角线和主对角线的距离。data[k:]存储了offsets[k]对应的对角线的全部元素。例子如下:
scipy.sparse,使用说明,python,矩阵,scipy

>>> data = np.array([[1, 2, 3, 4], [5, 6, 0, 0], [0, 7, 8, 9]])
>>> offsets = np.array([0, -2, 1])
>>> sparse.dia_matrix((data, offsets), shape=(4, 4)).toarray()
array([[1, 7, 0, 0],
       [0, 2, 8, 0],
       [5, 0, 3, 9],
       [0, 6, 0, 4]])

注意:offsets[0]=0表示第0个对角线与主对角线的距离为0,表示第0个对角线就是主对角线,data[0]就是第0个对角线的值。offsets[1]=-2表示第1个对角线与主对角线距离为-2,此时该对角线在主对角线的左下方,对角线上数值的数量为4-2=2,对应的值为data[1, :2+1],此时data[1, 3:]为无效的值,在构造对角稀疏矩阵时不起作用。offsets[2]=1表示第2个对角线与主对角线距离为1,此时该对角线在主对角线的右上方,对角线上数值的数量为4-1=3,对应的值为data[2, 1:],此时data[2, :1]为无效的值,在构造对角稀疏矩阵时不起作用。

4.5 csc_matrix & csr_matrix

csr_matrix是按行对矩阵进行压缩的,csc_matrix则是按列对矩阵进行压缩的。通过row_offsets,column_indices,data来确定矩阵。column_indices,data与coo格式的列索引与数值的含义完全相同,row_offsets表示元素的行偏移量。例子如下,

>>> 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_matrix((data, indices, indptr), shape=(3, 3)).toarray()
array([[1, 0, 2],
       [0, 0, 3],
       [4, 5, 6]])

注意:indices和data分别表示列索引和数据,第 i 行的列索引存储在indices[indptr[i]:indptr[i+1]] 中,对应的值为data[indptr[i]:indptr[i+1]]。即第0行的列索引为indices[0:2]=[0,2],值为data[0:2]=[1,2];第1行的列索引为indices[2:3]=[2],值为data[2:3]=[3]…

CSR格式常用于读入数据后进行稀疏矩阵计算。

两者的优缺点互反:

  • CSR优点:高效的稀疏矩阵算术操作、高效的行切片、快速地矩阵向量内积操作;

  • CSR缺点:缓慢地列切片操作(可以考虑csc)、转换到稀疏结构代价较高(可以考虑lil,dok)。

  • CSC优点:高效的稀疏矩阵算术操作、高效的列切片、快速地矩阵向量内积操作(不如csr,bsr块);

  • CSC缺点:缓慢地行切片操作(可以考虑csr)、 转换到稀疏结构代价较高(可以考虑lil,dok)。

4.6 bsr_matrix

基于行的块压缩,通过row_offsets,column_indices,data来确定矩阵。与csr相比,只是data中的元数据由0维的数变为了一个矩阵(块),其余完全相同。

>>> 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)).todense()
matrix([[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]])

优点:很类似于csr,更适合于矩阵的某些子矩阵很多值,在某些情况下比csr和csc计算更高效。

5. 稀疏矩阵的存取

5.1 用save_npz保存单个稀疏矩阵

>>> scipy.sparse.save_npz('sparse_matrix.npz', sparse_matrix)
>>> sparse_matrix = scipy.sparse.load_npz('sparse_matrix.npz')

稀疏矩阵存储大小比较:

a = np.arange(100000).reshape(1000,100)
a[10: 300] = 0
b = sparse.csr_matrix(a)
# 稀疏矩阵压缩存储到npz文件
sparse.save_npz('b_compressed.npz', b, True)  # 文件大小:100KB
# 稀疏矩阵不压缩存储到npz文件
sparse.save_npz('b_uncompressed.npz', b, False)  # 文件大小:560KB
# 存储到普通的npy文件
np.save('a.npy', a)  # 文件大小:391KB
# 存储到压缩的npz文件
np.savez_compressed('a_compressed.npz', a=a)  # 文件大小:97KB

对于存储到npz文件中的CSR格式的稀疏矩阵,内容为:

data.npy
format.npy
indices.npy
indptr.npy
shape.npy

6. 总结

  • 加载数据文件时使用coo_matrix快速构建稀疏矩阵,然后调用to_csr()、to_csc()、to_dense()把它转换成CSR或稠密矩阵(numpy.matrix)。
  • coo_matrix格式常用于从文件中进行稀疏矩阵的读写,而csr_matrix格式常用于读入数据后进行稀疏矩阵计算。

7. 参考

【1】https://blog.csdn.net/winycg/article/details/80967112
【2】https://blog.csdn.net/vor234/article/details/124935384文章来源地址https://www.toymoban.com/news/detail-810130.html

到了这里,关于【scipy.sparse包】Python稀疏矩阵详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • numpy 邻接矩阵转稀疏矩阵 array to scipy csr_matrix

    也就是说,一个dense的numpy矩阵,如何转换成scipy包里面的sparse的csr矩阵看代码: 输出: print(csr_a.toarray()) print(csr_a.tocoo())

    2024年02月12日
    浏览(15)
  • 使用python 将稀疏矩阵保存为mtx格式文件

    使用scipy包 创建一个稀疏矩阵 将稀疏矩阵转换成稠密矩阵 将稀疏矩阵保存为mtx格式文件 将稀疏矩阵保存为npz格式文件 参考链接:https://cmdlinetips.com/2021/04/save-sparse-matrix-in-python-to-mtx-and-npz-file/

    2024年02月13日
    浏览(15)
  • sparse conv稀疏卷积

     很好的教程,感谢作者的分享 通俗易懂的解释Sparse Convolution过程 - 知乎 稀疏卷积和普通卷积的区别 spconv和普通卷积没有区别,最重要的区别在于卷积的数据的存储方式和计算方法,这种计算方法可以增加计算稀疏点云的效率,其他的都是完全相同的(但SubMConv3d还是稍微有点

    2024年02月11日
    浏览(13)
  • 【python】用scipy生成特殊矩阵

    scipy.linalg 中提供了一系列特殊矩阵的生成方法,包括循环矩阵、汉克尔矩阵、费德勒矩阵、阿达马矩阵、莱斯利矩阵、希尔伯特及其逆矩阵、帕斯卡及其逆矩阵等。 现有一向量 c = [ c 0 , c 1 , ⋯   , c n ] c=[c_0, c_1,cdots,c_n] c = [ c 0 ​ , c 1 ​ , ⋯ , c n ​ ] ,则 circulant(c) 返回一

    2024年02月16日
    浏览(15)
  • 稀疏矩阵的三元组表示----(算法详解)

    目录 基本算法包括:(解释都在代码里) 1.创建 2.对三元组元素赋值 3.将三元组元素赋值给变量 4.输出三元组 5.转置(附加的有兴趣可以看看) 稀疏矩阵的概念:矩阵的非零元素相较零元素非常小时,这个矩阵就叫稀疏矩阵。 稀疏矩阵可以用 三元组表示 和 十字链表表示

    2024年01月21日
    浏览(10)
  • RLE 稀疏水平集 RLE sparse level sets 论文阅读笔记

    原文: Houston, Ben, Mark Wiebe, and Chris Batty. “RLE sparse level sets.” ACM SIGGRAPH 2004 Sketches. 2004. 137. 只有一页,这就是技术草案的含金量吗 run-length encoded, RLE 游程编码 为什么 run-length 会被翻译为游程 我理解它把连续的重复出现的数字编码成 值+出现次数 的思想 但是还是理解不了这

    2024年02月22日
    浏览(16)
  • 【字典学习+稀疏编码Sparse Encoding】简单介绍与sklearn的实现方式

    简单来说,稀疏编码就是把输入向量(信号)/ 矩阵(图像)表示为稀疏的系数向量和一组超完备基向量(字典)的线性组合。 因此,稀疏编码通过上述方式以后, 就可以将输入数据重构为稀疏的向量 :即向量内部元素满足只有很少的几个非零元素或只有很少的几个远大于

    2024年02月12日
    浏览(55)
  • 【华为OD统一考试B卷 | 100分】矩阵稀疏扫描、 稀疏矩阵(C++ Java JavaScript Python)

    在线OJ 已购买本专栏用户,请私信博主开通账号,在线刷题!!! 运行出现 Runtime Error 0Aborted,请忽略 华为OD统一考试A卷+B卷 新题库说明 2023年5月份,华为官方已经将的 2022/0223Q(1/2/3/4)统一修改为OD统一考试(A卷)和OD统一考试(B卷)。 你收到的链接上面会标注A卷还是B卷。

    2024年02月09日
    浏览(17)
  • matlab使用教程(13)—稀疏矩阵创建和使用

            使用稀疏矩阵存储包含众多零值元素的数据,可以节省大量内存并加快该数据的处理速度。 sparse 是一种属性,可以将该属性分配给由 double 或 logical 元素组成的任何二维 MATLAB 矩阵。通过 sparse 属性,MATLAB 可以:         • 仅存储矩阵中的非零元素及其索引。

    2024年02月13日
    浏览(14)
  • 华为OD机试 - 矩阵稀疏扫描(Java & JS & Python)

    题目描述 如果矩阵中的许多系数都为零,那么该矩阵就是稀疏的。对稀疏现象有兴趣是因为它的开发可以带来巨大的计算节省,并且在许多大的实践中都会出现矩阵稀疏的问题。 给定一个矩阵,现在需要逐行和逐列地扫描矩阵,如果某一行或者某一列内,存在连续出现的0的

    2024年02月11日
    浏览(9)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包