损失值不减少
The loss value does not decrease
我正在用 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
P.S。有了这些 X 和 y,预计损失不会变为零,为了简单起见,我在这里像添加它们一样添加了它们。我会将此架构应用于预期满足此模型的数据点。然而,我只是想看到损失减少。
我的目标是用神经网络近似向量场的哈密顿量,其中只有一些轨迹是已知的。例如,仅更新 x(t)\rightarrow x(t+\Delta t)
某些点的选择。因此向量 X
包含点 x(t)
,而 y
包含 $x(t+\Delta t)$。我上面的网络以一种简单的方式近似哈密顿函数 H(x)
,为了优化它,我需要找到与这个哈密顿函数相关的轨迹。
特别是 XH
旨在成为与近似哈密顿量相关联的哈密顿向量场。时间更新pred = X + dt*XH
只是向前欧拉一步
但是,我这里的主要问题可以抽象为:如何将网络的梯度与损失函数中的输入相关联?
可能是因为 NN
的梯度流图 被 gradH
步骤破坏了。 (检查 HH.grad_fn
与 gradH.grad_fn
)
因此您的 pred
张量(以及随后的损失)不包含通过 NN
网络的必要梯度流。
loss
包含输入 X
的梯度流,但不包含 NN.parameters()
。因为优化器只对那些 NN.parameters()
进行 step()
,所以网络 NN
没有被更新,并且由于 X
都没有被更新,损失没有改变。
您可以通过在 loss.backward()
之后检查 loss.grad_fn
来检查损失如何向后发送梯度
这里有一个简洁的函数(在 Whosebug 上找到)来检查它:
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]
来工作
我正在用 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
P.S。有了这些 X 和 y,预计损失不会变为零,为了简单起见,我在这里像添加它们一样添加了它们。我会将此架构应用于预期满足此模型的数据点。然而,我只是想看到损失减少。
我的目标是用神经网络近似向量场的哈密顿量,其中只有一些轨迹是已知的。例如,仅更新 x(t)\rightarrow x(t+\Delta t)
某些点的选择。因此向量 X
包含点 x(t)
,而 y
包含 $x(t+\Delta t)$。我上面的网络以一种简单的方式近似哈密顿函数 H(x)
,为了优化它,我需要找到与这个哈密顿函数相关的轨迹。
特别是 XH
旨在成为与近似哈密顿量相关联的哈密顿向量场。时间更新pred = X + dt*XH
只是向前欧拉一步
但是,我这里的主要问题可以抽象为:如何将网络的梯度与损失函数中的输入相关联?
可能是因为 NN
的梯度流图 被 gradH
步骤破坏了。 (检查 HH.grad_fn
与 gradH.grad_fn
)
因此您的 pred
张量(以及随后的损失)不包含通过 NN
网络的必要梯度流。
loss
包含输入 X
的梯度流,但不包含 NN.parameters()
。因为优化器只对那些 NN.parameters()
进行 step()
,所以网络 NN
没有被更新,并且由于 X
都没有被更新,损失没有改变。
您可以通过在 loss.backward()
之后检查 loss.grad_fn
来检查损失如何向后发送梯度
这里有一个简洁的函数(在 Whosebug 上找到)来检查它:
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]