scipy csr_matrix:了解 indptr

Posted

技术标签:

【中文标题】scipy csr_matrix:了解 indptr【英文标题】:scipy csr_matrix: understand indptr 【发布时间】:2019-02-17 08:17:30 【问题描述】:

每隔一段时间,我都会操作csr_matrix,但我总是忘记参数indicesindptr 是如何协同工作来构建稀疏矩阵的。

在使用符号csr_matrix((data, indices, indptr), [shape=(M, N)]) 定义稀疏矩阵时,我正在寻找关于indptr 如何与dataindices 参数交互的清晰直观的解释。

我可以从scipy documentation 看到data 参数包含所有非零数据,indices 参数包含与该数据关联的列(因此,indices 等于@987654332 @ 在文档中给出的示例中)。但是我们如何才能清楚地解释indptr参数呢?

【问题讨论】:

查看lil 等效项可能会有所帮助。 @Tanguy 描述的连续切片 M.indices[indptr[i]:indptr[i+1]] 对应于 lil rows 数组中的列表。 【参考方案1】:

在这个例子中:

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 告诉非零数据元素的数量,从开始到第三行结束。

【讨论】:

【参考方案2】:

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

我们使用:

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

【讨论】:

【参考方案3】:
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 文档。

数据数组包含按行遍历的稀疏矩阵中存在的非零元素。

索引数组给出每个非零数据点的列号。

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

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

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

希望你明白这一点。

【讨论】:

【参考方案4】:

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

data 是一个包含稀疏矩阵的所有非零元素的数组。 indices 是一个数组,将data 中的每个元素映射到稀疏矩阵中的列。

indptr 然后将dataindices 的元素映射到稀疏矩阵的行。这是通过以下推理完成的:

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

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

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

【讨论】:

感谢您试图说清楚,但仍然没有.. 您能否举一个 M 的示例,然后从一行中执行第 2 点,解释 indices 和 @987654343 中的哪些值@ 它来了?我试图遵循一个例子,但我没有得到它。 我花了一些时间来理解这一点(但比我必须自己研究它要短得多),但我现在明白了。让我绊倒的部分是数据的连续值。一直认为这些值代表了列。如果它们是随机值,我认为这将有助于读者更快地理解。不过很棒。谢谢。 @ivankeller:将您的问题更新为编辑后的示例/图片:“indptr 的最后一个元素不应该是 10 而不是 11?” --> 否,因为在 python 中对数据结构进行子集时未选择范围中的最后一个元素(例如data[l] 不包含在data[k:l] 中)。 @spacedustpi:我用字母替换了data 中的值,希望能避免进一步混淆。关于你关于空行的问题,@a-nadjar 举了一个例子。如果第 i 行为空,则 indptr 的第 i 值等于第 i+1 值,因此子集范围为[indptr[i]:indptr[i+1]]dataindices 不返回任何值。 一张图片值一千字。谢谢!【参考方案5】:

当然,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)

【讨论】:

以上是关于scipy csr_matrix:了解 indptr的主要内容,如果未能解决你的问题,请参考以下文章

对 scipy.sparse.csr_matrix 中的行求和

scipy csr_matrix和csc_matrix函数详解

为啥 scipy 的稀疏 csr_matrix 的向量点积比 numpy 的密集数组慢?

(Python Scipy)如何展平一个 csr_matrix 并将其附加到另一个 csr_matrix?

scipy.sparse.csr.csr_matrix 未显示在变量资源管理器中

ndarray 与 scipy.sparse.csr.csr_matrix 的互转