简体   繁体   English

如何将嵌套循环简化为割炬张量操作?

[英]How can I simplify a nested loop into torch tensor operations?

I'm trying to convert some code I have written in numpy which contains a nested-loop into tensor operations found in PyTorch. 我正在尝试将我在numpy中编写的一些代码转换为PyTorch中的张量操作,该代码包含嵌套循环。 However, after trying to implement my own version I'm not getting the same value on the output. 但是,在尝试实现自己的版本后,我在输出中没有得到相同的值。 I have managed to do the same with a single loop, so I'm not entirely sure what I'm doing wrong. 我已经设法通过一个循环完成了同样的事情,所以我不确定自己在做什么错。

    #(Numpy Version)
    #calculate Kinetic Energy
    summation = 0.0
    for i in range(0,len(k_values)-1):
        summation += (k_values[i]**2.0)*wavefp[i]*(((self.hbar*kp_values[i])**2.0)/(2.0*self.mu))*wavef[i]
    Ek = step*(4.0*np.pi)*summation

    #(Numpy Version)
    #calculate Potential Energy
    summation = 0.0
    for i in range(0,len(k_values)-1):
        for j in range(0,len(kp_values)-1):
            summation+= (k_values[i]**2.0)*wavefp[i]*(kp_values[j]**2.0)*wavef[j]*self.MTV[i,j]
    Ep = (step**2.0)*(4.0*np.pi)*(2.0/np.pi)*summation

            #####################################################

    #(PyTorch Version)
    #calcualte Kinetic Energy
    Ek = step*(4.0*np.pi)*torch.sum( k_values.pow(2)*wavefp.mul(wavef)*((kp_values.mul(self.hbar)).pow(2)/(2.0*self.mu)) )

    #(PyTorch Version)
    #calculate Potential Energy
    summation = 0.0
    for i in range(0,len(k_values)-1):
        summation += ((k_values[i].pow(2)).mul(wavefp[i]))*torch.sum( (kp_values.pow(2)).mul(wavef).mul(self.MTV[i,:]) )
    Ep = (step**2.0)*(4.0*np.pi)*(2.0/np.pi)*summation

The arrays/tensors k_values, kp_values, wavef, and wavefp have dimensions of (1000,1). 数组/张量k_values,kp_values,wavef和wavefp的尺寸为(1000,1)。 The values self.hbar, and self.mu, and step are scalars. 值self.hbar和self.mu以及step是标量。 The variable self.MTV is a matrix of size (1000,1000). 变量self.MTV是大小为(1000,1000)的矩阵。

I would expect that both methods would give the same output but they don't. 我希望这两种方法都能提供相同的输出,但它们却不会。 The code for calculating the Kinetic Energy (in both Numpy and PyTorch) give the same value. 用于计算动能的代码(在Numpy和PyTorch中)都具有相同的值。 However, the potential energy calculation differ, and I'm not entirely sure why. 但是,势能的计算方式有所不同,我不确定为什么。

Many Thanks in advance! 提前谢谢了!

The problem is in the shapes. 问题在于形状。 You have kp_values and wavef in (1000, 1) which needs to be converted to (1000, ) before the multiplications. 你有kp_valueswavef中(1000,1),其需要乘法之前被转换成(1000)。 The outcome of (kp_values.pow(2)).mul(wavef).mul(MTV[i,:]) is a matrix but you asummed it is a vector. (kp_values.pow(2)).mul(wavef).mul(MTV[i,:])是一个矩阵,但您假定它是一个向量。

So, the following should work. 因此,以下方法应该起作用。

summation += ((k_values[i].pow(2)).mul(wavefp[i]))*torch.sum((kp_values.squeeze(1)
    .pow(2)).mul(wavef.squeeze(1)).mul(MTV[i,:]))

And a loop-free Numpy and PyTorch solution would be: 一个无循环的Numpy和PyTorch解决方案将是:

step = 1.0
k_values = np.random.randint(0, 100, size=(1000, 1)).astype("float") / 100
kp_values = np.random.randint(0, 100, size=(1000, 1)).astype("float") / 100
wavef = np.random.randint(0, 100, size=(1000, 1)).astype("float") / 100
wavefp = np.random.randint(0, 100, size=(1000, 1)).astype("float") / 100
MTV = np.random.randint(0, 100, size=(1000, 1000)).astype("float") / 100

# Numpy solution
term1 = k_values**2.0 * wavefp # 1000 x 1 
temp = kp_values**2.0 * wavef # 1000 x 1
term2 = np.matmul(temp.transpose(1, 0), MTV).transpose(1, 0) # 1000 x 1000
summation = np.sum(term1 * term2)
print(summation)

# PyTorch solution
term1 = k_values.pow(2).mul(wavefp) # 1000 x 1
term2 = kp_values.pow(2).mul(wavef).transpose(0, 1).matmul(MTV) # 1000 x 1000
summation = torch.sum(term2.transpose(0, 1).mul(term1)) # 1000 x 1000
print(summation.item())

Output 产量

12660.407492918514
12660.407492918514

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM