【问题标题】:Is normalization necessary for regression problem in Neural network神经网络中的回归问题是否需要归一化
【发布时间】:2020-11-29 15:51:24
【问题描述】:

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

这是一个回归问题。

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

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

loss = loss_func(prediction, outputs)

在这一行中计算的损失是 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()

感谢您的宝贵时间。

【问题讨论】:

    标签: python neural-network pytorch


    【解决方案1】:

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

    没有。

    但是……

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

    >>> import torch
    >>> torch.nn.MSELoss()(torch.randn(1)-1000, torch.randn(1)+1000)
    tensor(4002393.)
    

    MSE 是一个非常好的损失函数,如果不给它一个NaN,你就不能真正得到NaN。我敢打赌,您的模型给出了NaN 输出。

    NaN 最常见的两个原因是:意外除以 0,以及大得离谱的权重/梯度。

    我在我的机器上运行了你的代码变体:

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

    由于权重大得离谱,它在大约 20 个训练步骤中达到了NaN。

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

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

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

    【讨论】:

    • 感谢您的帮助!我已经使用 sklearn 的 MinMaxScaler() 对数据进行了标准化。预测结果不准确。可能是因为我没有开始为网络提供更多的神经元和隐藏层。
    • 单个神经元无法计算2x^3 + 7x^2 - 8x + 120;它找到的解决方案是生成数据的最佳单一值。您可以进行“手动特征提取”,而不仅仅是给网络x,而是给它torch.stack([x, x**2, x**3], dim=-1) 和nn.Linear(3, 1)。然后,由于没有激活函数,它应该能够很好地匹配输出。如果你在中间添加多个带有激活函数的层,我怀疑你不会得到那么好的结果。
    • 谢谢!这只是对我学习如何构建神经网络的测试。我认为在没有任何已知公式的情况下,在实际应用中使用神经网络时,学习如何确定神经元和隐藏层的数量很重要。
    猜你喜欢
    • 2013-04-21
    • 2013-11-19
    • 2019-01-27
    • 1970-01-01
    • 2018-09-10
    • 2021-09-13
    • 1970-01-01
    • 2014-02-19
    • 2019-07-13
    相关资源
    最近更新 更多