代码之家  ›  专栏  ›  技术社区  ›  Medulla Oblongata

用Pytorch神经网络绘制回归问题的预测值和实际值

  •  0
  • Medulla Oblongata  · 技术社区  · 3 年前

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

    以下是我的数据示例:

                       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 值与实际/预期值的比值如下。我以为 预测 不会只是一条直线。

    enter image description here

    0 回复  |  直到 3 年前
        1
  •  0
  •   anonymous    3 年前

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

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