我有两个 3D 矩阵:
a = np.random.normal(size=[3,2,5])
b = np.random.normal(size=[5,2,3])
我想要分别沿 2 轴和 0 轴的每个切片的点积:
c = np.zeros([3,3,5]) # c.size is 45
c[:,:,0] = a[:,:,0].dot(b[0,:,:])
c[:,:,1] = a[:,:,1].dot(b[1,:,:])
...
我想使用我尝试过的 np.tensordot (为了效率和速度)来做到这一点:
c = np.tensordot(a, b, axes=[2,0])
但我得到一个包含 36 个元素(而不是 45 个)的 4D 数组。c.shape, c.size = ((3L, 2L, 2L, 3L), 36)。我在这里找到了一个类似的问题(Numpy tensor: Tensordot over frontal slice of tensor),但这并不是我想要的,我无法推断出我的问题的解决方案。总而言之,我可以使用 np.tensordot 来计算上面显示的 c 数组吗?
更新#1
@hpaulj 的答案是我想要的,但是在我的系统(python 2.7 和 np 1.13.3)中,这些方法非常慢:
n = 3000
a = np.random.normal(size=[n, 20, 5])
b = np.random.normal(size=[5, 20, n])
t = time.clock()
c_slice = a[:,:,0].dot(b[0,:,:])
print('one slice_x_5: {:.3f} seconds'.format( (time.clock()-t)*5 ))
t = time.clock()
c = np.zeros([n, n, 5])
for i in range(5):
c[:,:,i] = a[:,:,i].dot(b[i,:,:])
print('for loop: {:.3f} seconds'.format(time.clock()-t))
t = time.clock()
d = np.einsum('abi,ibd->adi', a, b)
print('einsum: {:.3f} seconds'.format(time.clock()-t))
t = time.clock()
e = np.tensordot(a,b,[1,1])
e1 = e.transpose(0,3,1,2)[:,:,np.arange(5),np.arange(5)]
print('tensordot: {:.3f} seconds'.format(time.clock()-t))
a = a.transpose(2,0,1)
t = time.clock()
f = np.matmul(a,b)
print('matmul: {:.3f} seconds'.format(time.clock()-t))