【问题标题】:Double dot product with broadcasting in numpy在 numpy 中广播的双点积
【发布时间】:2017-08-16 16:24:15
【问题描述】:

我有以下操作:

import numpy as np

x = np.random.rand(3,5,5)
w = np.random.rand(5,5)

y=np.zeros((3,5,5))
for i in range(3):
    y[i] = np.dot(w.T,np.dot(x[i],w))

它对应于伪表达式y[m,i,j] = sum( w[k,i] * x[m,k,l] * w[l,j], axes=[k,l] 或等效于w.Txw 广播公司在x 的第一个维度上的点积。

如何使用 numpy 的广播规则来实现它?

提前致谢。

【问题讨论】:

    标签: python numpy matrix tensor


    【解决方案1】:

    这是np.tensordot 的一种矢量化方法,它应该比broadcasting + summation anyday -

    # Take care of "np.dot(x[i],w)" term
    x_w = np.tensordot(x,w,axes=((2),(0)))
    
    # Perform "np.dot(w.T,np.dot(x[i],w))" : "np.dot(w.T,x_w)"
    y_out = np.tensordot(x_w,w,axes=((1),(0))).swapaxes(1,2)
    

    或者,所有的混乱都由一个np.einsum 呼叫处理,但可能会更慢 -

    y_out = np.einsum('ab,cae,eg->cbg',w,x,w)
    

    运行时测试-

    In [114]: def tensordot_app(x, w):
         ...:     x_w = np.tensordot(x,w,axes=((2),(0)))
         ...:     return np.tensordot(x_w,w,axes=((1),(0))).swapaxes(1,2)
         ...: 
         ...: def einsum_app(x, w):
         ...:     return np.einsum('ab,cae,eg->cbg',w,x,w)
         ...: 
    
    In [115]: x = np.random.rand(30,50,50)
         ...: w = np.random.rand(50,50)
         ...: 
    
    In [116]: %timeit tensordot_app(x, w)
    1000 loops, best of 3: 477 µs per loop
    
    In [117]: %timeit einsum_app(x, w)
    1 loop, best of 3: 219 ms per loop
    

    给广播一个机会

    求和符号是 -

    y[m,i,j] = sum( w[k,i] * x[m,k,l] * w[l,j], axes=[k,l] )
    

    因此,这三个术语将被叠加用于广播,就像这样 -

    w : [ N x k x i x N x N]
    x : [ m x k x N x l x N]
    w : [ N x N X N x l x j]
    

    ,其中N 表示附加新轴以方便broadcasting 沿着这些暗淡。

    使用None/np.newaxis 添加新轴的术语将如下所示 -

    w : w[None, :,    :,    None, None]
    x : x[:,    :,    None, :,    None]
    w : w[None, None, None, :,       :]
    

    因此,广播的产品将是 -

    p = w[None,:,:,None,None]*x[:,:,None,:,None]*w[None,None,None,:,:]
    

    最后,输出将是 sum-reduction to loss (k,l),即轴 =(1,3) -

    y = p.sum((1,3))
    

    【讨论】:

    • 酷!我知道tensordot对于点积比广播要快,但是一个总和+广播不会比两个tensordots快吗?
    • 另外,您是否知道任何参考资料清楚地解释了如何将给定的张量运算(用索引表示)转换为 numpy 和广播运算?我对如何做有点了解,但我不知道一般的方法:)
    • @Tool Tensordot 避免了扩展并通过 BLAS 调用进行 sum-reduction,因此比广播 + sum-reductions 快得多。
    • @Tool 没有通用的方法。我们需要跟踪正在进行减和的轴,并将轴 arg 下的轴用于np.tensordot。如果您无法理解它,我至少可以指出另一个使用tensordot 解释的问答 - stackoverflow.com/questions/41870228
    • 感谢您提供此参考资料(我知道但我需要再读一遍)。我可能表达得很糟糕,我正在寻找一种通用的方法来从给定的数学张量运算连接到具有广播和减少的等效 numpy 实现,因为我认为每个给定的张量运算都可以通过这种方式实现。我可能会为此发布一个新问题,因为它可能更清楚。
    猜你喜欢
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多