【问题标题】:score calculation takes too long: avoid for loops - python分数计算时间过长:避免循环 - python
【发布时间】:2021-03-05 04:58:38
【问题描述】:

我是 python 新手,需要您的帮助。

我有三个矩阵,特别是:

  • 矩阵 M(矩阵类:scipy.sparse.csc.csc_matrix),维度:N x C;
  • 矩阵G(矩阵类:numpy.ndarray),维度:C x T;
  • 矩阵 L(矩阵类:numpy.ndarray),维度:T x N。

其中:N = 10000,C = 1000,T = 20。

我想计算一下,这个分数:

我尝试使用两个for 循环,一个用于i-index,一个用于c。此外,我使用dot 乘积来获得等式中的最后一个总和。但是我的实现需要太多时间才能给出结果。

这是我实现的:

    score = 0.0
    for i in range(N): 
        for c in range(C):
            Mic = M[i,c]
            score += np.outer(Mic,(np.dot(L[:,i],G[c,:])))

有没有办法避免两个for 循环?

提前谢谢你!

最好的

【问题讨论】:

  • 我并不感到惊讶。在numpy 数组上这样的迭代很慢,在稀疏数组上的迭代更慢。 csc 矩阵针对矩阵乘法进行了优化(dot),甚至需要显着程度的稀疏性(相对于总形状只有几个非零值)。当 Mic 是标量值时,为什么要使用 outer (可能是 0)?
  • 首先,G.dot(L) 甚至 G@L 应该给出一个 (C,N) 形状的数组。我打算建议M.dot(G@L),但那是 (N,N),而你想要它的对角线,或者更确切地说是它的轨迹。
  • 我会试试这个解决方案!谢谢!

标签: python for-loop optimization product sparse-matrix


【解决方案1】:

试试这个score = np.einsum("ic,ti,ct->", M, L, G)

EDIT1

顺便说一下,在您的情况下,score = np.sum(np.diag(M @ G @ L))(在从 3.5 版开始的 PYTHON3 中,您可以将@ 运算符的语义用于matmul 函数)比einsum 快(尤其是在@987654326 @由于有效地使用内存,也许@hpaulj 在他的评论中是这个意思)。但是einsum 更容易用于复杂的张量积(用einsum 编码我直接使用了你的数学表达式,没有考虑优化)。

通常,将fornumpy 一起使用会导致计算速度急剧下降(在numpy 的情况下考虑“矢量化计算”)。

【讨论】:

  • 我不认为einsumM 一起使用。 M.A 是的,如果有足够的内存。
  • 我的 8GB RAM 笔记本电脑没有内存问题(所有 M、L、G 为 float64)。
  • 非常感谢!如果我还想在最后一个总和的结果上应用日志(所以是点积的日志),有没有办法继续使用einsum?提前谢谢!
  • 这应该有效: score = np.sum(np.diag(M @ np.log(G @ L)))
  • 对于sum_i(sum_c M_ic * log (sum_t L_ti * G_ct)),使用einsum 不是一个好的解决方案(直接按照您的表达即:np.einsum("ic,ci->",M, np.log(np.einsum("ti,ct->ci",L,G))))。你有一个很好的解决方案。一条评论:np.sum(np.diag(A)) 方阵 Anp.trace(A) 相同。
猜你喜欢
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-20
  • 1970-01-01
  • 2015-08-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多