我想使用tensordot计算两个张量特定维度的点积。例如:
A是一个形状为(3,4,5)的张量, B是一个形状为(3,5)的张量。
我想在A的第三个维度和B的第二个维度上进行点积运算,并获得一个输出,其维度为(3,4)。
如下所示:
for i in range(3):
C[i] = dot(A[i], B[i])
如何使用tensordot完成此操作?
我想使用tensordot计算两个张量特定维度的点积。例如:
A是一个形状为(3,4,5)的张量, B是一个形状为(3,5)的张量。
我想在A的第三个维度和B的第二个维度上进行点积运算,并获得一个输出,其维度为(3,4)。
如下所示:
for i in range(3):
C[i] = dot(A[i], B[i])
如何使用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)
然而,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})
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
的例子作为答案,欢迎!)