基本上,我有2个张量:A,其中A.shape = (N, H, D)
,B,其中B.shape = (K, H, D)
。我想做的是得到一个形状为(N, K, D, H)
的张量C,使得:
C[i, j, :, :] = A[i, :, :] * B[j, :, :].
这可以在Theano中有效地完成吗?
附注:我想要达到的实际最终结果是具有形状(N, K, D)
的张量E,使得:
E[i, j, :] = (A[i, :, :]*B[j, :, :]).sum(0)
所以,如果有办法直接得到这个,我更喜欢它(希望节省空间)。
答案 0 :(得分:2)
可以建议使用broadcasting
-
(A[:,None]*B).sum(2)
请注意,在(N, K, H, D)
上的总和减少为axis=2
之前,正在创建的中间数组的形状为(N,K,D).
答案 1 :(得分:0)
您可以使用batched_dot
获取最终的三维结果E
,而无需创建大型中间数组:
import theano.tensor as tt
A = tt.tensor3('A') # A.shape = (D, N, H)
B = tt.tensor3('B') # B.shape = (D, H, K)
E = tt.batched_dot(A, B) # E.shape = (D, N, K)
不幸的是,这需要您置换输入和输出数组的尺寸。虽然可以在Theano中使用dimshuffle
来完成,但似乎batched_dot
无法处理任意跨步数组,因此在评估ValueError: Some matrix has no unit stride
时,以下内容会引发E
:
import theano.tensor as tt
A = tt.tensor3('A') # A.shape = (N, H, D)
B = tt.tensor3('B') # B.shape = (K, H, D)
A_perm = A.dimshuffle((2, 0, 1)) # A_perm.shape = (D, N, H)
B_perm = B.dimshuffle((2, 1, 0)) # B_perm.shape = (D, H, K)
E_perm = tt.batched_dot(A_perm, B_perm) # E_perm.shape = (D, N, K)
E = E_perm.dimshuffle((1, 2, 0)) # E.shape = (N, K, D)
batched_dot
在第一个(尺寸D
)尺寸上使用scan
。当scan
顺序执行时,如果在GPU上运行,则计算效率低于并行计算所有产品的效率。
您可以明确地使用batched_dot
在广播方法中scan
方法的内存效率和并行度之间进行权衡。想法是并行计算大小为C
的批次的完整产品M
(假设M
是D
的精确因子),使用{{1}批量迭代}}:
scan