import torch import torch.nn as nn import numpy as np import pandas as pd import matplotlib.pyplot as plt # 由于训练数据存在相差较大的,因此使用min/max尺度变换对训练数据进行归一化 # 注意只对训练数据进行归一化,为了防止有些信息从训练数据泄露到的测试数据 from sklearn.preprocessing import MinMaxScaler flight_data = pd.read_csv(r"C:\Users\Administrator\Desktop\填补缺失值.csv") fig_size = plt.rcParams["figure.figsize"] fig_size[0] = 15 fig_size[1] = 5 plt.rcParams["figure.figsize"] = fig_size plt.title('power vs day') plt.ylabel('power') plt.xlabel('day') plt.grid(True) plt.autoscale(axis='x',tight=True) plt.plot(flight_data['power']) plt.show() #提取数据 all_data = flight_data['power'].values.astype(float) print(all_data) #将数据区分为训练数据和测试数据 test_data_size = 960 train_data = all_data[:-test_data_size] test_data = all_data[-test_data_size:] # 由于训练数据存在相差较大的,因此使用min/max尺度变换对训练数据进行归一化 # 注意只对训练数据进行归一化,为了防止有些信息从训练数据泄露到的测试数据 scaler = MinMaxScaler(feature_range=(-1, 1)) train_data_normalized = scaler.fit_transform(train_data.reshape(-1, 1)) print(train_data_normalized) # 将数据转换为张量 train_data_normalized = torch.FloatTensor(train_data_normalized).view(-1) def create_inout_sequences(input_data, tw): inout_seq = [] L = len(input_data) for i in range(L-tw): train_seq = input_data[i:i+tw] train_label = input_data[i+tw:i+tw+1] inout_seq.append((train_seq ,train_label)) return inout_seq train_window =5 train_inout_seq = create_inout_sequences(train_data_normalized, train_window) #定义LSTM模型 class LSTM(nn.Module): def __init__(self, input_size=1, hidden_size=55, output_size=1): super().__init__() self.hidden_size = hidden_size # 定义lstm 层 self.lstm = nn.LSTM(input_size, hidden_size) # 定义线性层,即在LSTM的的输出后面再加一个线性层 self.linear = nn.Linear(hidden_size, output_size) # input_seq参数表示输入sequence def forward(self, input_seq): # lstm默认的输入X是(sequence_legth,bacth_size,input_size) lstm_out,\ self.hidden_cell = self.lstm(input_seq.view(len(input_seq), 1, -1), self.hidden_cell) # lstm_out的默认大小是(sequence_legth,bacth_size,hidden_size) # 转化之后lstm_out的大小是(sequence_legth, bacth_size*hidden_size) predictions = self.linear(lstm_out.view(len(input_seq), -1)) # 由于bacth_size = 1, 可知predictions 的维度为(sequence_legth, output_size) # [-1] 表示的是取最后一个时间步长对应的输出 return predictions[-1] # 模型实例化并定义损失函数和优化函数 model = LSTM() loss_function = nn.MSELoss() optimizer = torch.optim.Adam(model.parameters(), lr=0.001) print(model) epochs = 1 for i in range(epochs): for seq, labels in train_inout_seq: optimizer.zero_grad() model.hidden_cell = (torch.zeros(1, 1, model.hidden_size), torch.zeros(1, 1, model.hidden_size)) y_pred = model(seq) single_loss = loss_function(y_pred, labels) single_loss.backward() optimizer.step() #if i%25 == 1: print(f'epoch: {i:3} loss: {single_loss.item():10.8f}') print(f'epoch: {i:3} loss: {single_loss.item():10.10f}') # 以train data的最后12个数据进行预测 fut_pred = 960 test_inputs = train_data_normalized[-train_window:].tolist() print(test_inputs) model.eval() # 基于最后12个数据来预测第133个数据,并基于新的预测数据进一步预测 # 134-144 的数据 for i in range(fut_pred): seq = torch.FloatTensor(test_inputs[-train_window:]) # 模型评价时候关闭梯度下降 with torch.no_grad(): model.hidden = (torch.zeros(1, 1, model.hidden_size), torch.zeros(1, 1, model.hidden_size)) test_inputs.append(model(seq).item()) test_inputs[fut_pred:] actual_predictions = scaler.inverse_transform(np.array(test_inputs[train_window:] ).reshape(-1, 1)) print(actual_predictions) # 绘制图像查看预测的[133-144]的数据和实际的133-144 之间的数据差别 x = np.arange(127584,128544, 1) plt.title('power vs day') plt.ylabel('power') plt.grid(True) plt.autoscale(axis='x', tight=True) plt.plot(flight_data['power']) plt.plot(x,actual_predictions) plt.show()
话不多说,先上代码,这个LSTM网络是基于之前一个博主的,然后我再根据自己的比赛需要改进了一部分,这篇文章算是记录一下自己第一次搭建神经网络。
1:第一个就是数据的读取 建议使用pandas来读取数据 值得注意的是路径名前要有一个r用于转义,否则系统会报错,还有EXCEL文件要转化成CSV格式
2:第二个就是对于原始数据的可视化,python作为解释性语言相信大家也看的明白那些plt...怎么干嘛
3:因为数据是一个时间序列,所以我们先提取其中的值部分,先忽略时间部分
4:将数据集划分为训练集和测试集,比例一般在4:1左右
5:数据的归一化
from sklearn.preprocessing import MinMaxScaler
使用库函数 将值变化到-1到1之间 这样便于在训练的时候快速收敛 不然计算时间会比较久
还有就是一些参数的设定 比如train_window hidden_size epoch fut_pred
等等参数的设置 里面还有一些LSTM的细节 感兴趣的可以多了解一下他的原理
最后就是自己改预测范围 看你想要的预测是多
少 当然原来的博主里面没有反归一化 我们要记得反归一化 不然预测的数据还是-1到1
actual_predictions = scaler.inverse_transform(np.array(test_inputs[train_window:] ).reshape(-1, 1))