基于pytorch的LSTM单变量预测的实例

基于pytorch的LSTM单变量预测的实例

说明:

初学pytorch,试着做一做实例。数据处理参考了一些大佬的代码。

数据集来源于:champagne.csv · MJ/Datasets - Gitee.com

1.import库+读取数据集

df.fillna()#对缺失值进行填充,mean是一列的平均数。

import torch
import torch.nn as nn
import pandas as pd
import numpy as np
from scipy.interpolate import make_interp_spline
from torch.utils.data import Dataset,DataLoader
from itertools import chain
import matplotlib.pyplot as plt
def read_csv(filename):
  df=pd.read_csv(filename)
  colums=df.columns
  df.fillna(df.mean(),inplace=True)
  #归一化处理
  MAX=np.max(df[colums[1]])
  MIN=np.min(df[colums[1]])
  df[colums[1]]=(df[colums[1]]-MIN)/(MAX-MIN)
  return df

2.数据预处理

由于LSTM是时间序列预测,所以需要seq_len,以下代码中8就是seq_len。

原理:通过前8个时刻的数据来预测下一个时刻。

def process(filename,b):
  print("procedding-------")
  data=read_csv(filename)
  print(data.shape)
  load=data[data.columns[1]]
  load=load.tolist()
  data=data.values.tolist()
  seq=[]
  for i in range(len(data)-8):#8个时刻为一组
    train_seq=[]
    train_label=[]
    for j in range(i,i+8):
      x=[load[j]]
        #如果是多变量,在这里可以添加列
      train_seq.append(x)
    train_label.append(load[i+8])
    train_seq=torch.FloatTensor(train_seq)
    train_label=torch.FloatTensor(train_label)
    seq.append((train_seq,train_label))
  print(len(seq))
  Dtr=seq[:int(len(seq)*0.8)]
  Dte=seq
  train_len=int(len(Dtr)/b)*b
  test_len=int(len(Dte)/b)*b
  Dtr,Dte=Dtr[:train_len],Dte[:test_len]
  Dtr=DataLoader(dataset=Dtr,batch_size=b,shuffle=False,num_workers=0)
  Dte=DataLoader(dataset=Dte,batch_size=b,shuffle=False,num_workers=0)
  return Dtr,Dte

3.LSTM搭建

pred[:-1:]是为了只取最后一个时刻的数据。

class LSTM(nn.Module):
  def __init__(self,input_size,hidden_size,num_layers,output_size,batch_size):
    super().__init__()
    self.input_size = input_size
    self.hidden_size = hidden_size
    self.num_layers = num_layers
    self.output_size = output_size
    self.num_directions = 1
    self.batch_size = batch_size
    self.lstm=nn.LSTM(self.input_size,self.hidden_size,self.num_layers,batch_first=True)
    self.linear=nn.Linear(self.hidden_size,self.output_size)
  def forward(self,input):
    seq_len = input.shape[1]
    #input(batch_size, seq_len, input_size)
    output,_=self.lstm(input)
    pred=self.linear(output)
    pred=pred[:,-1,:]
    return pred

4.训练

optimizer.step()这步不能忘记,否则结果只是限定在一个小范围内。

def train(name,b):
  Dtr,Dte=process(filename=name,b=b)
  model=LSTM(input_size=1,hidden_size=12,output_size=1,num_layers=1,batch_size=b)
  print(model)
  loss_fu=nn.MSELoss()
  optimizer=torch.optim.Adam(model.parameters(),lr=0.01)
  epoch=40
  for i in range(epoch):
    cnt=0
    print('NOW',i)
    for(seq,label) in Dtr:
      cnt+=1
      y_pred=model(seq)
      loss=loss_fu(y_pred,label)
      optimizer.zero_grad()
      loss.backward()
      optimizer.step()#梯度上升
      print('epoch',i,':',cnt,loss.item())

5.测试结果

make_interp_spline插值法,是一种曲线平滑处理的方法。

可参考Python scipy.interpolate.make_interp_spline用法及代码示例 - 纯净天空 (vimsky.com)

  x = [i for i in range(1, 97)]#x是横坐标 1-96
  x = np.linspace(np.min(x), np.max(x), 900)
  #np.linspace(start,end,num)在start 和end之间返回900个数字 np.min 是返回最小的数字
  y = make_interp_spline(x, y.T)(x)#画图方式 x,y行数要一样
  plt.plot(x, y, c='green', marker='*', ms=1, alpha=0.75, label='true')
  y = make_interp_spline(x, pred.T)(x)#预测的
  plt.plot(x, y, c='red', marker='o', ms=1, alpha=0.75, label='pred')
  #plt.grid(axis='y')
  plt.legend()#图例的名称
  plt.show()

结果似乎还不错。文章有什么问题的话,欢迎指正。


8.22更新

阅读了一些单步预测的文章,发现一些自身的问题:

每次预测时都是用前8个时刻的真实值来预测下一个时刻,实际应用这种预测做的没有意义。应该将第9个的预测值加入数据集中,并参与到预测,实现迭代预测。但是这样误差会越来越大。

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是一个使用 PyTorch 实现 LSTM变量预测的示例代码: ```python import torch import torch.nn as nn import numpy as np import pandas as pd from sklearn.preprocessing import MinMaxScaler # 加载数据 df = pd.read_csv('data.csv') df = df.dropna() data = df.values[:, 1:].astype('float32') # 数据预处理 scaler = MinMaxScaler(feature_range=(-1, 1)) data = scaler.fit_transform(data) # 划分训练集和测试集 train_size = int(len(data) * 0.7) train_data = data[:train_size, :] test_data = data[train_size:, :] # 定义函数将数据转换为序列数据 def create_sequences(data, seq_length): xs = [] ys = [] for i in range(len(data) - seq_length - 1): x = data[i:(i + seq_length), :] y = data[(i + seq_length), :] xs.append(x) ys.append(y) return np.array(xs), np.array(ys) # 创建序列数据 seq_length = 10 train_X, train_y = create_sequences(train_data, seq_length) test_X, test_y = create_sequences(test_data, seq_length) # 转换为 PyTorch 张量 train_X = torch.from_numpy(train_X).float() train_y = torch.from_numpy(train_y).float() test_X = torch.from_numpy(test_X).float() test_y = torch.from_numpy(test_y).float() # 定义 LSTM 模型 class LSTM(nn.Module): def __init__(self, input_size, hidden_size, num_layers, output_size): super(LSTM, self).__init__() self.hidden_size = hidden_size self.num_layers = num_layers self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True) self.fc = nn.Linear(hidden_size, output_size) def forward(self, x): h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).requires_grad_() c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).requires_grad_() out, (hn, cn) = self.lstm(x, (h0.detach(), c0.detach())) out = self.fc(out[:, -1, :]) return out # 训练模型 input_size = train_X.shape[2] output_size = train_y.shape[1] hidden_size = 128 num_layers = 2 learning_rate = 0.01 num_epochs = 1000 model = LSTM(input_size, hidden_size, num_layers, output_size) criterion = nn.MSELoss() optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) for epoch in range(num_epochs): outputs = model(train_X) optimizer.zero_grad() loss = criterion(outputs, train_y) loss.backward() optimizer.step() if epoch % 100 == 0: print("Epoch [{}/{}], Loss: {:.4f}".format(epoch+1, num_epochs, loss.item())) # 测试模型 model.eval() with torch.no_grad(): test_outputs = model(test_X) test_loss = criterion(test_outputs, test_y) print('Test loss: {:.4f}'.format(test_loss.item())) # 将预测结果转换为原始数据范围 test_outputs = scaler.inverse_transform(test_outputs.numpy()) test_y = scaler.inverse_transform(test_y.numpy()) # 绘制预测结果和实际结果 import matplotlib.pyplot as plt plt.plot(test_y[:, 0], label='Actual') plt.plot(test_outputs[:, 0], label='Predicted') plt.legend(loc='upper left') plt.show() ``` 这个示例代码加载了一个数据集,使用 MinMaxScaler 对数据进行预处理,然后将数据划分为训练集和测试集。接着,它定义了一个函数将数据转换为序列数据,创建了 LSTM 模型,并使用 MSE 损失函数和 Adam 优化器训练模型。最后,它测试了模型,并将预测结果和实际结果绘制在一起。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值