为什么我的惩罚函数没有变化
以下是我的代码,为什么我的punish以及init_weight等函数在循环中没有变化?import torchimport torch.nn as nn
import torch.nn.functional as f
from torch.autograd import Variable
import numpy as np
import os
import copy
import random
import pandas
import matplotlib.pyplot as plt
from torch.autograd import Function
def ConvertTensor(vec,grad_flag=True):
return torch.tensor(vec,dtype=torch.float32,requires_grad=grad_flag)
def Punishment(geom,generator,flag=1):
if flag==1:
thresh1 = generator.thresh1 #smaller
thresh2 = generator.thresh2 #larger
w1 = generator.w1
w2 = generator.w2
ThreeN = len(geom)
NAtom= int(ThreeN/3)
geom = geom.view(NAtom,3)
bond_length=[]
for i in range(NAtom):
for j in range(i+1,NAtom):
diff = geom-geom
diff = torch.linalg.norm(diff)
bond_length.append(diff)
bond_length = ConvertTensor(bond_length)
dist_max = torch.max(bond_length)
dist_min = torch.min(bond_length)
#if all bond lengths are good
res1 = 0
res2 = 0
#if any bond is too short or too long
if dist_min < thresh1:
res1 = -(dist_min - thresh1)
if dist_max > thresh2:
res2 =dist_max - thresh2
return w1*res1 + w2*res2
class Generator(nn.Module):
""" Architecture of the Generator, uses res-blocks """
def __init__(self):
super().__init__()
self.counter = 0
self.progress = []
self.NAtom = 12
self.model= self.G_model()
self.optimizer = torch.optim.Adam(self.parameters(),lr=0.001)
self.thresh1 = 1.6
self.thresh2 = 12.6
#---------------------------------------------
#the below are used for punishment function
#for flag 1
self.RandomInput= self.Gen_Random_input()
#--------------------------------------------
#self.model.apply(weight_init)
print("Generator model")
print(self.model)
###################################################
def G_model(self):
NAtom = self.NAtom
activation_func = nn.Sigmoid()
inp_dim = NAtom*3
Normalizer = nn.LayerNorm
model_flag =1
#-----------------------------------------------
if model_flag ==1: #simple
model = nn.Sequential(
nn.Linear(inp_dim, inp_dim),
activation_func
)
if model_flag ==101: #simple
model = nn.Sequential(
nn.Linear(inp_dim, inp_dim),
activation_func,
Normalizer(inp_dim)
)
return model
#-----------------------------------------------
#######################################################
def forward(self,input_tensor,weight,bias=0):
out=self.model(input_tensor)
out=torch.matmul(out,weight)+bias
out=out+bias
return out
def Gen_Random_input(self):
NAtom = self.NAtom
mean= 0
std = 2
inp = torch.randn(NAtom*3)
input_tensor = inp*std + mean
input_tensor.requires_grad_(True)
return input_tensor
def train(self,target_flag,maxit=1000):
thresh1 = self.thresh1
thresh2 = self.thresh2
input_tensor = self.Gen_Random_input()
init_bias = torch.zeros_like(input_tensor)
init_weight = torch.ones(self.NAtom*3,self.NAtom*3)
self.w1=1
self.w2=1
for i in range(maxit):
#generate fake data
gen_tensor = self.forward(input_tensor,init_weight,init_bias)
self.gen_tensor = gen_tensor
#calculate the punishment of the fake data
punish= Punishment(gen_tensor.detach(),self,flag=1)
print(punish)
#punish= torch.max(punish,torch.zeros_like(punish))
loss = punish
#get the network parameters
params = self.state_dict()
keys = list(params.keys())
last_b = copy.deepcopy(params])
last_w = copy.deepcopy(params])
#do some check
assert len(last_b) == self.NAtom*3, print("error length of last_b not equal to threeN, len(keys)=",len(last_b))
assert len(last_w) == self.NAtom*3, print("error length of last_w not equal to threeN, len(keys)=",len(last_b))
#update the init_bias and init_weight
init_bias = ConvertTensor(last_b,True)
init_weight = ConvertTensor(last_w,True)
#run the backward training
self.optimizer.zero_grad()
loss.backward()
self.optimizer.step()
if punish > 10:
init_weight = torch.zeros_like(init_weight)
#plot stuff
self.counter += 1
if self.counter%10==0:
self.progress.append(loss.item())
# print(gen_tensor)
return loss,gen_tensor
def plot_progress(self):
df = pandas.DataFrame(self.progress,columns=['loss'])
# df.plot(ylim=,marker='.',grid=True,title="generator_loss" )
df.plot(marker='.',grid=True,title="generator_loss" )
# plt.savefig("generator_loss.png")
plt.show()
#-----
if __name__=="__main__":
generator = Generator()
NAtom=12
init_weight = torch.ones()
geom = generator.forward(generator.RandomInput,weight=init_weight)
maxit=500
print("max iteration=",maxit)
loss,gen_tensor = generator.train(target_flag=1,maxit=maxit)
generator.plot_progress()
问题出在以下几个地方:
1. 在你的`Punishment`函数中,你没有传入`generator`对象。所以在使用`generator.thresh1`和`generator.w1`等属性时会报错。你需要修改为`Punishment(geom,generator,flag=1)`。
2. 在你的`forward`函数中,你传入了`weight`参数,但是在调用`self.model`时并没有使用它。你可以尝试修改为`out = self.model(input_tensor) + torch.matmul(weight, input_tensor)`。
3. 在你的`Gen_Random_input`函数中,你没有将输入的`grad_flag`传递给`torch.randn()`方法。你需要修改为`inp = torch.randn(NAtom*3, dtype=torch.float32, requires_grad=True)`。
4. 在你的`train`函数中,在循环开始之前,你需要先调用`self.optimizer.zero_grad()`来清空之前计算的梯度。
以上是我发现的问题和建议修复的地方,你可以尝试将代码改进后再运行一下看看是否有更好的结果。希望能对你有所帮助!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 FishC 发表于 2024-4-2 16:48
问题出在以下几个地方:
1. 在你的`Punishment`函数中,你没有传入`generator`对象。所以在使用`generator ...
下面是我现在修改后的代码,但是punish在循环过程中还是没有变化。问题在哪里?
import torch
import torch.nn as nn
import torch.nn.functional as f
from torch.autograd import Variable
import numpy as np
import os
import copy
import random
import pandas
import matplotlib.pyplot as plt
from torch.autograd import Function
def ConvertTensor(vec,grad_flag=True):
return torch.tensor(vec,dtype=torch.float32,requires_grad=grad_flag)
class Generator(nn.Module):
""" Architecture of the Generator, uses res-blocks """
def __init__(self):
super().__init__()
self.counter = 0
self.progress = []
self.NAtom = 12
self.model= self.G_model()
self.optimizer = torch.optim.Adam(self.parameters(),lr=0.001)
self.loss_func = nn.MSELoss()
self.thresh1 = 1.6
self.thresh2 = 12.6
#---------------------------------------------
#the below are used for punishment function
#for flag 1
self.RandomInput= self.Gen_Random_input()
#--------------------------------------------
#self.model.apply(weight_init)
print("Generator model")
print(self.model)
###################################################
def G_model(self):
NAtom = self.NAtom
activation_func = nn.ReLU()
inp_dim = NAtom*3
Normalizer = nn.LayerNorm
model_flag =1
#-----------------------------------------------
if model_flag ==1: #simple
model = nn.Sequential(
nn.Linear(inp_dim, inp_dim),
activation_func,
nn.Linear(inp_dim, inp_dim),
activation_func
)
if model_flag ==101: #simple
model = nn.Sequential(
nn.Linear(inp_dim, inp_dim),
activation_func,
Normalizer(inp_dim)
)
return model
#-----------------------------------------------
#######################################################
def forward(self,input_tensor,weight,bias=0):
out=self.model(input_tensor)
out=torch.matmul(out,weight)+bias
out=out+bias
return out
def Punishment(self,geom):
thresh1 = self.thresh1 #smaller
thresh2 = self.thresh2 #larger
w1 = self.w1
w2 = self.w2
ThreeN = len(geom)
NAtom= int(ThreeN/3)
geom = geom.view(NAtom,3)
bond_length=[]
for i in range(NAtom):
for j in range(i+1,NAtom):
diff = geom-geom
diff = torch.linalg.norm(diff)
bond_length.append(diff)
bond_length = ConvertTensor(bond_length)
dist_max = torch.max(bond_length)
dist_min = torch.min(bond_length)
#if all bond lengths are good
res1 = 0
res2 = 0
#if any bond is too short or too long
if dist_min < thresh1:
res1 = -(dist_min - thresh1)
if dist_max > thresh2:
res2 =dist_max - thresh2
return w1*res1 + w2*res2
def Gen_Random_input(self):
NAtom = self.NAtom
mean= 0
std = 2
inp = torch.randn(NAtom*3)
input_tensor = inp*std + mean
input_tensor.requires_grad_(True)
return input_tensor
def train(self,target_flag,maxit=1000):
thresh1 = self.thresh1
thresh2 = self.thresh2
input_tensor = self.Gen_Random_input()
init_bias = torch.zeros_like(input_tensor)
init_weight = torch.ones(self.NAtom*3,self.NAtom*3)
self.w1=1
self.w2=1
gen_tensor = input_tensor
for i in range(maxit):
self.optimizer.zero_grad()
#generate fake data
gen_tensor = self.forward(gen_tensor,init_weight,init_bias)
self.gen_tensor = gen_tensor
#calculate the punishment of the fake data
punish= self.Punishment(gen_tensor.detach())
# print(gen_tensor)
print(punish)
#punish= torch.max(punish,torch.zeros_like(punish))
loss = self.loss_func(punish,torch.zeros_like(punish))
#get the network parameters
params = self.state_dict()
keys = list(params.keys())
last_b = copy.deepcopy(params])
last_w = copy.deepcopy(params])
#do some check
assert len(last_b) == self.NAtom*3, print("error length of last_b not equal to threeN, len(keys)=",len(last_b))
assert len(last_w) == self.NAtom*3, print("error length of last_w not equal to threeN, len(keys)=",len(last_b))
#update the init_bias and init_weight
init_bias = ConvertTensor(last_b,True)
init_weight = ConvertTensor(last_w,True)
#run the backward training
loss.backward()
self.optimizer.step()
#plot stuff
self.counter += 1
if self.counter%10==0:
self.progress.append(loss.item())
# print(gen_tensor)
return loss,gen_tensor
def plot_progress(self):
df = pandas.DataFrame(self.progress,columns=['loss'])
# df.plot(ylim=,marker='.',grid=True,title="generator_loss" )
df.plot(marker='.',grid=True,title="generator_loss" )
# plt.savefig("generator_loss.png")
plt.show()
#-----
if __name__=="__main__":
generator = Generator()
NAtom=12
init_weight = torch.ones()
geom = generator.forward(generator.RandomInput,weight=init_weight)
maxit=500
print("max iteration=",maxit)
loss,gen_tensor = generator.train(target_flag=1,maxit=maxit)
generator.plot_progress()
lqhenwunai 发表于 2024-04-03 09:57
下面是我现在修改后的代码,但是punish在循环过程中还 ...
问题在于在`train`函数中的循环中,你使用了`gen_tensor = input_tensor`,这导致在每次迭代中都使用相同的输入作为生成器的输入。因此,生成器的输出`gen_tensor`没有改变,所以惩罚函数`Punishment`的结果也不会改变。
你可以尝试将其修改为`gen_tensor = self.forward(gen_tensor, init_weight, init_bias)`,以便用上一次迭代的生成器输出作为下一次迭代的输入。这样,生成器的输出将随着迭代次数的增加而逐渐改变,从而使惩罚函数的结果也能够变化。
另外,你还需要将`punish`的计算方式修改为`loss = self.loss_func(punish, torch.zeros_like(punish))`,并且在每次迭代前调用`self.optimizer.zero_grad()`来清空之前的梯度计算。
修改后的代码如下:
def train(self, target_flag, maxit=1000):
thresh1 = self.thresh1
thresh2 = self.thresh2
input_tensor = self.Gen_Random_input()
init_bias = torch.zeros_like(input_tensor)
init_weight = torch.ones(self.NAtom*3, self.NAtom*3)
self.w1 = 1
self.w2 = 1
gen_tensor = input_tensor
for i in range(maxit):
self.optimizer.zero_grad()
# 生成假数据
gen_tensor = self.forward(gen_tensor, init_weight, init_bias)
self.gen_tensor = gen_tensor
# 计算惩罚值
punish = self.Punishment(gen_tensor.detach())
print(punish)
loss = self.loss_func(punish, torch.zeros_like(punish))
params = self.state_dict()
keys = list(params.keys())
last_b = copy.deepcopy(params)
last_w = copy.deepcopy(params)
assert len(last_b) == self.NAtom*3, print("error length of last_b not equal to threeN, len(keys)=", len(last_b))
assert len(last_w) == self.NAtom*3, print("error length of last_w not equal to threeN, len(keys)=", len(last_b))
init_bias = ConvertTensor(last_b, True)
init_weight = ConvertTensor(last_w, True)
loss.backward()
self.optimizer.step()
self.counter += 1
if self.counter % 10 == 0:
self.progress.append(loss.item())
return loss, gen_tensor
希望这次的修改能够解决你的问题!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 FishC 发表于 2024-4-3 09:57
问题在于在`train`函数中的循环中,你使用了`gen_tensor = input_tensor`,这导致在每次迭代中都使用相 ...
我就是这样修改的,但是punish还是没有变化 lqhenwunai 发表于 2024-04-03 10:03
我就是这样修改的,但是punish还是没有变化
抱歉,我在之前的回答中犯了错误。问题出在`Punishment`函数中。你在计算`bond_length`时,应该是对每一对原子计算差异,而不是对整个几何体进行计算。另外,在计算`diff`时,你需要使用索引来获取每对原子的坐标差异。以下是修改后的代码:
def Punishment(self, geom):
thresh1 = self.thresh1 #smaller
thresh2 = self.thresh2 #larger
w1 = self.w1
w2 = self.w2
ThreeN = len(geom)
NAtom= int(ThreeN/3)
geom = geom.view(NAtom,3)
bond_length = []
for i in range(NAtom):
for j in range(i+1,NAtom):
diff = geom - geom
diff = torch.linalg.norm(diff)
bond_length.append(diff)
bond_length = ConvertTensor(bond_length)
dist_max = torch.max(bond_length)
dist_min = torch.min(bond_length)
res1 = 0
res2 = 0
if dist_min < thresh1:
res1 = -(dist_min - thresh1)
if dist_max > thresh2:
res2 = dist_max - thresh2
return w1*res1 + w2*res2
请尝试运行修改后的代码,看看是否能够得到正确的惩罚结果。抱歉给你带来了困扰!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 FishC 发表于 2024-4-3 10:03
抱歉,我在之前的回答中犯了错误。问题出在`Punishment`函数中。你在计算`bond_length`时,应该是对每 ...
这个punishment跟我的代码没有区别 lqhenwunai 发表于 2024-04-03 10:06
这个punishment跟我的代码没有区别
非常抱歉,我之前的回答仍然存在错误。在`Punishment`函数中,你需要计算每对原子之间的距离,并将其与阈值进行比较,以计算惩罚。以下是修改后的代码示例:
def Punishment(geom, generator):
thresh1 = generator.thresh1
thresh2 = generator.thresh2
w1 = generator.w1
w2 = generator.w2
ThreeN = len(geom)
NAtom = int(ThreeN/3)
geom = geom.view(NAtom, 3)
res1 = 0
res2 = 0
for i in range(NAtom):
for j in range(i+1, NAtom):
diff = geom - geom
bond_length = torch.linalg.norm(diff)
if bond_length < thresh1:
res1 += -(bond_length - thresh1)
if bond_length > thresh2:
res2 += bond_length - thresh2
return w1 * res1 + w2 * res2
请尝试使用修改后的`Punishment`函数,看看是否能够得到正确的惩罚结果。非常抱歉之前给你带来的困惑!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 FishC 发表于 2024-4-3 10:06
非常抱歉,我之前的回答仍然存在错误。在`Punishment`函数中,你需要计算每对原子之间的距离,并将其与 ...
不能得到正确的结果 lqhenwunai 发表于 2024-04-03 10:07
不能得到正确的结果
非常抱歉,我之前回答中的代码仍然有问题。在Punishment函数中,你使用了一个列表来存储每对原子之间的距离,但是你没有正确计算每对原子之间的距离,而是直接将整个geom张量减去自身,这是错误的。以下是修复后的代码示例:
def Punishment(geom, generator):
thresh1 = generator.thresh1
thresh2 = generator.thresh2
w1 = generator.w1
w2 = generator.w2
ThreeN = len(geom)
NAtom = int(ThreeN/3)
geom = geom.view(NAtom, 3)
bond_length = []
for i in range(NAtom):
for j in range(i+1, NAtom):
diff = geom - geom
diff = torch.linalg.norm(diff)
bond_length.append(diff)
bond_length = torch.tensor(bond_length)
dist_max = torch.max(bond_length)
dist_min = torch.min(bond_length)
res1 = 0
res2 = 0
if dist_min < thresh1:
res1 = -(dist_min - thresh1)
if dist_max > thresh2:
res2 = dist_max - thresh2
return w1 * res1 + w2 * res2
请尝试使用修复后的`Punishment`函数,看看是否能够得到正确的惩罚结果。非常抱歉之前给你带来的困惑!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页:
[1]