代码之家  ›  专栏  ›  技术社区  ›  orange

保持尺寸不受numpy张量的影响

  •  0
  • orange  · 技术社区  · 8 年前

    np.tensordot 在过去没有任何问题,但我现在的例子,我努力理解结果。

    对于 np.tensordot(d * y, r, axes=((1, 2, 3), (2, 3, 4))).shape (6, 5) ,但相反,我得到了 (6, 6, 5) .我什么时候跑步 tensordot 然而,在axis0上6次,我会得到预期的结果,但我宁愿 在一次通话中帮我做到这一点。这个怎么了?

    >>> import numpy as np
    >>> d = np.random.rand(6, 7, 1, 2)
    >>> y = np.random.rand(6, 7, 1, 2)
    >>> r = np.random.rand(6, 5, 7, 1, 2) > 0.5
    >>> 
    >>> np.tensordot(d * y, r, axes=((1, 2, 3), (2, 3, 4))).shape
    (6, 6, 5)
    >>> np.tensordot((d * y)[0], r[0], axes=((0, 1, 2), (1, 2, 3))).shape
    (5,)
    >>> np.tensordot((d * y)[1], r[1], axes=((0, 1, 2), (1, 2, 3))).shape
    (5,)
    >>> np.tensordot((d * y)[2], r[2], axes=((0, 1, 2), (1, 2, 3))).shape
    (5,)
    ...
    >>> np.tensordot((d * y)[5], r[5], axes=((0, 1, 2), (1, 2, 3))).shape
    (5,)
    
    2 回复  |  直到 8 年前
        1
  •  1
  •   hpaulj    8 年前

    考虑一个更简单的情况:

    In [709]: d=np.ones((6,2));
    In [710]: np.tensordot(d,d,axes=(1,1)).shape
    Out[710]: (6, 6)
    

    这相当于:

    In [712]: np.einsum('ij,kj->ik',d,d).shape
    Out[712]: (6, 6)
    

    这不是 ij,ij->i

    你有 (6, 7, 1, 2) (6, 5, 7, 1, 2)

    np.einsum('i...,ij...->ij',d,r)

    在封面下, tensordot 重塑和交换轴,使问题成为二维问题 np.dot


    In [726]: np.einsum('aijk,abijk->ab',d,r).shape
    Out[726]: (6, 5)
    

    和方法:

    In [729]: (d[:,None,...]*r).sum(axis=(2,3,4)).shape
    Out[729]: (6, 5)
    

    In [734]: timeit [np.tensordot(d[i],r[i], axes=((0, 1, 2), (1, 2, 3))) for i in 
         ...: range(6)]
    145 µs ± 514 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    In [735]: timeit np.einsum('aijk,abijk->ab',d,r)
    7.22 µs ± 34.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    In [736]: timeit (d[:,None,...]*r).sum(axis=(2,3,4))
    16.6 µs ± 84.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    

    另一种解决方案是使用 @

    In [747]: timeit np.squeeze(d.reshape(6,1,14)@r.reshape(6,5,14).transpose(0,2,1))
    11.4 µs ± 28.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    
        2
  •  1
  •   Rufflewind    8 年前

    在里面 tensordot ,每个轴为:

    • 不受影响(且不受约束),在总和中仅出现一次。

    所以当你写作的时候 tensordot(d * y, r, axes=((1, 2, 3), (2, 3, 4)))

    T[i j k] = ∑[l m n] dy[i l m n] r[j k l m n]
    

    哪里 dy ≡ d * y .你怎么了 计算is

    T[i k] = ∑[l m n] dy[i l m n] r[i k l m n]
    

    i 出现两次,但未被汇总。这意味着 一、 受限 这一切都可以自己做。

    最简单的方法是使用 einsum 只需明确声明您想要什么:

    np.einsum("i l m n, i k l m n -> i k", d * y, r)
    

    可以看到您试图计算的整个表达式,它应该能够找到一种相对最优的方法来执行此计算。