【问题标题】:The loss value does not decrease损失值不降低
【发布时间】:2021-07-17 11:16:23
【问题描述】:

我正在使用 Pytorch 实现一个简单的前馈神经网络,并且损失函数似乎没有减少。由于我已经完成了一些其他测试,问题似乎出在我为计算 pred 所做的计算中,因为如果我稍微改变网络以便它为每个条目吐出一个二维向量并将其保存为 pred,一切正常。

你看到这里定义 pred 的问题了吗?谢谢

import torch
import numpy as np
from torch import nn

dt = 0.1

class Neural_Network(nn.Module):
    def __init__(self, ):
        super(Neural_Network, self).__init__()
    
        self.l1 = nn.Linear(2,300)
        self.nl = nn.Tanh()
        self.l2 = nn.Linear(300,1)
    
    
    def forward(self, X):
        z = self.l1(X)
        z = self.nl(z)
        o = self.l2(z)
        return o



N = 1000
X = torch.rand(N,2,requires_grad=True)
y = torch.rand(N,1)
NN = Neural_Network()

criterion = torch.nn.MSELoss(reduction='sum')
optimizer = torch.optim.Adam(NN.parameters(), lr=1e-5)

epochs = 200

for i in range(epochs):  # trains the NN 1,000 times

    HH = torch.mean(NN(X))
    gradH =  torch.autograd.grad(HH, X)[0]
    XH= torch.cat((gradH[:,1].unsqueeze(0),-gradH[:,0].unsqueeze(0)),dim=0).t()
    pred = X + dt*XH

    #Optimize and improve the weights
    loss = criterion(pred, y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()


    print (" Loss: ", loss.detach().numpy())  # mean sum squared loss

附:有了这些 X 和 y,损失预计不会为零,为了简单起见,我将它们像它们一样添加在这里。我将把这个架构应用到期望满足这个模型的数据点上。不过,我只想看到损失减少。


我的目标是用神经网络近似一个向量场的哈密顿量,其中只有一些轨迹是已知的。例如,仅更新x(t)\rightarrow x(t+\Delta t) 用于某些点的选择。所以向量X 包含点x(t),而y 包含$x(t+\Delta t)$。我上面的网络以简单的方式近似哈密顿函数H(x),为了优化它,我需要找到与这个哈密顿函数相关的轨迹。

特别是XH 旨在成为与近似哈密顿量相关的哈密顿矢量场。时间更新pred = X + dt*XH简直是欧拉前进了一步。

但是,我在这里的主要问题可以抽象为:如何将网络相对于其输入的梯度包含在损失函数中?

【问题讨论】:

    标签: python neural-network pytorch loss-function


    【解决方案1】:

    可能是因为NN 的梯度流图在gradH 步骤中被破坏了。 (检查HH.grad_fngradH.grad_fn

    因此,您的 pred 张量(以及后续损失)不包含通过 NN 网络的必要梯度流。

    loss 包含输入 X 的梯度流,但不包含 NN.parameters() 的梯度流。因为优化器只采用step() 而不是那些NN.parameters(),所以网络NN 没有被更新,并且由于X 也没有被更新,所以损失不会改变。

    您可以通过在loss.backward() 之后检查loss.grad_fn 来检查损失是如何向后发送梯度的 这是一个简洁的函数(在 Stackoverflow 上找到)来检查它:

    def getBack(var_grad_fn):
        print(var_grad_fn)
        for n in var_grad_fn.next_functions:
            if n[0]:
                try:
                    tensor = getattr(n[0], 'variable')
                    print(n[0])
                    print('Tensor with grad found:', tensor)
                    print(' - gradient:', tensor.grad)
                    print()
                except AttributeError as e:
                    getBack(n[0])
    

    loss.backward() 之后使用getBack(loss.grad_fn) 自己检查(尽管之前可能会减少批次 N 的大小)

    编辑:它通过更改 gradH = torch.autograd.grad(HH, X, create_graph=True)[0] 来工作

    【讨论】:

    • 好的,谢谢。似乎有关 NN.parameters 的信息在该步骤中丢失了。你对如何解决这个问题有什么建议吗?我是 Pytorch 的新手
    • 我不太确定你想用 gradH 做什么,所以如果你有任何材料(tf 代码或方程式)也许我可以提供帮助。
    • 根据pytorch grad documentation,我猜使用gradH = torch.autograd.grad(HH, X, create_graph=True)[0] 可以解决问题(取决于你想要什么)
    • 我已经在问题中添加了一个更新,我解释了我想要做什么,我希望这可以帮助你
    • 现在可以使用 @DannyBoi ,非常感谢您添加 create_graph=True
    猜你喜欢
    • 2022-01-02
    • 2023-01-19
    • 2020-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-13
    • 1970-01-01
    • 2012-11-07
    相关资源
    最近更新 更多