如何矢量化此 python 代码以使其更高效? (速度)

how to vectorize this python code to make it more efficient? (in speed)

我正在尝试使用 numpy 模块对我的代码进行矢量化,原始代码如下:

m = [M[i,:9].dot(N[:9,i]) for i in xrange(9)]

并且我将代码改进为:

m = np.diagonal(M[:9,:9].dot(N[:9,:9]))  

但这会导致一些不必要的计算(尤其是当索引远大于9时)。我可以做些什么来进一步提高效率?

编辑:基本上我打算做的是计算两个矩阵 M 和 N 的点积的对角线元素。

您可以使用 np.einsum,因为我们需要保持 M 的第一个轴与 N 的第二个轴对齐,而 reducing/losing 剩余的轴输入。因此,我们将有一个基于 einsum 的解决方案,如下所示:

m = np.einsum('ij,ji->i',M[:,:9],N[:9,:])

假设两个矩阵都是方阵并且具有相同的维度,这就是我们可以做的:

  1. 根据矩阵乘法的定义,你要计算的结果基本上是一个点积向量。结果向量的第一个元素是M的第一行与N的第一列的点积,然后是M的第二行与N的第二列的点积,依此类推

  2. 我们可以通过转置 N,然后将 M 和 NT 按元素相乘,然后将每一行相加来表达此计算。这给了我们一个结果列向量。这是代码:

    Nprime = np.transpose(N[:,:9])
    product = np.multiply(M[:9,:], Nprime)
    result = np.sum(product, axis=1)
    

    根据Divakar的建议,可以浓缩成一行:

    result = (M[:,:9] * (N[:9,:].T)).sum(1)
    

示例(尺寸为 3 而不是 9):

import numpy as np

>>> M = np.array(
    [[1, 2, 3],
     [6, 5, 4],
     [8, 7, 9]])

>>> N = np.array(
    [[0, 9, 7],
     [2, 4, 5],
     [6, 8, 1]])

>>> M.dot(N)
array([[22,  41,  20],
       [34, 106,  71],
       [68, 172, 100]])

>>> np.diagonal(M.dot(N))
array([22, 106, 100])
# ^ The reference answer

>>> Nprime = np.transpose(N)
array([[0, 2, 6],
       [9, 4, 8],
       [7, 5, 1]])

>>> product = np.multiply(M, Nprime)
array([[ 0,  4, 18],
       [54, 20, 32],
       [56, 35,  9]])

>>> result = np.sum(product, axis=1)
array([22, 106, 100])