Pytorch和多项式线性回归问题

时间:2017-03-14 19:47:08

标签: python machine-learning linear-regression polynomials pytorch

我修改了我在Pytorch github上找到的代码帽以适合我的数据,但是我的损失结果很大,每次迭代它们都会变大,后来变成了nan.Code不会给我任何错误,也不会丢失结果,没有预测。 我有另一个代码处理简单的线性回归,所有工作正常。我想我在这里缺少一些简单的东西,但我无法看到它。任何帮助将不胜感激。

代码:

import sklearn.linear_model as lm
from sklearn.preprocessing import PolynomialFeatures
import torch
import torch.autograd
import torch.nn.functional as F
from torch.autograd import Variable


train_data = torch.Tensor([
   [40,  6,  4],
   [44, 10,  4],
   [46, 12,  5],
   [48, 14,  7],
   [52, 16,  9],
   [58, 18, 12],
   [60, 22, 14],
   [68, 24, 20],
   [74, 26, 21],
   [80, 32, 24]])
test_data = torch.Tensor([
    [6, 4],
    [10, 5],
    [4, 8]])

x_train = train_data[:,1:3]
y_train = train_data[:,0]

POLY_DEGREE = 3
input_size = 2
output_size = 1

poly = PolynomialFeatures(input_size * POLY_DEGREE, include_bias=False)
x_train_poly = poly.fit_transform(x_train.numpy())


class Model(torch.nn.Module):

    def __init__(self):
        super(Model, self).__init__()
        self.fc = torch.nn.Linear(poly.n_output_features_, output_size)

    def forward(self, x):
        return self.fc(x)

model = Model()    
criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.001)

losses = []

for i in range(10):
    optimizer.zero_grad()
    outputs = model(Variable(torch.Tensor(x_train_poly)))
    print(outputs)
    loss = criterion(outputs, Variable(y_train))
    print(loss.data[0])
    losses.append(loss.data[0])
    loss.backward()    
    optimizer.step()
    if loss.data[0] < 1e-4:
        break    

print('n_iter', i)
print(loss.data[0])
plt.plot(losses)
plt.show()

输出:

  

[393494300459008.0,inf,inf,inf,nan,nan,nan,nan,nan,nan]

     

n_iter

     

9 nan

1 个答案:

答案 0 :(得分:1)

有几件事导致了这个问题。改变其中的部分或全部将为您提供合理的结果并使学习成为可能。

  1. 您的某些(多项式)要素具有巨大的差异,并且具有非常大的值。检查np.max(x_train_poly)。当您的权重矩阵被随机初始化时,这会导致初始预测大部分关闭,并且损失很快接近无穷大。要抵消这种情况,您可能需要首先标准化您的功能(即为每个功能设置均值0和方差1)。请注意,在非常深的网络中,使用了类似的想法,即#34;批量标准化&#34;。如果您有兴趣,可以在此处阅读更多内容:https://arxiv.org/abs/1502.03167您可以执行以下操作来修复您的示例:

    means = np.mean(x_train_poly,axis=0,keepdims=True)
    std = np.std(x_train_poly,axis=0,keepdims=True)
    x_train_poly = (x_train_poly - means) / std
    
  2. 您当前的模型,没有任何隐藏层,这是神经网络的一种点,并构建一个非线性回归量/分类器。您现在正在做的是对27个输入要素应用线性变换,以获得接近输出的内容。您可以添加如下附加图层:

    hidden_dim = 50
    
    class Model(torch.nn.Module):
        def __init__(self):
            super(Model, self).__init__()
            self.layer1 = torch.nn.Linear(poly.n_output_features_, hidden_dim)
            self.layer2 = torch.nn.Linear(hidden_dim, output_size)
    
        def forward(self, x):
            return self.layer2(torch.nn.ReLU()(self.layer1(x)))
    

    请注意,我在第一次线性变换后添加了非线性,因为除此之外没有多个图层。

  3. 初始预测的问题在开始时大大偏离并导致损失接近无穷大。您使用的是平方损失,它基本上会使您的初始错误的数量级增加一倍&#34;在损失函数中。一旦损失无穷大,你将无法逃脱,因为当你使用平方损失时,渐变更新基本上也是无限的。一个有时很有用的简单修复就是使用平滑的L1损失。在该区间之外的区间[0,1]和L1损失上基本上是MSE。更改以下内容:

    criterion = torch.nn.SmoothL1Loss()
    
  4. 这已经让你得到一些明智的东西(即不再有infs),但现在 考虑调整学习率并引入weight_decay。您可能还想更改优化程序。一些有效的建议:

    optimizer = torch.optim.SGD(model.parameters(), lr=0.01, weight_decay=1)
    optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=0.1)