这是一个典型应用np.tensordot()
:
sum = np.tensordot(A, B, [[0,2],[0,1]])
定时
使用下面的代码:
import numpy as np
n_examples = 100
A = np.random.randn(n_examples, 20,30)
B = np.random.randn(n_examples, 30,5)
def sol1():
sum = np.zeros([20,5])
for i in range(len(A)):
sum += np.dot(A[i],B[i])
return sum
def sol2():
return np.array(map(np.dot, A,B)).sum(0)
def sol3():
return np.einsum('nmk,nkj->mj',A,B)
def sol4():
return np.tensordot(A, B, [[2,0],[1,0]])
def sol5():
return np.tensordot(A, B, [[0,2],[0,1]])
结果:
timeit sol1()
1000 loops, best of 3: 1.46 ms per loop
timeit sol2()
100 loops, best of 3: 4.22 ms per loop
timeit sol3()
1000 loops, best of 3: 1.87 ms per loop
timeit sol4()
10000 loops, best of 3: 205 µs per loop
timeit sol5()
10000 loops, best of 3: 172 µs per loop
在我的电脑上tensordot()
是最快的解决方案,改变为使评估轴并不会改变结果n性能。
感谢您的详细回复!它确实在我的电脑上生成了最快的解决方案!但是,如果增加矩阵大小(从20x30,30x5到600x300,300x10),sol1()会再次变快,比“tensordot”解决方案快5倍。我想知道为什么在Python中循环会比本地C实现更快,比如'tensordot' – aha
@aha,这对我来说也是一个惊喜,我期望'tensordot()'更快。你是否也比较了'sol4()'和'sol5()',改变了轴的评估顺序?也许这可以有所作为... –
使用'600x300','300x10'的矩阵大小,'sol1()'需要'16.5ms','sol4()'需要'113ms'和'sol5()'需要' 89ms' – aha