一次调用np.einsum http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.einsum.html扩展后会一次性执行所有这些操作V
to a 5D
形状与np.newaxis/None http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#numpy.newaxis,就像这样-
EV = np.einsum('ijklm,mj->imkl',V[...,None],M)
因此,我们避免使用任何中间数组来实现内存高效的解决方案。
解释
(1) 涉及扩展维度的起始代码:
V_exp = np.tile(V[:, :, :, :, None], (1, 1, 1, 1, N1))
M_exp = np.tile(M.T[None, :, None, None, :], (N0, 1, N2, N3, 1))
output1 = V_exp * M_exp
In np.einsum
的方式,它会被翻译为:
np.einsum('ijklm,mj->ijklm',V[...,None],M)
请注意,我们已经使用了mj
而不是通常的jm
for M
对应于M.T[None, :, None, None, :]
.
(2) 接下来,我们有:
EV = np.sum(V_exp * M_exp, axis = 1)
因此,我们总结一下axis = 1
,所以 einsum 调用需要输出字符串说明符被改变自->ijklm
to ->iklm
.
(3)最后:
EV = np.rollaxis(EV, 3, 1)
对于本次移植rollaxis
,我们只需要push up axis=3
to axis=1
的位置和下推每一个axes=1,2
向右一个位置。就这样输出字符串说明符会改变自->iklm
to ->imkl
给我们:
np.einsum('ijklm,mj->imkl',V[...,None],M)