如何将嵌套循环简化为火炬张量操作?
How can I simplify a nested loop into torch tensor operations?
我正在尝试将我用 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
arrays/tensorsk_values、kp_values、wavef 和 wavefp 的维度为 (1000,1)。值 self.hbar、self.mu 和 step 是标量。变量 self.MTV 是一个大小为 (1000,1000) 的矩阵。
我希望这两种方法都能提供相同的输出,但事实并非如此。计算动能的代码(在 Numpy 和 PyTorch 中)给出相同的值。然而,势能计算不同,我不完全确定为什么。
非常感谢!
问题出在形状上。您在 (1000, 1) 中有 kp_values
和 wavef
,需要在乘法之前将其转换为 (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
我正在尝试将我用 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
arrays/tensorsk_values、kp_values、wavef 和 wavefp 的维度为 (1000,1)。值 self.hbar、self.mu 和 step 是标量。变量 self.MTV 是一个大小为 (1000,1000) 的矩阵。
我希望这两种方法都能提供相同的输出,但事实并非如此。计算动能的代码(在 Numpy 和 PyTorch 中)给出相同的值。然而,势能计算不同,我不完全确定为什么。
非常感谢!
问题出在形状上。您在 (1000, 1) 中有 kp_values
和 wavef
,需要在乘法之前将其转换为 (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