2矢量矩阵点积的性能

ibl*_*asi 1 python performance numpy dot-product

问题更侧重于计算的表现.

我有2个矢量矩阵.这意味着它们具有X,Y,Z的3个深度尺寸.矩阵的每个元素必须与另一个矩阵的相同位置上的元素制作点积.

一个简单而无效的代码就是这个:

import numpy as np
a = np.random.uniform(low=-1.0, high=1.0, size=(1000,1000,3))
b = np.random.uniform(low=-1.0, high=1.0, size=(1000,1000,3))
c = np.zeros((1000,1000))
numRow,numCol,numDepth = np.shape(a)

for idRow in range(numRow):
    for idCol in range(numCol):
        # Angle in radians
        c[idRow,idCol] = math.acos(a[idRow,idCol,0]*b[idRow,idCol,0] + a[idRow,idCol,1]*b[idRow,idCol,1] + a[idRow,idCol,2]*b[idRow,idCol,2])
Run Code Online (Sandbox Code Playgroud)

但是,numpy函数可以加快计算速度,使代码更快:

# Angle in radians
d = np.arccos(np.multiply(a[:,:,0],b[:,:,0]) + np.multiply(a[:,:,1],b[:,:,1]) + np.multiply(a[:,:,2],b[:,:,2]))
Run Code Online (Sandbox Code Playgroud)

但是,我想知道是否还有其他的sintaxis可以通过其他函数,索引来改进上面的这个...

首先代码需要4.658s,而第二个需要0.354s

ask*_*han 5

您可以使用np.einsum,在任何轴上相乘,然后求和:

np.arccos(np.einsum('ijk,ijk->ij', a, b))
Run Code Online (Sandbox Code Playgroud)

你在问题中发布的更直接的方法就是使用np.sum,你沿着最后一个轴(-1)求和:

np.arccos(np.sum(a*b, -1))
Run Code Online (Sandbox Code Playgroud)

他们都给出了相同的答案,但einsum速度最快,sum是下一个:

In [36]: timeit np.arccos(np.einsum('ijk,ijk->ij', a, b))
10000 loops, best of 3: 20.4 µs per loop

In [37]: timeit e = np.arccos(np.sum(a*b, -1))
10000 loops, best of 3: 29.8 µs per loop

In [38]: %%timeit
   ....: d = np.arccos(np.multiply(a[:,:,0],b[:,:,0]) +
   ....:               np.multiply(a[:,:,1],b[:,:,1]) +
   ....:               np.multiply(a[:,:,2],b[:,:,2]))
   ....:
10000 loops, best of 3: 34.6 µs per loop
Run Code Online (Sandbox Code Playgroud)