【Scipy学习】Scipy中稀疏矩阵用法解析(sp.csr_matrix;sp.csc_matrix;sp.coo_matrix)

1 引言

  在矩阵处理中为了减少内存的占用经常用到各种形式的稀疏矩阵存储方式(比如单位阵,会造成空间浪费),这时就采用矩阵压缩的方式来表述,数据不变,存储形式发生改变,省很多空间。),scipy(一个Python库)就是一个利器。下面就介绍scipy中稀疏矩阵存储的各种函数,其中很多内容多有参考他人博客,就不一一在文中列出而是在参考文献中一并给出链接。

2 csr_matrix

  为了方便记忆可以把csr分成三个单词compress sparse row因此csr是按行压缩的稀疏矩阵。

2.1 csr_matrix 返回值解释

  csr_matrix矩阵返回值有三个属性indptr indices data 可以分别对应 count index data 三个通俗的解释。

  • 由于csr_matrix是按行压缩的矩阵indptr(count)为每行中元素不为0个数的计数,值得注意的是这个计数是累加的,详细的解释看下面的例子。
  • indices即index,表示每行中不为0元素的列的索引位置
  • data 就是压缩矩阵中不为0的元素,返回的值是按照从0行到n行的顺序来的

   '''
   # 原始矩阵orig样例:
   orig = array([[1, 0, 2],
               [0, 0, 3],
               [4, 5, 6]])

   CSR: 按【行row】来压缩,便于理解,进行重命名
   
       count,就是官方的indptr,是一个递增数组
           含义:【差值】是统计原始矩阵每【行】【非0数据】的【个数】,
               反向理解,就是【累加】原始矩阵每行的【非0数据】的【个数】
               对于count数组,假设索引为i,
               count[i+1] - count[i]就是原始矩阵【第i行】的【非0数据】的【个数】
           样例:
               当i=0时,count[1] - count[0] = 2-0 = 2, 表示原始矩阵【第0行】的【非0数据】有【2个】
               当i=1时,count[2] - count[1] = 3-2 = 1, 表示原始矩阵【第1行】的【非0数据】有【1个】
               当i=2时,count[3] - count[2] = 6-3 = 3, 表示原始矩阵【第2行】的【非0数据】有【3个】
               
       index, 就是官方的indices,是一个【列索引】数组
           含义:对于CSR,这里就是【列】的索引,即表示原始矩阵当前行中的【非0数据】所在的【列索引值】
               对于index和count数组,假设索引为i,
               index[count[i]: count[i+1]]表示原始矩阵中【第i行】的【非0数据】所在的【列索引值】
               ps:注意中间是【冒号】
               
           样例:
               当i=0时,index[count[0]:count[1]] = index[0:2]= [0,2], 
           表示原始矩阵【第0行】的【2个】【非0数据】所在的【列索引值】为0和2,即定位为orig[0,0]和orig[0,2]
               当i=1时,index[count[1]:count[2]] = index[2:3]= [2], 
           表示原始矩阵【第0行】的【1个】【非0数据】所在的【列索引值】为2,即定位为orig[1,2]
               当i=2时,index[count[2]:count[3]] = index[3:6]= [0,1,2], 
           表示原始矩阵【第0行】的【3个】【非0数据】所在的【列索引值】为0,1,2,即定位为orig[2,0], orig[2,1]和orig[2,2]
           
       data,保持不变, 按行顺序,存储【非0数据】的数组
           含义:根据index数组找到每行中【非0数据】的【列索引值】,依次存取数据即可
               对于data和count数组,假设索引为i,
               data[count[i]: count[i+1]]表示原始矩阵中【第i行】的【非0数据】的【值】
           样例:
               当i=0时,data[count[0]:count[1]] = data[0:2]= [1,2], 
           表示原始矩阵【第0行】的【2个】【非0数据】,即定位为orig[0,0] =1 和orig[0,2]=2
               当i=1时,index[count[1]:count[2]] = index[2:3]= [2], 
           表示原始矩阵【第0行】的【1个】【非0数据】,即定位为orig[1,2]=3
               当i=2时,index[count[2]:count[3]] = index[3:6]= [0,1,2], 
           表示原始矩阵【第0行】的【3个】【非0数据】,即定位为orig[2,0]=4, orig[2,1]=5 和orig[2,2]=6
   '''
   
   count = np.array([0, 2, 3, 6])
   index = np.array([0, 2, 2, 0, 1, 2])
   data = np.array([1, 2, 3, 4, 5, 6])

   # 将稀疏矩阵转为原始矩阵
   orig = csr_matrix((data, index, count), shape=(3, 3)).toarray()
   # 将原始矩阵转为稀疏矩阵
   res = csr_matrix(orig)
   
   print(res.indptr) 
   # [0 2 3 6] 
   print(res.indices)
   # [0 2 2 0 1 2]
   print(res.data)
   # [1 4 5 2 3 6]
   print(orig)
   # [[1 0 2]
   #  [0 0 3]    
   # [4 5 6]]
   print(res)
   # (0, 0)        1
   # (0, 2)        2
   # (1, 2)        3
   # (2, 0)        4
   # (2, 1)        5
   # (2, 2)        6

2.2 csr_matrix 定义矩阵

如何定义一个csr_matrix 矩阵大致总结为三种:

import scipy.sparse as sp
# 定义一个空的稀疏矩阵
s = sp.csr_matrix((3, 3))
print(s.shape)
# (3, 3)
根据行列索引建
row = [0, 1, 2]
col = [0, 0, 1]
value = [1, 2, 3]
s = sp.csr_matrix((value, (row, col)), shape=[3, 3])
print(s)
#  (0, 0)        1
#  (1, 0)        2
#  (2, 1)        3

# 上面的解释所建立的方式

3 csc_matrix

  为了方便记忆可以把csc分成三个单词compress sparse column因此csr是按列压缩的稀疏矩阵。

3.1 csc_matrix返回值的解释

  类比于跟csr的解释csc的解释相同。

  csc_matrix矩阵返回值有三个属性indptr indices data 可以分别对应 count index data 三个通俗的解释。

  • 由于csc_matrix是按列压缩的矩阵indptr(count)为每行中元素不为0个数的计数,值得注意的是这个计数是累加的,详细的解释看下面的例子。
  • indices即index,表示每列中不为0元素的行的索引位置
  • data 就是压缩矩阵中不为0的元素,返回的值是按照从0列到n列的顺序来的
  '''
  # 原始矩阵orig样例:
  orig = array([[1, 0, 4],
              [0, 0, 5],
              [2, 3, 6]])

  CSC: 按【列col】来压缩,便于理解,进行重命名
  
      count,就是官方的indptr,是一个递增数组
          含义:【差值】是统计原始矩阵每【列】【非0数据】的【个数】,
              反向理解,就是【累加】原始矩阵每列的【非0数据】的【个数】
              对于count数组,假设索引为i,
              count[i+1] - count[i]就是原始矩阵【第i列】的【非0数据】的【个数】
          样例:
              当i=0时,count[1] - count[0] = 2-0 = 2, 表示原始矩阵【第0列】的【非0数据】有【2个】
              当i=1时,count[2] - count[1] = 3-2 = 1, 表示原始矩阵【第1列】的【非0数据】有【1个】
              当i=2时,count[3] - count[2] = 6-3 = 3, 表示原始矩阵【第2列】的【非0数据】有【3个】
              
      index, 就是官方的indices,是一个【行索引】数组
          含义:对于CSC,这里就是【行】的索引,即表示原始矩阵当前列中的【非0数据】所在的【行索引值】
              对于index和count数组,假设索引为i,
              index[count[i]: count[i+1]]表示原始矩阵中【第i列】的【非0数据】所在的【行索引值】
              ps:注意中间是【冒号】
              
          样例:
              当i=0时,index[count[0]:count[1]] = index[0:2]= [0,2], 
          表示原始矩阵【第0列】的【2个】【非0数据】所在的【行索引值】为0和2,即定位为orig[0,0]和orig[2,0]
              当i=1时,index[count[1]:count[2]] = index[2:3]= [2], 
          表示原始矩阵【第0列】的【1个】【非0数据】所在的【行索引值】为2,即定位为orig[2,1]
              当i=2时,index[count[2]:count[3]] = index[3:6]= [0,1,2], 
          表示原始矩阵【第0列】的【3个】【非0数据】所在的【行索引值】为0,1,2,即定位为orig[0,2], orig[1,2]和orig[2,2]
          
      data,保持不变, 按列顺序,存储【非0数据】的数组
          含义:根据index数组找到每列中【非0数据】的【行索引值】,依次存取数据即可
              对于data和count数组,假设索引为i,
              data[count[i]: count[i+1]]表示原始矩阵中【第i列】的【非0数据】的【值】
          样例:
              当i=0时,data[count[0]:count[1]] = data[0:2]= [1,2], 
          表示原始矩阵【第0列】的【2个】【非0数据】,即定位为orig[0,0] =1 和orig[2,0]=2
              当i=1时,index[count[1]:count[2]] = index[2:3]= [2], 
          表示原始矩阵【第0列】的【1个】【非0数据】,即定位为orig[2,1]=3
              当i=2时,index[count[2]:count[3]] = index[3:6]= [0,1,2], 
          表示原始矩阵【第0列】的【3个】【非0数据】,即定位为orig[0,2]=4, orig[1,2]=5 和orig[2,2]=6
  '''
  
  count = np.array([0, 2, 3, 6])
  index = np.array([0, 2, 2, 0, 1, 2])
  data = np.array([1, 2, 3, 4, 5, 6])

  # 将稀疏矩阵转为原始矩阵
  orig = csc_matrix((data, index, count), shape=(3, 3)).toarray()
  # 将原始矩阵转为稀疏矩阵
  res = csc_matrix(orig)
  
  print(res.indptr) 
  # [0 2 3 6]
  print(res.indices)
  # [0 2 2 0 1 2]
  print(res.data)
  # [1 4 5 2 3 6]
  print(orig)
  # [[1 0 4]
  # [0 0 5]
  # [2 3 6]]
  print(res)
  # (0, 0)        1
  # (2, 0)        2
  # (2, 1)        3
  # (0, 2)        4
  # (1, 2)        5
  # (2, 2)        6

4 coo_matrix

coo_matrix是坐标格式矩阵,给定存在元素的行列位置和值直接生成矩阵。

from scipy.sparse import coo_matrix
import numpy as np
row = np.array([1, 1, 3, 2]) # 行索引
col = np.array([0, 2, 2, 3]) # 列索引
data= np.array([5, 8, 4, 9]) # 索引对应的数值
coo = coo_matrix((data, (row, col)), shape=(4, 4)).todense()
#先看shape,表示这个稀疏矩阵是4x4大小的,所有值初始都为0,即4x4的全0矩阵
#(row, col)行、列组合就表示一个具体的位置,其(1,0),(1,2),(3,2),(2,3)就是4x4矩阵的索引位置。
#data,表示索引位置上的数值,即(1,0)上的数值为5,(1,2)上的数值为8,等等。
#todense,作用可以自己试试,如果没有这个函数,则输出如下结果
#  (1, 0)	5
#  (1, 2)	8
#  (3, 2)	4
#  (2, 3)	9
print(coo)
#打印出coo稀疏矩阵

5 稀疏矩阵的运算

5.1 加法

两个稀疏矩阵相加直接加

row = [0, 1, 2]
col = [0, 0, 1]
value = [1, 2, 3]
a = sp.csr_matrix((value, (row, col)), shape=[3, 3])
b = a
c = a+b
print(c)
#   (0, 0)        2
#   (1, 0)        4
#   (2, 1)        6

5.2 乘法

可以是两个稀疏矩阵相乘,乘完后还是稀疏矩阵

row = [0, 1, 2]
col = [0, 0, 1]
value = [1, 2, 3]
a = sp.csr_matrix((value, (row, col)), shape=[3, 3])
b = a
c = a.dot(b)
print(c)
#  (0, 0)        1
#  (1, 0)        2
#  (2, 0)        6

也可以是稀疏矩阵乘以一个稠密矩阵(顺序不能换,不能是稠密矩阵乘以稀疏矩阵,如果需要则先调换二者顺序为 sparse x dense,乘完再转置回来),乘完之后c是稠密矩阵,这类似于tensorflow中的 tf.sparse_tensor_dense_matmul 操作

row = [0, 1, 2]
col = [0, 0, 1]
value = [1, 2, 3]
a = sp.csr_matrix((value, (row, col)), shape=[3, 3])
b = a.todense()
c = a.dot(b)
print(c)
>>> [[1 0 0]
	 [2 0 0]
	 [6 0 0]]

5.3 提取行列

稀疏矩阵提取行列和稠密矩阵提取一样

row = [0, 1, 2]
col = [0, 0, 1]
value = [1, 2, 3]
a = sp.csr_matrix((value, (row, col)), shape=[3, 3])
print('a的第0行\n', a[0], '\n a的第0列\n', a[:, 0])
>>>  a的第0(0, 0)       1
	 a的第0(0, 0)       1
	   (1, 0)        2

6 参考文献

[1]稀疏矩阵详解:csr_matrix和csc_matrix
[2]scipy.sparse csr_matrix()
[3]Scipy.sparse模块中的coo_matrix、csc_matrix、csr_matrix函数
[4]十分钟理解Scipy.csc_matrix和coo_matrix

  • 16
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个错误提示说明你的代码使用了 `scipy.sparse` 模块的 `coo_array` 属性,但是该属性并不存在。可能是你的代码存在拼写错误或者版本不兼容等问题。 正常情况下,`scipy.sparse` 模块存在的属性包括:`coo_matrix`, `csr_matrix`, `csc_matrix`, `lil_matrix` 等。如果你想使用的 `coo_matrix`,可以通过以下方式导入: ```python from scipy.sparse import coo_matrix ``` 希望这能帮助你解决问题! ### 回答2: 这个错误提示意味着在导入Scipy库的稀疏模块时,没有找到名为“coo_array”的属性。Scipy是一个Python科学计算工具库,提供了多种数学、科学和工程计算的基础算法和工具,其的稀疏模块包含了处理大规模稀疏矩阵的函数和类。COOCoordinate Format)是稀疏矩阵的一种存储格式,具有行列坐标和元素值三个属性,方便表示和处理非零元素稀疏的矩阵。 出现上述错误提示可能的原因有以下几种: 1. Scipy库的版本过低,不支持coo_array属性。这时可以尝试升级Scipy库,或使用稀疏矩阵的其他格式和函数,比如csr_matrix或lil_matrix等。 2. 导入Scipy.sparse时,没有正确声明所需的属性。可以查看代码Scipy.sparse的导入语句是否正确,或使用wildcard import语句,如“from scipy.sparse import *”,但这种方式可能会导致命名空间冲突和不必要的内存开销。 3. 项目使用了自定义版本或修改过的Scipy库,导致与标准库不兼容。可以检查自己的代码和环境是否有相关修改,并确认其对coo_array的影响。 总之,在使用Scipy库时,应该尽量避免过度依赖某个属性或版本,保证代码的可移植性和兼容性。在出现错误或无法解决的问题时,可以查看官方文档、提问社区或参考其他可靠资源,获得更多信息和帮助。 ### 回答3: 这个错误信息是由于在使用scipy.sparse模块的coo_array函数时出现了问题,可能是因为该函数不存在或者在该模块被重命名或移除了。 Scipy是一个用于科学计算的Python库,它包含了很多用于数值计算、统计、优化、信号处理和图像处理等方面的功能模块。其sparse模块则提供了稀疏矩阵的处理功能。 COO格式是稀疏矩阵的一种常见表示方法,它使用三个数组分别存储稀疏矩阵的行、列和非零元素。coo_matrix函数可以将一个稀疏矩阵表示成COO格式,而coo_array函数就是用于将一个普通的数组表示成COO格式的函数。 可能导致这个错误的原因有多种,其比较常见的是版本不兼容问题。有时候,在更新Scipy库的过程,某些函数会被重命名或者移除,这样就会导致之前的代码出现了问题。 解决方法一般是查看当前使用Scipy库版本,并在官方文档里查找该函数的具体情况。如果该函数已经失效,在代码使用新的相应函数代替即可。另外,也可以考虑在导入库时指定具体的函数,例如:from scipy.sparse import coo_matrix,而不是直接导入整个模块。这样可以避免因为重名函数导致的错误。 总之,要解决这个错误,需要了解Scipy稀疏矩阵以及COO格式的相关知识,并检查当前的库版本以及所使用的函数。只要将代码出错的函数替换为正确的函数即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值