我有一个CSC格式的矩阵A,其中我只索引一列
b = A[:,col]
产生(n×1)矩阵。我想做的是:
v = M * b
其中M是CSR中的(n×n)矩阵。结果v是(n×1)CSR矩阵。我需要迭代v中的值(实际上不包括0)并检索满足特殊条件的一个元素的索引(注意:未选择稀疏矩阵格式以适合该特定操作,但是一般矩阵x矩阵产品应该是CSR * CSC最快,对吗?)
问题是,迭代CSR格式的向量中的条目(0< i< n< n [v [i,0])非常慢并且我实际上浪费了相当多的内存,因为v不再稀疏。有人能告诉我如何执行这些操作,我可以快速迭代结果向量,保持与副本相关的内存开销很小吗?
IN: M (CSR-Matrix), A (CSC-Matrix), col_index
v = M * A[:,col_index]
for entries in v:
do stuff
是否有可能以某种方式加快CSC-Matrix中列的“高级”索引?在代码中的其他一点,我必须提取A的子矩阵(不能重新配置以允许切片,因此使用索引数组),其包括所有列的给定子集。线条剖析时,[:,idxlist]需要很长时间。
期待您的建议
答案 0 :(得分:1)
scipy稀疏模块在每个版本中都会越来越好,但很明显它正在进行中,所以通过直接访问对象的内部可以做很多优化。例如。你的情况:
>>> a = sps.rand(5, 20, density=0.2, format='csr')
>>> b = sps.rand(20, 1, density=0.2, format='csc')
>>> c = a * b
>>> c.A
array([[ 0.30331594],
[ 0. ],
[ 0.12198742],
[ 0.34350077],
[ 0. ]])
您可以将c
的非零条目设为c.data
:
>>> c.data
array([ 0.30331594, 0.12198742, 0.34350077])
获取相应的行号有点棘手。可能最简单的方法是将输出转换为CSC格式,因为它们直接将它们设为c.indices
,而c.data
仍然与以前相同:
>>> c.tocsc().indices
array([0, 2, 3])
>>> c.tocsc().data
array([ 0.30331594, 0.12198742, 0.34350077])
但如果你不喜欢它,你可以在不进行转换的情况下提取它们:
>>> np.where(c.indptr[:-1] != c.indptr[1:])[0]
array([0, 2, 3], dtype=int64)
所以如果你想找到,例如最大值及其行号,您可以这样做:
>>> row_idx = np.where(c.indptr[:-1] != c.indptr[1:])[0]
>>> idx = np.argmax(c.data)
>>> c.data[idx], row_idx[idx]
(0.34350077450601624, 3)
答案 1 :(得分:1)
在Code Review问题中,我正在探索加速稀疏矩阵行的迭代的方法,https://codereview.stackexchange.com/questions/32664/numpy-scipy-optimization/33566#33566
csr
getrow
出乎意料地缓慢。至少对于那个小测试用例,将稀疏矩阵转换为密集数组更快,并使用常规的numpy索引(使用np.nonzero
来获取稀疏条目)。将矩阵转换为lil
并在zip(X.data, X.rows)
上进行常规Python迭代同样快。
我的印象是scipy.sparse
最适合线性代数问题,而且索引和迭代速度慢。