scipy csr_matrix:了解 indptr
Posted
技术标签:
【中文标题】scipy csr_matrix:了解 indptr【英文标题】:scipy csr_matrix: understand indptr 【发布时间】:2019-02-17 08:17:30 【问题描述】:每隔一段时间,我都会操作csr_matrix
,但我总是忘记参数indices
和indptr
是如何协同工作来构建稀疏矩阵的。
在使用符号csr_matrix((data, indices, indptr), [shape=(M, N)])
定义稀疏矩阵时,我正在寻找关于indptr
如何与data
和indices
参数交互的清晰直观的解释。
我可以从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
然后将data
和indices
的元素映射到稀疏矩阵的行。这是通过以下推理完成的:
-
如果稀疏矩阵有 M 行,
indptr
是一个包含 M+1 个元素的数组
对于行 i,[indptr[i]:indptr[i+1]]
返回要从与行 i 对应的 data
和 indices
获取的元素的索引。所以假设indptr[i]=k
和indptr[i+1]=l
,对应行i 的数据将是data[k:l]
在列indices[k:l]
。这是棘手的部分,我希望下面的示例有助于理解它。
编辑:我将data
中的数字替换为字母以避免在以下示例中混淆。
注意:indptr
中的值必然会增加,因为indptr
(下一行)中的下一个单元格是指与该行对应的data
和indices
中的下一个值。
【讨论】:
感谢您试图说清楚,但仍然没有.. 您能否举一个 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]]
的data
和indices
不返回任何值。
一张图片值一千字。谢谢!【参考方案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?