Python稀疏矩阵获取最大值和索引

5

我是一个有用的助手,可以为您进行文本翻译。

我有一个稀疏矩阵A(在密集形式下等于10 * 3),例如:

print type(A)
<class scipy.sparse.csr.csr_matrix>

print A
(0, 0)  0.0160478743808
(0, 2)  0.0317314165078
(1, 2)  0.0156596521648
(1, 0)  0.0575683686558
(2, 2)  0.0107481166871
(3, 0)  0.0150580924929
(3, 2)  0.0297743235876
(4, 0)  0.0161931803955
(4, 2)  0.0320187296788
(5, 2)  0.0106034409766
(5, 0)  0.0128109177074
(6, 2)  0.0105766993238
(6, 0)  0.0127786088452
(7, 2)  0.00926522256063
(7, 0)  0.0111941023699

每列的最大值为:
print A.max(axis=0)
(0, 0)  0.0575683686558
(0, 2)  0.0320187296788

I would like to get the index corresponding to the column value. I know that the

A.getcol(i).tolist()
will return me a list of each column which allow me to use argmax() function, but this way is really slow. I am wondering is there any descent way to do?


你的矩阵能够适应内存吗?只要A.todense()是可行的,执行A.todense().argmax(axis=0)会得到你想要的结果。 - kbrose
argmax 对于 scipy 稀疏矩阵来说是一个不错的增强功能。同时,您能否切换到 CSC 格式?如果可以的话,有一种相当高效的方法来获取列的 argmax。 - Warren Weckesser
@kbrose,由于数据大小超出内存限制,无法使用.todense()方法。 - KEXIN WANG
2个回答

3

在每个矩阵列中获取最大值和最大值的位置更有效的方法是使用scipy.sparse原生函数:

  • A中每个矩阵列的最大值:

    max_values = A.max(axis=0)

  • A中每个矩阵列的最大值位置:

    max_args = A.argmax(axis=0)

同样,可以使用axis=1计算每个矩阵行中的最大值和最大值位置,或者使用axis=None计算整个矩阵的最大值和最大值位置。


1
这是你在问题中提出的方法的微小变化:
col_argmax = [A.getcol(i).A.argmax() for i in range(A.shape[1])]

.A属性等同于.toarray()。)
(一个可能更有效的替代方法是)
B = A.tocsc()
col_argmax = [B.indices[B.indptr[i] + B.data[B.indptr[i]:B.indptr[i+1]].argmax()] for i in range(len(B.indptr)-1)]

任何一个都可以,但我必须问一下:如果你的数组形状为(10, 3),为什么要使用稀疏矩阵?(10,3)很小!只需使用常规的密集numpy数组即可。即使您保留A作为稀疏矩阵,计算该大小矩阵列的argmax最有效的方法可能是将其转换为密集数组并使用argmax方法:
col_argmax = A.A.argmax(axis=0)

嗨,Warren,非常感谢你的回答!我测试了你的解决方案,它比A.toarray()或.todense()函数更快。 - KEXIN WANG
唯一的问题是,当一个或多个矩阵列为空(全为0)时,您的方法无法正常工作。在这种情况下,只需为我返回一个随机数即可,因此我稍微修改了您的代码:def get_max(i): try: index = B.data[B.indptr[i]:B.indptr[i+1]].argmax() except: # 列的总和为零 # 换句话说,这个测试文档中没有任何单词出现在训练文档中 index = -1 return index maxval_index = [B.indices[B.indptr[i] + get_max(i)] for i in range(len(B.indptr)-1)] - KEXIN WANG
关于你为什么选择稀疏矩阵的问题,因为我的A矩阵实际大小为100k * 300k,我想计算A与另一个大矩阵的内积。CSR.dot函数非常快。这就是我选择稀疏矩阵的原因。 - KEXIN WANG
“...因为我的A矩阵的实际大小是100k * 300k...” 好的,这是使用稀疏矩阵的一个很好的理由。你应该在问题中包含这些信息。 - Warren Weckesser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接