我想使用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做到这一点?
答案 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, 5
(ik
)c
具有形状3, 4
(ij
)看起来有点神奇,对吗?让我们稍微打破一下。
->
时,我们“丢失”的字母是将要求和的轴。这也是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
示例作为另一个答案,请随意!)