python - 绘制 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
不仅仅是一条直线。
解决方案
您可以将测试和训练循环分开,因为我认为您正在使用脚本累积梯度。学习时看不到任何测试集信息是一条黄金法则。
问题应该存在于您可以删除的第 6 个激活函数中。我了解您希望将输出值限制在 0 到 1 之间,但在与分类无关的任务中使用 sigmoid 并不是一件好事。
推荐阅读
- javascript - 从 AMD 模块 moodle 调用 PHP 函数
- laravel - Symlink():没有这样的文件或目录,因为公用文件夹位于不同的目录中
- vb.net - 将光标移动到 Visual Basic(紧凑框架)表单中的文本/内容的末尾?
- azure - 如何使用 Nginx 和 Microsoft Azure AD 进行身份验证?
- mysql - 外键约束导致 MySQL 5.7 中的重复条目,但不是 5.6
- python - 获取相关对象列表 - Django Queryset
- android - Android Studio 预览版和 Emulator 显示出很大差异
- python - 如何在没有互联网连接的情况下在 CentOS 中安装最新版本的 Python 和 python 包?
- css - JavaFX - TreeView - CSS 在以编程方式选择元素时不适用
- javascript - click 事件不会在 ajax 加载的对象上触发