神经网络中的回归问题是否需要归一化

Mis*_*ead 1 python neural-network pytorch

我正在学习如何使用 PyTorch 构建神经网络。这个公式是我代码的目标:y =2 X^3 + 7 X^2 - 8*X + 120

这是一个回归问题。

我使用它是因为它很简单,并且可以计算输出,这样我就可以确保我的神经网络能够根据给定的输入预测输出。

但是,我在训练过程中遇到了一些问题。问题出现在这行代码中:

loss = loss_func(prediction, outputs)
Run Code Online (Sandbox Code Playgroud)

在这一行中计算的损失是 NAN(不是数字)

我使用 MSEloss 作为损失函数。100 个数据集用于训练 ANN 模型。输入 X_train 的范围从 -1000 到 1000。

我认为问题出在 X_train 和 MSEloss 的值上。X_train 应该缩放到 0 到 1 之间的一些值,以便 MSEloss 可以计算损失。

但是,在回归问题中,是否可以在不将输入缩放为 0 到 1 之间的值的情况下训练 ANN 模型?

这是我的代码,它不使用 MinMaxScaler 并使用 NAN 打印损失:

import torch
import torch.nn as nn
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import torch.nn.functional as F
from torch.autograd import Variable

#Load datasets
dataset = pd.read_csv('test_100.csv')

x_temp_train = dataset.iloc[:79, :-1].values
y_temp_train = dataset.iloc[:79, -1:].values
x_temp_test = dataset.iloc[80:, :-1].values
y_temp_test = dataset.iloc[80:, -1:].values

#Turn into tensor
X_train = torch.FloatTensor(x_temp_train)
Y_train = torch.FloatTensor(y_temp_train)
X_test = torch.FloatTensor(x_temp_test)
Y_test = torch.FloatTensor(y_temp_test)

#Define a Artifical Neural Network
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.linear = nn.Linear(1,1)  #input=1, output=1, bias=True
        
    def forward(self, x):
        x = self.linear(x)
        return x
net = Net()
print(net)

#Define a Loss function and optimizer
optimizer = torch.optim.SGD(net.parameters(), lr=0.2)
loss_func = torch.nn.MSELoss()

#Training
inputs = Variable(X_train)
outputs = Variable(Y_train)
for i in range(100):      #epoch=100
    prediction = net(inputs)
    loss = loss_func(prediction, outputs)
    optimizer.zero_grad() #zero the parameter gradients
    loss.backward()       #compute gradients(dloss/dx)
    optimizer.step()      #updates the parameters
    
    if i % 10 == 9:        #print every 10 mini-batches
        #plot and show learning process
        plt.cla()
        plt.scatter(X_train.data.numpy(), Y_train.data.numpy())
        plt.plot(X_train.data.numpy(), prediction.data.numpy(), 'r-', lw=2)
        plt.text(0.5, 0, 'Loss=%.4f' % loss.data.numpy(), fontdict={'size': 10, 'color': 'red'})
        plt.pause(0.1)
        
plt.show()
Run Code Online (Sandbox Code Playgroud)

谢谢你的时间。

Mul*_*ter 5

神经网络中的回归问题是否需要归一化?

不。

但...

我可以告诉你 MSELoss 使用非标准化值。你可以说是因为:

>>> import torch
>>> torch.nn.MSELoss()(torch.randn(1)-1000, torch.randn(1)+1000)
tensor(4002393.)
Run Code Online (Sandbox Code Playgroud)

MSE 是一个表现非常好的损失函数,如果NaN不给它一个NaN. 我敢打赌你的模型正在给出NaN输出。

导致 a 的两个最常见原因NaN是:意外除以 0,以及异常大的权重/梯度。

我使用以下命令在我的机器上运行了您的代码的变体:

x = torch.randn(79, 1)*1000
y = 2*x**3 + 7*x**2 - 8*x + 120
Run Code Online (Sandbox Code Playgroud)

NaN由于非常大的权重,它需要大约 20 个训练步骤。

如果学习率太大,模型可能会获得大得离谱的权重。您可能认为0.2它不会太大,但这是人们用于规范化数据的典型学习率,这迫使他们的梯度相当小。由于您没有使用归一化数据,让我们计算一下您的梯度有多大(大致)。

首先,您的 x 的数量级为1e3,您的预期输出 y 缩放为x^3,然后 MSE 计算(pred - y)^2。那么你的损失是1e3^3^2=1e18。这会传播到您的梯度,并回想一下权重更新是+= gradient*learning_rate,因此很容易理解为什么您的权重在浮点精度之外很快就会爆炸。

如何解决这个问题?那么你可以使用2e-7. 或者你可以规范化你的数据。我建议规范化您的数据;它还有其他很好的训练属性,可以避免这些问题。