theano - 使用 tensordot 计算两个张量的点积

theano - use tensordot compute dot product of two tensor

我想使用 tensordot 来计算两个张量的特定 dim 的点积。喜欢:

A​​为张量,形状为(3, 4, 5) B为张量,形状为(3, 5)

我想用 A 的第三个 dim 和 B 的第二个 dim 做一个点,得到一个 dims 为 (3, 4) 的输出

如下所示:

for i in range(3):
    C[i] = dot(A[i], B[i])

tensordot如何实现?

在这种情况下,einsum 可能比 tensordot 更容易理解。例如:

c = np.einsum('ijk,ik->ij', a, b)

我将过度简化解释,使事情更容易理解。我们有两个输入数组(用逗号分隔),这会产生我们的输出数组(在 -> 的右侧)。

  • a 具有 3, 4, 5 的形状,我们将其称为 ijk
  • b 的形状为 3, 5 (ik)
  • 我们希望输出 c 的形状为 3, 4 (ij)

好像有点神奇吧?让我们把它分解一下。

  • 我们 "lose" 穿过 -> 的字母是将被求和的轴。这也是 dot 正在做的事情。
  • 我们想要形状为 3, 4 的输出,所以我们要消除 k
  • 因此,输出c应该是ij
  • 这意味着我们将 b 称为 ik

作为一个完整的例子:

import numpy as np

a = np.random.random((3, 4, 5))
b = np.random.random((3, 5))

# Looping through things
c1 = []
for i in range(3):
    c1.append(a[i].dot(b[i]))
c1 = np.array(c1)

# Using einsum instead
c2 = np.einsum('ijk,ik->ij', a, b)

assert np.allclose(c1, c2)

您也可以使用 tensordot 执行此操作。一旦我有更多时间,我将添加一个例子。 (当然,如果其他人想在此期间添加一个 tensordot 示例作为另一个答案,请随意!)

好吧,你想在 numpy 中还是在 Theano 中? 在这种情况下,如您所述,您希望将 A 的轴 3 与 B 的轴 2 收缩,两者都很简单:

import numpy as np

a = np.arange(3 * 4 * 5).reshape(3, 4, 5).astype('float32')
b = np.arange(3 * 5).reshape(3, 5).astype('float32')

result = a.dot(b.T)

在 Theano 中这写成

import theano.tensor as T

A = T.ftensor3()
B = T.fmatrix()

out = A.dot(B.T)

out.eval({A: a, B: b})

然而,输出的形状是 (3, 4, 3)。由于您似乎想要形状 (3, 4) 的输出,因此 numpy 替代方案使用 einsum,就像这样

einsum_out = np.einsum('ijk, ik -> ij', a, b)

然而,einsum 在 Theano 中并不存在。所以这里的具体情况可以模拟如下

out = (a * b[:, np.newaxis]).sum(2)

也可以用Theano写

out = (A * B.dimshuffle(0, 'x', 1)).sum(2)
out.eval({A: a, B: b})