基于pytorch的lstm时间回归预测(附全部代码)
⾸先说明作者是神经⽹络纯新⼿,虽然之前⽤过神经⽹络的代码,但基本上都是各种copy,只搞清楚了input_size和output_size,这两天因为⼯作需要要跑⼀个lstm的回归预测,在⽹上的教程都不太清楚,对新⼿不是很友好,对新⼿友好的好像好多都是错的,⾃⼰也想了很久才想明⽩lstm回归预测到低是什么情况,跟⼤家分享⼀下,如果有错误也希望⼤家能指正。
⾸先是lstm的⼀张图,引⾃,建议看本⽂章之前先⼏个教程把lstm搞懂,我个⼈觉得lstm懂了的标志就是下⾯这张图你看懂了。
⾸先,厘清⼀下本⽂所针对的任务,多特征的时间序列回归预测,再说直⽩⼀点,数据长成这个样⼦
简单来说就是n*m的ndarray,n表⽰时间序列的长度,m表⽰每⼀个时间点的feature,我图中的数据来⾃,准确来说,这个数据也不是来⾃于这个作者,是⼀个经典的“航空客流预测”任务。这个作者应该是个机器学习的⼤佬,这篇⽂章很值得⼀读,但是估计新⼿也读不太懂,我纯新⼿反正⼀开始是没搞懂,但是⾮常不建议去看这篇⽂章的原版,因为原版完全是个错误例⼦。
因为是⼩⽩向我就不先说错误例⼦怎么做的了,只说⼀个最关键的点,“航空客流预测”任务中,时间序列很短只有100多个长度,完全可以⼀次性放进长度为100多的lstm⾥⾯训练,但是通常的时间回归预测任务⾥⾯,时间长度很多,势必要分成很多个定长的序列,然后再送进去训练。这⼀点也是最误解我的,我想了半天都想不通time_step到低去哪了,事实上分成训练集之后的时间序列数据本⾝长度就是那个time_step。(当然也可以不定长,事实上我刚刚转的那篇⽂章就是这样做的,但是我感觉⽬前我没啥必要这样搞。)下⾯我简单把流程说⼀下。
第⼀步:定⼀个time_step,把原数据拆成n个样本,⽐如原数据是[[1a,1b],[2a,2b],[3a,3b],[4a,4b]],time_step定为2,则原数据被拆成[[[1a,1b],[2a,2b]],[[2a,2b],[3a,3b]],[[3a,3b],[4a,4b]]]。
本来是不想在流程⾥⾯加很多字的,但是这点太关键了所以在这⾥说明。这⾥为了避免造成误解,我特意⽤了feature为2的数据!把
time_step个数据塞到⼀起之后并不是直接扔给⼀个lstm的神经单元,之前说的⽂章原版本就是返了这个错误,把time_step个数据塞到⼀个lstm跟⽤mlp就没什么区别了,⼀定是⼀个数据的全部feature扔到⼀个单元⾥⾯,然后有多长就扔给多长的lstm来训练。这⾥有另外让⼈感觉迷惑的点,就是pytorch⾥⾯的lstm⽹络并没有固定长度,也就是说你训练的时候可以⽤10长度的lstm⽹络,预测的时候⽤5长度的塞进⽹络都可以,这个从lstm原理上⾯的权值共享很容易理解为什么可以,但是会让新⼿感觉很
迷惑,尤其是在时间回归预测⾥⾯,我们只需要最后⼀个值,也就是output[-1],但是lstm是把output整个给输出出来,这个细节⼀定要注意!
第⼆步:定⼀个batch_size,把n个样本分成n/batch_size个⼩batch,每个batch扔进⽹络去训练,最后剩下来不⾜⼀个batch的也打包好塞进去。
第三步:出结果,预测检验就可以了!
我⽐较懒,lstm的输⼊输出,参数我就不再写了,⽹上介绍的也⾮常多,可以去看看,下⾯附上我的代码,同样是⽤“航天客流预测”任务的数据去做,⼤家可以试⼀下,调⼀下time_step你就会发现1步都够预测了hhh,说明这个航天客流预测数据估计本⾝就是个sin类数据,规律性太强,当然也可能是知乎那篇⽂章的三个feature的trick⽐较⽜逼,总之⼤家可以试试。
ps:我真的很懒,jupyter写的代码直接download成py了,见谅!
#!/usr/bin/env python
# coding: utf-8
# In[1]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import torch
get_ipython().run_line_magic('matplotlib', 'inline')
from torch import nn
from torch.autograd import Variable
# In[121]:
batch_size=32
time_step=1
epoch=500
input_size=3
output_size=1
mid_dim=8
mid_layers=1
# In[122]:
class RegLSTM(nn.Module):
def __init__(self, inp_dim, out_dim, mid_dim, mid_layers,batch):
super(RegLSTM, self).__init__()
< = nn.LSTM(inp_dim, mid_dim, mid_layers,batch_first=batch)  # rnn
< = nn.Sequential(
nn.Linear(mid_dim, mid_dim),
nn.Tanh(),
nn.Linear(mid_dim, out_dim),
)  # regression
def forward(self, x):
y = (x)[0]  # y, (h, c) = (x)
batch_size, seq_len, hid_dim = y.shape
batch_size, seq_len, hid_dim = y.shape
y = y.reshape(-1, hid_dim)
y = (y)
y = y.reshape(batch_size, seq_len, -1)
return y
# In[123]:
def load_data():
seq_number=np.array(
[112., 118., 132., 129., 121., 135., 148., 148., 136., 119., 104.,
118., 115., 126., 141., 135., 125., 149., 170., 170., 158., 133.,
114., 140., 145., 150., 178., 163., 172., 178., 199., 199., 184.,
162., 146., 166., 171., 180., 193., 181., 183., 218., 230., 242.,
209., 191., 172., 194., 196., 196., 236., 235., 229., 243., 264.,
272., 237., 211., 180., 201., 204., 188., 235., 227., 234., 264.,
302., 293., 259., 229., 203., 229., 242., 233., 267., 269., 270.,
315., 364., 347., 312., 274., 237., 278., 284., 277., 317., 313.,
318., 374., 413., 405., 355., 306., 271., 306., 315., 301., 356.,
348., 355., 422., 465., 467., 404., 347., 305., 336., 340., 318.,
362., 348., 363., 435., 491., 505., 404., 359., 310., 337., 360.,
342., 406., 396., 420., 472., 548., 559., 463., 407., 362., 405.,
417., 391., 419., 461., 472., 535., 622., 606., 508., 461., 390.,
432.],dtype=np.float32
)
seq_number=seq_number[:,np.newaxis]
seq_year=np.arange(12)
seq_month=np.arange(12)
seq_year_anspose(
[
np.tile(seq_month,len(seq_year)),
]
)
atenate((seq_number,seq_year_month),axis=1)
seq=(an(axis=0))/seq.std(axis=0)
return(seq)
# In[124]:
data=load_data()
print(data)
train_size=int(len(data)*0.75)
# In[125]:
data_s((train_size-time_step+1,time_step,input_size)) label_s((train_size-time_step+1,time_step,output_size)) for i in range(train_size-time_step+1):
data_sample[i]=data[i:i+time_step,:]
label_sample[i]=data[i+1:i+1+time_step,0:1:]
# In[126]:
device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
net=RegLSTM(input_size,output_size,mid_dim,mid_layers,True).to(device) criterion=nn.MSELoss()
criterion=nn.MSELoss()
optimizer=torch.optim.Adam(net.parameters(),lr=1e-2)
# In[127]:
for i in range(epoch):
for j in range(int((train_size-time_step+1)/batch_size)):
train_X=data_sample[j*batch_size:(j+1)*batch_size,:,:]
train_Y=label_sample[j*batch_size:(j+1)*batch_size,:,:]
var_sor(train_X,dtype=torch.float32,device=device)        var_sor(train_Y,dtype=torch.float32,device=device)        out = net(var_x)
loss=criterion(out,var_y)
#loss = criterion(out[:,-1,:], var_y[:,-1,:])
<_grad()
loss.backward()
optimizer.step()
train_X=data_sample[(j+1)*batch_size:,:,:]
train_Y=label_sample[(j+1)*batch_size:,:,:]
var_sor(train_X,dtype=torch.float32,device=device)    var_sor(train_Y,dtype=torch.float32,device=device)    out = net(var_x)
loss = criterion(out, var_y)
<_grad()
loss.backward()
optimizer.step()
if i%100==0:
print('Epoch: {:4}, Loss: {:.5f}'.format(i, loss.item()))
# In[128]:
net=net.eval()
test_X=data[train_size:,:]
test_Y=data[train_size+time_step:,0:1:]
test_y=list()
for i in range(test_X.shape[0]-time_step):
test_x=test_X[i:time_step+i,:].reshape(1,time_step,input_size)
test_sor(test_x,dtype=torch.float32,device=device)
tem=net(test_x).cpu().data.numpy()
test_y.append(tem[0][-1])
test_y=np.array(test_y).reshape((-1,1))
diff=test_y-test_Y
l1_an(np.abs(diff))
l2_an(diff**2)
print("L1:{:.3f}    L2:{:.3f}".format(l1_loss,l2_loss))
python新手代码错了应该怎么改
plt.plot(test_y, 'r', label='pred')
plt.plot(test_Y, 'b', label='real', alpha=0.3)
# In[7]:
a=np.array([1,2,3])
b=np.array([2,2,4])
# In[9]:
shape(-1,1)
shape(-1,1) shape(-1,1)
# In[8]:
# In[10]:
# In[ ]:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。