scipy csr矩阵:理解indptr

jc3wubiy  于 2022-11-10  发布在  其他
关注(0)|答案(6)|浏览(199)

每隔一段时间,我都会操作一个csr_matrix,但我总是忘记参数indicesindptr是如何一起工作来构建稀疏矩阵的。
我希望在使用符号csr_matrix((data, indices, indptr), [shape=(M, N)])定义稀疏矩阵时,能够清楚直观地解释indptr如何与dataindices参数交互。
我可以从scipy documentation中看到,data参数包含所有非零数据,indices参数包含与该数据关联的列(因此,在文档中给出的示例中,indices等于col)。但是,我们如何清楚地解释indptr参数呢?

xeufq47z

xeufq47z1#

也许这样的解释可以帮助理解这个概念:

  • data是包含稀疏矩阵的所有非零元素的数组。
  • indices是将data中的每个元素Map到其在稀疏矩阵中的列的数组。

1.然后,indptrdataindices的元素Map到稀疏矩阵的行。
1.如果稀疏矩阵有M行,则indptr是包含M+1个元素的数组
1.对于行i[indptr[i]:indptr[i+1]]返回要从dataindices中获取的对应于行i的元素的索引。因此,假设indptr[i]=kindptr[i+1]=l,对应于行i的数据将是data[k:l],位于列indices[k:l]。这是比较棘手的部分,我希望下面的示例有助于理解它。

EDIT:在下面的示例中,我用字母替换了data中的数字,以避免混淆。

注意:indptr中的值必然会增加,因为indptr中的下一个单元格(下一行)引用了与该行对应的dataindices中的下一个值。

x7rlezfr

x7rlezfr2#

当然,indptr中的元素是按升序排列的,但如何解释indptr的行为呢?简而言之,直到indptr中的元素相同或不增加,您才可以跳过稀疏矩阵的行索引。
下面的示例说明了indptr元素的上述解释:
例1)设想这样的矩阵:

array([[0, 1, 0],
       [8, 0, 0],
       [0, 0, 0],
       [0, 0, 0],
       [0, 0, 7]])

mat1 = csr_matrix(([1,8,7], [1,0,2], [0,1,2,2,2,3]), shape=(5,3))
mat1.indptr

# array([0, 1, 2, 2, 2, 3], dtype=int32)

mat1.todense()  # to get the corresponding sparse matrix

示例2)CSR_matrix的数组(稀疏矩阵已经存在的情况):

arr = np.array([[0, 0, 0],
                [8, 0, 0],
                [0, 5, 4],
                [0, 0, 0],
                [0, 0, 7]])

mat2 = csr_matrix(arr))
mat2.indptr

# array([0, 0, 1, 3, 3, 4], dtype=int32)

mat2.indices

# array([0, 1, 2, 2], dtype=int32)

mat.data

# array([8, 5, 4, 7], dtype=int32)
os8fio9y

os8fio9y3#

在此范例中:

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]])

要读取indptr,请执行以下操作-

  • 忽略indptr[0] = 0
  • indptr[1] = 2表示非零数据元素的数量,直到第一行的末尾
  • indptr[2] = 3表示从第二行开始到结束的非零数据元素的数量。
  • indptr[3] = 6表示从第三行的开头到结尾的非零数据元素的数量。
jq6vz3qz

jq6vz3qz4#

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]])

在上面的示例中,来自scipy文档。

  • 该数据数组包含按行遍历的稀疏矩阵中存在的非零元素。
  • indices数组给出每个非零数据点的列号。
  • 例如:-col[0]用于数据中的第一个元素,即1,col[2]用于数据中的第二个元素,即2,依此类推,直到最后一个数据元素,因此数据数组和索引数组的大小相同。
  • indptr数组基本上指示了行中第一个元素的位置,其大小比行数多一。
  • 例如:-indptr的第一个元素是0,表示行[0]的第一个元素出现在data[0]处,即“1”,indptr的第二个元素是2,表示行[1]中的第一个元素出现在data[2]处,即元素“3”,indptr的第三个元素是3,表示行[2]的第一个元素出现在data[3]处,即“4”。
  • 希望你明白我的意思。
webghufk

webghufk5#

由于这是一个稀疏矩阵,这意味着与整个元素($m \times n$)相比,矩阵中的非零元素相对非常少。
我们用途:

  • data存储所有非零元素,从左到右,从上到下
  • indices来存储这些数据中的每一个的所有列索引
  • indptr[i]:indptr[i+1]表示data字段中的切片,以查找行[i]的所有非零元素
iecba09b

iecba09b6#

可以将indptr中的值看作是 * a在压缩前(稀疏)格式的特定行开始之前**已经传递的非零元素的数量。这很难理解,但下面的示例应该可以解释清楚。

import numpy as np
from scipy.sparse import csr_matrix

array_for_csr = np.array([[2, 0, 19, 5],
                          [8, 0, 0, 1],
                          [0, 0, 0, 0],
                          [4, 6, 6, 0]])
matrix = csr_matrix(array_for_csr)
print(matrix)
"""
(0, 0)  2
(0, 2)  19
(0, 3)  5
(1, 0)  8
(1, 3)  1
(3, 0)  4
(3, 1)  6
(3, 2)  6
"""
print(matrix.indices)

# [0 2 3 0 3 0 1 2]

print(matrix.indptr)

# [0 3 5 5 8]

前。
indptr[0] = 0,因为在预压缩矩阵的第一行开始之前,矩阵中的0个值已经被传递(由于我们还没有开始遍历矩阵,因此没有值被传递)

  • indptr[1] = 3,因为在预压缩矩阵中的第2行开始之前已经经过了矩阵中的3个值(值2、19、5)
    indptr[2] = 5,因为在预压缩矩阵中的第3行开始之前已经经过了矩阵中的5个值(值2、19、5、8、1)。
    indptr[3] = 5,因为在预压缩矩阵中的第4行开始之前已经经过了矩阵中的5个值(因为预压缩矩阵的第4行中的所有值都是零)
    indptr[4] = 8,因为在预压缩矩阵中的第5行开始之前,矩阵中的8个值已经过去(indptr阵列中的最后一个值将总是等于预压缩(稀疏)矩阵中的非零值的数目

相关问题