在Python的Numpy中,点积不等于einsum,而且我不确定为什么不

时间:2019-08-09 07:12:29

标签: python numpy numpy-einsum

但是显然我做错了。

我整夜都在追踪错误,终于解决了。考虑:

xs = np.arange(100 * 3).reshape(100, 3)
W = np.arange(3 * 17).reshape(3, 17)

a = np.einsum('df, hg -> dg', xs, W)
b = np.dot(xs, W)

在以上a != b中。

我发现的问题在于本质,我说df, hg -> dg,但是如果我将h换成f,它会按预期工作:

a = np.einsum('df, fg -> dg', xs, W)
b = np.dot(xs, W)

现在,a == b

两种情况下的求和运算有何不同,我希望它们是相同的?

2 个答案:

答案 0 :(得分:2)

以下是基于广播的等效表达方式,也许它们可以帮助您了解不同之处:

dffg = (xs[:,:,None]*W[None,:,:]).sum(1)
dfhg = (xs[:,:,None,None]*W[None,None,:,:]).sum((1,2))

(a==dfhg).all()
# True
(b==dffg).all()
# True

在dfhg情况下,数据轴实际上并不重叠;因此,可以对每个术语分别进行求和:

dfhg_ = (xs.sum(1)[:,None]*W.sum(0)[None,:])
(a==dfhg_).all()
# True

将其与dffg情况进行对比,在dffg情况下,在xs的每一行和W的每一列之间形成点积。

答案 1 :(得分:1)

使用np.einsum进行矩阵乘法的正确方法是重复“中间”索引(指示在“行时间”列上的求和),如下所示:

a = np.array([[1,2],[3,4]])
b = np.array([[1,-2],[-0.4,3]])
np.einsum('df,fg->dg', a, b)
array([[ 0.2,  4. ],
       [ 1.4,  6. ]])

a.dot(b) 
array([[ 0.2,  4. ],
       [ 1.4,  6. ]])

如果不这样做,则得到a每个值乘以b

np.einsum('df, hg -> dfhg', a, b)

array([[[[  1. ,  -2. ],
         [ -0.4,   3. ]],

        [[  2. ,  -4. ],
         [ -0.8,   6. ]]],


       [[[  3. ,  -6. ],
         [ -1.2,   9. ]],

        [[  4. ,  -8. ],
         [ -1.6,  12. ]]]])

相同
a[:,:, None, None] * b

在使用显式运算符->时,如果省略中间索引,则会对这些轴求和:

np.einsum('df, hg -> dg', a, b)

array([[ 1.8,  3. ],
       [ 4.2,  7. ]])

与以下相同:

np.einsum('df, hg -> dfhg', a, b).sum(axis=1).sum(axis=1)

Here is a good guide to einsum(不是我的)。