没看出有什么优点csr
格式是在这种情况下。当然,所有非零值都收集在一个值中.data
数组,对应的列索引在.indices
。但它们是不同长度的块。这意味着它们不能并行处理或与numpy
数组步幅。
一种解决方案是将这些块填充为公共长度块。就是这样.toarray()
做。然后你可以找到最大值argsort(axis=1) or with
argpartition`。
另一种方法是将它们分成行大小的块,并处理每个块。这就是你正在做的.getrow
。另一种分解它们的方法是转换为lil
格式化并处理子列表.data
and .rows
arrays.
第三种可能的选择是使用ufunc
reduceat
方法。这可以让您申请ufunc
reduction
数组的连续块的方法。有设立ufunc
like np.add
利用这一点。argsort
不是这样的函数。但有一种方法可以构建ufunc
来自 Python 函数,并比常规 Python 迭代获得一定的速度。 [我需要查找最近的一个 SO 问题来说明这一点。]
我将用一个更简单的函数“行求和”来说明其中的一些内容。
If A2
是一个企业社会责任矩阵。
A2.sum(axis=1) # the fastest compile csr method
A2.A.sum(axis=1) # same, but with a dense intermediary
[np.sum(l.data) for l in A2] # iterate over the rows of A2
[np.sum(A2.getrow(i).data) for i in range(A2.shape[0])] # iterate with index
[np.sum(l) for l in A2.tolil().data] # sum the sublists of lil format
np.add.reduceat(A2.data, A2.indptr[:-1]) # with reduceat
A2.sum(axis=1)
被实现为矩阵乘法。这与排序问题无关,但仍然是看待求和问题的一种有趣的方式。记住csr
格式是为了有效乘法而开发的。
对于我当前的样本矩阵(为另一个稀疏问题创建)
<8x47752 sparse matrix of type '<class 'numpy.float32'>'
with 32 stored elements in Compressed Sparse Row format>
一些比较时间是
In [694]: timeit np.add.reduceat(A2.data, A2.indptr[:-1])
100000 loops, best of 3: 7.41 µs per loop
In [695]: timeit A2.sum(axis=1)
10000 loops, best of 3: 71.6 µs per loop
In [696]: timeit [np.sum(l) for l in A2.tolil().data]
1000 loops, best of 3: 280 µs per loop
其他都是 1ms 或更长。
我建议专注于开发单行函数,例如:
def max_n(row_data, row_indices, n):
i = row_data.argsort()[-n:]
# i = row_data.argpartition(-n)[-n:]
top_values = row_data[i]
top_indices = row_indices[i] # do the sparse indices matter?
return top_values, top_indices, i
然后看看 if 如何适合这些迭代方法之一。tolil()
看起来最有前途。
我还没有解决如何收集这些结果的问题。它们应该是列表的列表、具有 10 列的数组、另一个每行 10 个值的稀疏矩阵等等?
对大型稀疏数据的每一行进行排序并保存前 K 值和列索引 https://stackoverflow.com/questions/20297071/sorting-each-row-of-a-large-sparse-saving-top-k-values-column-index- 几年前有类似的问题,但没有答案。
scipy稀疏矩阵中每行或每列的Argmax https://stackoverflow.com/questions/30742572/argmax-of-each-row-or-column-in-scipy-sparse-matrix- 最近寻求问题argmax
对于行csr
。我讨论了一些相同的问题。
如何加快 numpy 中的循环速度? https://stackoverflow.com/questions/31622801/how-to-speed-up-loop-in-numpy/31623674#31623674- 如何使用的示例np.frompyfunc
创建一个ufunc
。我不知道结果函数是否具有.reduceat
method.
增加稀疏矩阵中前 k 个元素的值 https://stackoverflow.com/questions/24868129/increasing-value-of-top-k-elements-in-sparse-matrix/24868338#24868338- 获取 csr 的前 k 个元素(不是按行)。案例argpartition
.
行求和实现为np.frompyfunc
:
In [741]: def foo(a,b):
return a+b
In [742]: vfoo=np.frompyfunc(foo,2,1)
In [743]: timeit vfoo.reduceat(A2.data,A2.indptr[:-1],dtype=object).astype(float)
10000 loops, best of 3: 26.2 µs per loop
这是令人尊敬的速度。但我想不出一种编写可以实现的二元函数(需要两个参数)的方法argsort
通过减少。所以这可能是这个问题的死胡同。