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

时间:2015-12-16 13:34:43

标签: numpy theano deep-learning

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

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

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

如下所示:

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

如何通过tensordot做到这一点?

2 个答案:

答案 0 :(得分:4)

嗯,你想要这个在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)

然而,Theano中不存在einsum。因此,此处的具体情况可以模拟如下

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

也可以用Theano写的

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

答案 1 :(得分:2)

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

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

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

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

看起来有点神奇,对吗?让我们稍微打破一下。

  • 当我们越过->时,我们“丢失”的字母是将要求和的轴。这也是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示例作为另一个答案,请随意!)