鱼C论坛

 找回密码
 立即注册
查看: 536|回复: 5

神经网络训练惩罚函数问题

[复制链接]
发表于 2024-3-25 08:54:44 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
用pytorch随机生成一个张量,并用Calc_bond_length函数作为惩罚函数,然后进行神经网络训练。但是以下代码不能实现目的,所打印的input tensor在循环中没有变化。试了几种不同的网络结构,input tenso在循环中都没有变化。问题在哪里?
def Calc_bond_length(geom,thresh1,thresh2):
        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[i,:]-geom[j,:]
                        diff = torch.linalg.norm(diff)
                        bond_length.append(diff)

        dist_max = np.max(bond_length)
        dist_min = np.min(bond_length)

        if dist_max > thresh2 or dist_min < thresh1:
                return ConvertTensor(9,True) 
        else:
                return ConvertTensor(0,True)


        def train(self,thresh1,thresh2,maxit=1000):

                for i in range(maxit):
                        self.optimizer.zero_grad()
                        input_tensor = self.RandomInput         
                        print(input_tensor)

                        gen_tensor   = self.forward(input_tensor)
        
                        punish = 0
                        punish = Calc_bond_length(gen_tensor,thresh1,thresh2)        
                

                        loss    = punish
                
                        self.info.counter += 1
                        if self.info.counter%10==0:
                                self.info.progress.append(loss.item())
        
        
                        loss.backward()
                        self.optimizer.step()

                        if loss.item()<2:
                                print("break")
                                break


                return loss,gen_tensor
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-3-25 08:54:59 | 显示全部楼层
在你的代码中,循环中的`gen_tensor`是神经网络的输出,而`input_tensor`是随机生成的张量,并没有在循环中变化。这就是为什么打印出来的`input_tensor`没有变化的原因。

如果想要在每次循环中改变输入张量,可以将生成随机张量的代码放在循环内部。另外,别忘了在循环开始之前调用`self.optimizer.zero_grad()`来清除梯度。

下面是修改后的代码:
def train(self, thresh1, thresh2, maxit=1000):
    for i in range(maxit):
        self.optimizer.zero_grad()
        
        input_tensor = self.RandomInput()
        gen_tensor = self.forward(input_tensor)
        
        punish = Calc_bond_length(gen_tensor, thresh1, thresh2)
        
        loss = punish
        
        self.info.counter += 1
        if self.info.counter % 10 == 0:
            self.info.progress.append(loss.item())
    
        loss.backward()
        self.optimizer.step()
        
        if loss.item() ...

希望对你有所帮助!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-3-25 09:01:16 | 显示全部楼层
FishC 发表于 2024-3-25 08:54
在你的代码中,循环中的`gen_tensor`是神经网络的输出,而`input_tensor`是随机生成的张量,并没有在循环中 ...

哦,我说错了,是gen_tensor在循环中不发生改变。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-25 09:01:26 | 显示全部楼层
lqhenwunai 发表于 2024-03-25 09:01
哦,我说错了,是gen_tensor在循环中不发生改变。


如果`gen_tensor`在循环中没有变化,可能是因为你没有使用梯度下降优化算法来更新神经网络的参数。在训练步骤中,你需要计算损失函数并调用`backward()`方法计算梯度,然后调用优化器的`step()`方法来更新参数。请确保你的代码中包含了这些步骤。

在你的代码中,我看不到你定义的优化器。你需要在模型的初始化函数中创建一个优化器,例如使用随机梯度下降优化算法(SGD):
self.optimizer = torch.optim.SGD(self.parameters(), lr=0.01)

另外,请确保在每次循环中都调用`self.optimizer.zero_grad()`来清除梯度。

最后,检查一下训练循环中的损失函数计算是否正确,并确认`Calc_bond_length`函数返回的`punish`张量是可微分的(即可以进行反向传播)。

如果你的代码已经包含了这些步骤,但仍然没有更新`gen_tensor`,那可能是模型架构或数据流的问题。你可以检查模型的前向传播是否正确,以及数据输入是否正确传递给了模型。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-3-25 09:04:25 | 显示全部楼层
FishC 发表于 2024-3-25 09:01
如果`gen_tensor`在循环中没有变化,可能是因为你没有使用梯度下降优化算法来更新神经网络的参数。在训 ...

下面是我的网络类定义。不知道有没有什么问题。
另外怎么查看网络参数有没有更新?
class Generator(nn.Module):
        """ Architecture of the Generator, uses res-blocks """

        def __init__(self,para):
                super().__init__()
                
                self.info = para
                self.info.counter = 0
                self.info.progress = []

                self.model  = self.G_model()
                self.optimizer = para.optimizer(self.parameters(),lr=para.lr)
                self.flag_network = para.Gflag_network # =1, use network, =2 not use network        

                self.RandomInput  = self.Gen_Random_input()
                #self.model.apply(weight_init)
                print("Generator model")
                print(self.model)

        ##################################################3
        def G_model(self):
                info       = self.info

                model_flag = info.model_flag
                Nlayer     = info.Nlayer
                NAtom      = info.NAtom
                increment  = info.increment
                activation_func = info.activation_func
                inp_dim         = NAtom*3 
        #-----------------------------------------------
        #----------------------------------------------
                if model_flag==2:#increase then decrease
                        module_list=[]
                        for i in range(Nlayer):
                                module_list.append(nn.Linear(inp_dim,inp_dim+increment))
                                module_list.append(activation_func)
                                inp_dim+=increment
        
                        for i in range(Nlayer):
                                module_list.append(nn.Linear(inp_dim,inp_dim-increment))
                                module_list.append(activation_func)
                                inp_dim-=increment

                        module_list.append(nn.Linear(inp_dim,inp_dim))        
                        model = nn.Sequential(*module_list)
        #-----------------------------------------------------


                return model
        #-----------------------------------------------
        #######################################################


        def forward(self,input_tensor,flag=1):

                #use random input
                if flag==1:
                        out=self.model(input_tensor)
                
                if flag==2: #not use any network
                        out = input_tensor
                
                return out


        def Gen_Random_input(self):
                NAtom = self.info.NAtom
                mean  = self.info.configs[0].mean
                std   = self.info.configs[0].std
                inp   = torch.randn(NAtom*3)
                input_tensor = inp*std + mean
                input_tensor.requires_grad_(True)        
                return input_tensor
        
        def train(self,thresh1,thresh2,maxit=1000):

                for i in range(maxit):
                        self.optimizer.zero_grad()
                        input_tensor = self.RandomInput         
                        print(input_tensor)

                        gen_tensor   = self.forward(input_tensor, self.flag_network)
        
                        punish = 0
                        punish = Calc_bond_length(gen_tensor,thresh1,thresh2)        
                
        #                targets = torch.ones_like(gen_tensor)
        #                loss    = self.info.loss_func(gen_tensor,targets)+punish
                        loss    = punish
                
                        self.info.counter += 1
                        if self.info.counter%10==0:
                                self.info.progress.append(loss.item())
        
        
                        loss.backward()
                        self.optimizer.step()

                        if loss.item()<2:
                                print("break")
                                break


                return loss,gen_tensor
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-25 09:05:02 | 显示全部楼层
lqhenwunai 发表于 2024-03-25 09:04
下面是我的网络类定义。不知道有没有什么问题。
另外 ...


在你的代码中,定义了一个`Generator`类作为神经网络模型。看起来你的模型定义是正确的,但有几个问题需要注意:

1. 在`G_model`函数中,你创建了一个`module_list`变量,并将线性层和激活函数按顺序添加到其中。然而,在增加层之后,你忘记对应的循环结构中有两个缩进错误,导致这些层不会与主模块列表一起添加。你需要将这两个循环的缩进位置调整到与前面的循环相同。

2. 在`forward`函数中,你在使用随机输入时有一个小错误。条件`if flag==1`下的代码块应该位于此之后,而不是包含在其中。你需要将`out = self.model(input_tensor)`和`return out`移动到适当的位置。

3. 关于如何检查网络参数是否已更新,你可以使用`state_dict()`方法打印模型的参数字典。该方法返回一个Python字典对象,其中包含模型的所有参数及其对应的张量值。你可以在训练循环中适当的位置调用`print(self.state_dict())`来查看模型参数是否发生变化。

修正后的代码如下所示(已标注修复部分):
class Generator(nn.Module):
    """ Architecture of the Generator, uses res-blocks """

    def __init__(self, para):
        super().__init__()
        self.info = para
        self.info.counter = 0
        self.info.progress = []

        self.model = self.G_model()
        self.optimizer = para.optimizer(self.parameters(), lr=para.lr)
        self.flag_network = para.Gflag_network  # =1, use network, =2 not use network
        self.RandomInput = self.Gen_Random_input()

        print("Generator model")
        print(self.model)

    def G_model(self):
        info = self.info
        model_flag = info.model_flag
        Nlayer = info.Nlayer
        NAtom = info.NAtom
        increment = info.increment
        activation_func = info.activation_func
        inp_dim = NAtom * 3

        module_list = []  # Fixed: Initialize an empty list outside the loop

        if model_flag == 2:  # increase then decrease
            for i in range(Nlayer):
                module_list.append(nn.Linear(inp_dim, inp_dim + increment))
                module_list.append(activation_func)
                inp_dim += increment

            for i in range(Nlayer):  # Fixed: Correct indentation
                module_list.append(nn.Linear(inp_dim, inp_dim - increment))
                module_list.append(activation_func)
                inp_dim -= increment

        module_list.append(nn.Linear(inp_dim, inp_dim))

        model = nn.Sequential(*module_list)
        return model

    def forward(self, input_tensor, flag=1):
        if flag == 1:
            out = self.model(input_tensor)  # Moved from "if flag==1" condition
        elif flag == 2:
            out = input_tensor

        return out

    def Gen_Random_input(self):
        NAtom = self.info.NAtom
        mean = self.info.configs.mean
        std = self.info.configs.std
        inp = torch.randn(NAtom * 3)
        input_tensor = inp * std + mean
        input_tensor.requires_grad_(True)
        return input_tensor

    def train(self, thresh1, thresh2, maxit=1000):
        for i in range(maxit):
            self.optimizer.zero_grad()
            input_tensor = self.RandomInput
            print(input_tensor)
            gen_tensor = self.forward(input_tensor, self.flag_network)

            punish = Calc_bond_length(gen_tensor, thresh1, thresh2)
            loss = punish

            self.info.counter += 1
            if self.info.counter % 10 == 0:
                self.info.progress.append(loss.item())

            loss.backward()
            self.optimizer.step()

            # Check if the model parameters have been updated
            print(self.state_dict())

            if loss.item():
                ...

希望这些修改能够解决你的问题!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-15 10:22

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表