scipy csr_matrix:了解indptr

scipy csr_matrix: understand indptr

每隔一段时间,我就会操作一个 csr_matrix,但我总是忘记参数 indicesindptr 如何共同构建一个稀疏矩阵。

我正在寻找关于在使用符号 [=18= 定义稀疏矩阵时 indptr 如何与 dataindices 参数交互的清晰直观的解释].

我可以从 scipy documentation 中看到 data 参数包含所有非零数据,并且 indices 参数包含与该数据关联的列(因此, indices 等于文档中给出的示例中的 col)。但是indptr这个参数怎么解释清楚呢?

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

  • data是一个包含稀疏矩阵所有非零元素的数组。
  • indices 是一个数组,将 data 中的每个元素映射到其在稀疏矩阵中的列。
  • indptr 然后将 dataindices 的元素映射到稀疏矩阵的行。这是根据以下推理完成的:

    1. 如果稀疏矩阵有M行,indptr是一个包含M+1个元素的数组
    2. for row i, [indptr[i]:indptr[i+1]] returns 取自 dataindices 对应行的元素索引。所以假设 indptr[i]=kindptr[i+1]=l,对应行 i 的数据将是 data[k:l] 在列 indices[k:l]。这是棘手的部分,我希望下面的例子有助于理解它。

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

注意:indptr 中的值必然增加,因为 indptr 中的下一个单元格(下一行)指的是 data 和 [=11] 中的下一个值=] 对应于该行。

没错,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)
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 文档。

  • 数据数组包含遍历的稀疏矩阵中存在的 non-zero 个元素 row-wise。

  • 索引数组给出每个 non-zero 数据点的列号。

  • 例如:-col[0] 表示数据中的第一个元素,即 1,col[2] 表示数据中的第二个元素,即 2,依此类推,直到最后一个数据元素,因此大小数据数组和索引数组的相同。

  • indptr 数组基本上表示行的第一个元素的位置。它的大小比行数多一。

  • 例如:- indptr 的第一个元素是 0,表示 row[0] 的第一个元素出现在 data[0],即 '1',indptr 的第二个元素是 2,表示row[1] 中出现在 data[2] 中的第一个元素,即元素“3”,indptr 的第三个元素是 3,表示 row[2] 中的第一个元素在 data[3] 中,即“4”。

  • 希望你明白了。

由于这是一个稀疏矩阵,这意味着矩阵中的非零元素相对于整个元素($m \times n$)来说是非常少的。

我们使用:

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

在这个例子中:

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 表示非零数据元素的数量,从第三行开始到末尾。