我有以下内容:
sum_XY C_x I_xk Cy I_yl P_xy
目前我的代码如下:
# initialise dummy values
Nk = Nl = 100
NX = Ny = 10
Ix = np.random.rand(Nx, Nk)
Iy = np.random.rand(Ny, Nl)
C = np.random.rand(Nk)
Pin = np.ones(Nx*Ny)
# point 1
Fx = (Ix * C[np.newaxis, :Nk]).T # <- this part may be unavoidable due to using arbitrary precision for Ix, Iy
Fy = (Iy * C[np.newaxis, :Nl]).T # <- this part may be unavoidable due to using arbitrary precision for Ix, Iy
# point 2
H = Fx[:, np.newaxis, :, np.newaxis] * Fy[np.newaxis, :, np.newaxis, :]
H = H.reshape([Nk*Nl, Nx*Ny])
out = np.dot(H, Pin)
out.shape = [Nk, Nl]
# end
我想知道我是否可以用np.einsum
以某种方式执行上述操作,因为每当我尝试创建H时,我都会使用太多内存......
如果您需要其他信息,请与我们联系。
修改
由于数值准确性,可能只能从point 2
开始有效使用einsum。所以问题就变成了如何用einsum
从point 1
替换代码直到结束,从point 2
直到结束。
答案 0 :(得分:0)
从point2
开始,这与您的计算相符。
H2 = np.einsum('kx,ly->klxy', Fx, Fy)
out2 = np.einsum('klxy,xy->kl', H2, np.ones((Nx,Ny)))
print np.allclose(out, out2)
我尝试选择einsum索引来匹配你的形状参数。我用
测试了它Nk, Nl = 100, 90
Nx, Ny = 10, 9
只是为了确保我没有混淆维度。
由于第二个einsum只是总结了最后两个维度,因此简化为
out4 = np.einsum('kx,ly->kl', Fx, Fy)
包括point1
Fx = np.einsum('xk,k->kx', Ix, C[:Nk])
Fy = np.einsum('yl,l->ly', Iy, C[:Nl])
out5 = np.einsum('kx,ly->kl', Fx, Fy)
print np.allclose(out, out5)
或
out6 = np.einsum('xk,k,yl,l->kl', Ix, C[:Nk], Iy, C[:Nl])
print np.allclose(out, out6)
或模仿你的初始表达:
# sum_XY C_x I_xk C_y I_yl P_xy
out7 = np.einsum('k,xk,l,yl,xy->kl', Cx, Ix, Cy, Iy, Pin)
但是,将计算滚动到1或2 einsums
并不一定能节省您的时间或记忆。对于使用2个术语的计算,einsum
通常与dot
一样好,如果保存转置等,则会更好。但是,如果使用3个或4个术语,einsum
会减慢并使用更多内存,因为它必须在更大的空间内迭代(C代码级别)。