【问题标题】:In Python's Numpy, a dot product isn't equivalent to an einsum, and I'm not sure why not在 Python 的 Numpy 中,点积不等于 einsum,我不知道为什么不
【发布时间】:2019-08-09 07:12:29
【问题描述】:

但显然我做错了什么。

我一直在追逐一个错误,我终于解决了它。考虑:

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.

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

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

现在,a == b

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

【问题讨论】:

  • 附带说明,np.einsum('df, hg -> dg', xs, W) 适用于任意形状,而 np.einsum('df, fg -> dg', xs, W) 不适用。这应该意味着两者并不相同,因为每个张量积都可以以独特的方式解释为 einsum 求和。

标签: python numpy numpy-einsum


【解决方案1】:

下面是等效的基于广播的表达式,也许它们可以帮助您理解其中的区别:

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 的情况相比,在 xs 的每一行和 W 的每一列之间形成一个点积。

【讨论】:

    【解决方案2】:

    使用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(不是我的)。

    【讨论】:

      猜你喜欢
      • 2023-03-05
      • 1970-01-01
      • 1970-01-01
      • 2016-07-20
      • 1970-01-01
      • 2019-10-16
      • 1970-01-01
      • 2016-09-11
      • 1970-01-01
      相关资源
      最近更新 更多