首页 > 解决方案 > 绘制 Pytorch 回归问题的预测结果和实际结果

问题描述

我正在尝试通过调整 curiosily教程中的代码来使用神经网络解决回归问题。在训练/测试阶段之后,我想将预测结果(来自神经网络)与预期值一起绘制。但我总是得到预测结果的恒定值。

这是我的数据示例:

                   y        x1        x2        x3        x4        x5  \
Date                                                                     
2015-03-02  1.000000  0.326808  0.954789  0.345128  0.809366  0.401721   
2015-03-09  0.469589  0.323142  0.676289  0.000000  0.791904  0.337875   
2015-03-16  0.783375  0.211984  0.801912  0.312489  0.283238  0.628224   
2015-03-23  0.837088  0.099067  0.662923  0.028891  0.334150  0.455690   
2015-03-30  0.576463  0.000000  0.694937  0.376173  0.147238  0.784254   
2016-03-07  0.520800  0.652797  1.000000  0.501365  0.698179  0.498709   
2016-03-14  0.492543  0.658820  0.830122  0.219795  0.814204  0.330795   
2016-03-21  0.536455  0.731701  0.848878  0.133867  1.000000  0.134471   
2016-03-28  0.009716  0.880046  0.000000  0.299588  0.710215  0.310644   
2017-03-06  0.085095  1.000000  0.810502  0.792946  0.481694  0.726653   
2017-03-13  0.272674  0.890968  0.760774  0.227955  0.163028  0.352487   
2017-03-20  0.000000  0.769808  0.589088  1.000000  0.000000  1.000000   
2017-03-27  0.170325  0.656550  0.785720  0.247674  0.387465  0.547248   
2018-03-05  0.663452  0.792394  0.715791  0.004552  0.321927  0.000000   
2018-03-12  0.489003  0.838095  0.569241  0.269696  0.703545  0.079207   
2018-03-19  0.411556  0.833784  0.616880  0.124014  0.830961  0.281638   
2018-03-26  0.342121  0.851702  0.653559  0.554556  0.934628  0.426153   

                  x6  year  week  
Date                              
2015-03-02  0.925160  2015    10  
2015-03-09  0.631814  2015    11  
2015-03-16  0.757044  2015    12  
2015-03-23  0.617873  2015    13  
2015-03-30  0.660571  2015    14  
2016-03-07  1.000000  2016    10  
2016-03-14  0.833336  2016    11  
2016-03-21  0.884074  2016    12  
2016-03-28  0.000000  2016    13  
2017-03-06  0.796808  2017    10  
2017-03-13  0.737460  2017    11  
2017-03-20  0.567961  2017    12  
2017-03-27  0.783137  2017    13  
2018-03-05  0.739046  2018    10  
2018-03-12  0.577926  2018    11  
2018-03-19  0.620370  2018    12  
2018-03-26  0.699337  2018    13  

我的代码是

import os
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import pandas.io.sql as sql
from datetime import date, datetime, time, timedelta
import holidays
from db import DB
import torch
from torch import nn, optim
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler, StandardScaler


## load dataframe


## inputs
cols0 = [i for i in ['x1','x2','x3','x4','x5','x6','year','week'] if i != 'y']
X = mydata[cols0]

## output
y0 = mydata[['y']]

X_train, X_test, y_train, y_test = train_test_split(X, y0, test_size=0.3, random_state=50)

## convert everything to tensors
X_train = torch.from_numpy(X_train.values).float()
y_train = torch.squeeze(torch.from_numpy(y_train.values).float())
X_test = torch.from_numpy(X_test.values).float()
y_test = torch.squeeze(torch.from_numpy(y_test.values).float())

## build neural network
class Net(nn.Module):
    def __init__(self, n_features):
        super(Net, self).__init__()
        # n_features = no. inputs
        n1 = 8 # no. nodes in layer 1
        n2 = 5 # no. nodes in layer 2
        n3 = 4 # no. nodes in layer 3
        n4 = 5 # no. nodes in layer 4
        n5 = 2 # no. nodes in layer 5
        self.fc1 = nn.Linear(n_features,n1)
        self.fc2 = nn.Linear(n1,n2)
        self.fc3 = nn.Linear(n2,n3)
        self.fc4 = nn.Linear(n3,n4)
        self.fc5 = nn.Linear(n4,n5)
        self.fc6 = nn.Linear(n5,1)
    def forward(self, x):
        #x = F.relu(self.fc1(x)) 
        x = torch.tanh(self.fc1(x)) # activation function in layer 1
        x = torch.sigmoid(self.fc2(x)) 
        x = torch.sigmoid(self.fc3(x)) 
        x = torch.tanh(self.fc4(x)) 
        x = torch.tanh(self.fc5(x))
        return torch.sigmoid(self.fc6(x))

net = Net(X_train.shape[1])
criterion = nn.MSELoss() # loss function
optimizer = optim.Adam(net.parameters(), lr=0.0001)

## training 
for epoch in range(2001):
    
    y_pred = net(X_train)
    y_pred = torch.squeeze(y_pred)
    train_loss = criterion(y_pred, y_train)
       
    # forward feed
    y_test_pred = net(X_test)
    y_test_pred = torch.squeeze(y_test_pred)

    test_loss = criterion(y_test_pred, y_test) # calculate the loss
    optimizer.zero_grad() # clear out gradients from loss.backward()     
    train_loss.backward() # back propagation
    optimizer.step() # update weights
    
## reverse scaling of test data and model predictions
scaler = MinMaxScaler()
scaler0 = scaler.fit(np.expand_dims(y_train, axis=1))
ytrue = scaler0.inverse_transform(np.expand_dims(y_test.detach().numpy().flatten(),axis=0)).flatten()
ypred = scaler0.inverse_transform(np.expand_dims(y_test_pred.detach().numpy(),axis=0)).flatten()

plt.figure()
plt.plot(ypred, label='predicted')
plt.plot(ytrue, label='actual')
plt.ylabel('output y')
plt.legend()
plt.show()

显示predicted值与实际/预期值的图如下。我认为这predicted不仅仅是一条直线。

在此处输入图像描述

标签: pythonmachine-learningplotneural-networkpytorch

解决方案


您可以将测试和训练循环分开,因为我认为您正在使用脚本累积梯度。学习时看不到任何测试集信息是一条黄金法则。

问题应该存在于您可以删除的第 6 个激活函数中。我了解您希望将输出值限制在 0 到 1 之间,但在与分类无关的任务中使用 sigmoid 并不是一件好事。


推荐阅读