In [40]: a=np.ones((50,2,2),int); b=np.ones((50,2),int)
In [41]: np.einsum('bdc,ac->ab', a, b)
...
ValueError: axes don't match array
我不明白优化与此错误有什么关系。
对于第一个参数b,d,c
是 50,2,2。对于第二个a,c
是 50,2。结果应该是 50,50。但发生了什么事d
?
In [43]: np.einsum('bdc,ac->abd', a, b).shape
Out[43]: (50, 50, 2)
Oops:
In [49]: np.einsum('bdc,ac->ab', a, b, optimize=False).shape
Out[49]: (50, 50)
所以总结一下d
.
注意错误 - 通过优化,它使用tensordot
(转置加dot
),而不是原来的einsum
nditer
方法。
c_einsum
是那个能够处理缺失的人d
:
# If no optimization, run pure einsum
if optimize_arg is False:
return c_einsum(*operands, **kwargs)
尝试了一些时间安排:
使用默认优化的两步计算:
In [64]: timeit np.einsum('abd->ab', np.einsum('bdc,ac->abd', a, b))
288 µs ± 518 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
所需c_einsum
是比较快的
In [65]: timeit np.einsum('bdc,ac->ab', a, b, optimize=False)
170 µs ± 83.2 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In fact c_einsum
即使当tensordot
版本作品
In [67]: timeit np.einsum('bdc,ac->abd', a, b,optimize=False)
73.1 µs ± 46.6 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [68]: timeit np.einsum('bdc,ac->abd', a, b,optimize=True)
207 µs ± 6.97 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
这个例子可能太小,无法展示其优点tensordot/blas
.
看起来这已经在 github 上提出了——既有失败,也有较慢的“优化”速度:https://github.com/numpy/numpy/issues/10343 https://github.com/numpy/numpy/issues/10343“einsum 广播回归(optimize=True)”