我创建了这个玩具问题,反射(reflect)了我更大的问题:
import numpy as np
ind = np.ones((3,2,4)) # shape=(3L, 2L, 4L)
dist = np.array([[0.1,0.3],[1,2],[0,1]]) # shape=(3L, 2L)
ans = np.array([np.dot(dist[i],ind[i]) for i in xrange(dist.shape[0])]) # shape=(3L, 4L)
print ans
""" prints:
[[ 0.4 0.4 0.4 0.4]
[ 3. 3. 3. 3. ]
[ 1. 1. 1. 1. ]]
"""
我想尽快执行此操作,因此使用numpy函数计算
ans
应该是最好的方法,因为此操作很繁琐且矩阵很大。我看到了this post,但是形状不同,因此我无法理解应该为该问题使用哪种
axes
。但是,我确定tensordot应该有答案。有什么建议么?编辑:我接受了@ajcr's answer,但也请阅读我自己的答案,它可能会对其他人有所帮助...
最佳答案
您可以使用np.einsum
进行操作,因为它可以非常小心地控制要乘和求和的轴:
>>> np.einsum('ijk,ij->ik', ind, dist)
array([[ 0.4, 0.4, 0.4, 0.4],
[ 3. , 3. , 3. , 3. ],
[ 1. , 1. , 1. , 1. ]])
该函数将
ind
的第一个轴上的条目与dist
的第一个轴上的条目(下标'i'
)相乘。每个数组第二个轴的同上(下标'j'
)。代替返回3D数组,我们告诉einsum通过从输出下标中省略沿'j'
轴的值来求和,从而返回2D数组。np.tensordot
更难以应用于此问题。它会自动对轴的乘积求和。但是,我们需要两组产品,但只能将其中一组相加。编写
np.tensordot(ind, dist, axes=[1, 1])
(如您所链接的答案)会为您计算正确的值,但会返回形状为(3, 4, 3)
的3D数组。如果您负担得起较大阵列的内存成本,则可以使用:np.tensordot(ind, dist, axes=[1, 1])[0].T
这样可以为您提供正确的结果,但是由于
tensordot
首先会创建一个比所需数组大得多的数组,因此einsum
似乎是一个更好的选择。