python / numpy - 如何在以下示例中使用einsum?

时间:2014-11-25 18:45:23

标签: python numpy

我有以下内容:

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。所以问题就变成了如何用einsumpoint 1替换代码直到结束,从point 2直到结束。

1 个答案:

答案 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代码级别)。