【问题标题】:(Python) How to get diagonal(A*B) without having to perform A*B?(Python)如何获得对角线(A * B)而不必执行A * B?
【发布时间】:2013-06-30 13:01:15
【问题描述】:

假设我们有两个矩阵AB,让矩阵C 成为A*B(矩阵乘法不是元素)。我们希望只获得C 的对角线条目,这可以通过np.diagonal(C) 完成。但是,这会导致不必要的时间开销,因为我们将 A 与 B 相乘,即使我们只需要将 A 中的每一行与具有相同“id”的 B 的列相乘,即第 1 行AB 的第 1 列、A 的第 2 行与B 的第 2 列等等:形成C 对角线的乘法。有没有办法使用 Numpy 有效地实现这一目标?我想避免使用循环来控制哪一行与哪一列相乘,相反,我希望有一个内置的 numpy 方法来执行这种操作以优化性能。

提前谢谢..

【问题讨论】:

  • 请注意:NumPy 中的A*B 是逐元素乘法,而不是矩阵乘法(即a.dot(b))。
  • AB 类型为ndarraymatrix?
  • @Blair,如果ABnumpy.array,就是这种情况。如果是numpy.matrix,可以使用A*B
  • @gnibbler D'oh。我习惯于忘记numpy.matrix 的存在,因为我习惯性地使用三维数据。感谢您指出这一点。
  • @Bitwise、AB 是矩阵,抱歉没有澄清

标签: python numpy matrix


【解决方案1】:

我可能会在这里使用einsum

>>> a = np.random.randint(0, 10, (3,3))
>>> b = np.random.randint(0, 10, (3,3))
>>> a
array([[9, 2, 8],
       [5, 4, 0],
       [8, 0, 6]])
>>> b
array([[5, 5, 0],
       [3, 5, 5],
       [9, 4, 3]])
>>> a.dot(b)
array([[123,  87,  34],
       [ 37,  45,  20],
       [ 94,  64,  18]])
>>> np.diagonal(a.dot(b))
array([123,  45,  18])
>>> np.einsum('ij,ji->i', a,b)
array([123,  45,  18])

对于更大的数组,它会比直接做乘法快得多:

>>> a = np.random.randint(0, 10, (1000,1000))
>>> b = np.random.randint(0, 10, (1000,1000))
>>> %timeit np.diagonal(a.dot(b))
1 loops, best of 3: 7.04 s per loop
>>> %timeit np.einsum('ij,ji->i', a, b)
100 loops, best of 3: 7.49 ms per loop

[注意:最初我做了元素版本,ii,ii->i,而不是矩阵乘法。相同的 einsum 技巧有效。]

【讨论】:

    【解决方案2】:
    def diag(A,B):
        diags = []
        for x in range(len(A)):
            diags.append(A[x][x] * B[x][x])
        return diags
    

    我相信上面的代码就是你要找的。​​p>

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-29
    • 2021-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    • 2011-08-10
    相关资源
    最近更新 更多