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})
我想使用 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})