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

时间:2019-04-15 17:44:26

标签: python-3.x pytorch nested-loops

我正在尝试将我在numpy中编写的一些代码转换为PyTorch中的张量操作,该代码包含嵌套循环。但是,在尝试实现自己的版本后,我在输出中没有得到相同的值。我已经设法通过一个循环完成了同样的事情,所以我不确定自己在做什么错。

    #(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

数组/张量k_values,kp_values,wavef和wavefp的尺寸为(1000,1)。值self.hbar和self.mu以及step是标量。变量self.MTV是大小为(1000,1000)的矩阵。

我希望这两种方法都能提供相同的输出,但它们却不会。用于计算动能的代码(在Numpy和PyTorch中)都具有相同的值。但是,势能的计算方式有所不同,我不确定为什么。

非常感谢!

1 个答案:

答案 0 :(得分:1)

问题出在形状上。您在(1000,1)中有kp_valueswavef,在乘法之前需要将其转换为(1000,)。 (kp_values.pow(2)).mul(wavef).mul(MTV[i,:])的结果是一个矩阵,但您假定它是一个向量。

因此,以下方法应该起作用。

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

一个无循环的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())

输出

12660.407492918514
12660.407492918514