当前位置: 首页 > news >正文

时间序列预测实战(二十三)进阶版LSTM多元和单元预测(课程设计毕业设计首选)

      


一、本文介绍

本篇文章给大家带来的是利用我个人编写的架构进行LSTM模型进行时间序列建模(专门为了时间序列领域新人编写的架构,简单且不同于市面上大家用GPT写的代码),包括结果可视化、支持单元预测、多元预测、模型拟合效果检测、预测未知数据、以及滚动长期预测功能。该结构是一个通用架构任何模型嵌入其中都可运行。在之前我已经将出过一个LSTM的讲解了,那个比较简单只能进行单元预测,所以在这里进行了一个补充这个模型框架可以满足所有的时间序列功能。

  专栏目录:时间序列预测目录:深度学习、机器学习、融合模型、创新模型实战案例

专栏: 时间序列预测专栏:基础知识+数据分析+机器学习+深度学习+Transformer+创新模型

预测功能效果展示(不是测试集是预测未知数据)->

损失截图(后面运行有损失图像运行即可显示)-> 

根据损失来看模型的拟合效果还是很好的,但后面还是做了检验模型拟合效果的功能让大家真正的评估模型的效果。

测试集表现->

这里只展示了部分功能,代码中我还添加了许多可视化功能和结果生成功能。 

目录

一、本文介绍

二、LSTM的框架原理

2.1 LSTM的基础的结构

2.1.1 忘记门

2.1.2 输入门

2.1.3 输出门

三、数据集介绍

四、参数讲解 

五、完整运行代码

六、训练模型 

七、预测结果

7.1 预测未知数据效果图

7.2 测试集效果图 

7.3 CSV文件生成效果图 

7.4 检验模型拟合效果图

八、全文总结


二、LSTM的框架原理

LSTM(长短期记忆,Long Short-Term Memory)是一种用于处理序列数据的深度学习模型属于循环神经网络(RNN)的一种变体,其使用一种类似于搭桥术结构的RNN单元。相对于普通的RNN,LSTM引入了门控机制,能够更有效地处理长期依赖和短期记忆问题,是RNN网络中最常使用的Cell之一。

2.1 LSTM的基础的结构

LSTM通过刻意的设计来实现学习序列关系的同时,又能够避免长期依赖的问题。它的结构示意图如下所示。

在LSTM的结构示意图中,每一条黑线传输着一整个向量,从一个节点的输出到其他节点的输入。其中“+”号代表着运算操作(如矢量的和)而矩形代表着学习到的神经网络层。汇合在一起的线表示向量的连接,分叉的线表示内容被复制,然后分发到不同的位置。

如果上面的LSTM结构图你看着很难理解,但是其实LSTM的本质就是一个带有tanh激活函数的简单RNN,如下图所示。

LSTM这种结构的原理是引入一个称为细胞状态的连接。这个状态细胞用来存放想要的记忆的东西(对应简单LSTM结构中的h,只不过这里面不再只保存上一次状态了,而是通过网络学习存放那些有用的状态),同时在加入三个门,分别是

        忘记门:   决定什么时候将以前的状态忘记。

        输入门:决定什么时候将新的状态加进来。

        输出门:决定什么时候需要把状态和输入放在一起输出。

从字面上可以看出,由于三个门的操作,LSTM在状态的更新和状态是否要作为输入,全部交给了神经网络的训练机制来选择。

下面分别来介绍一下三个门的结构和作用。


2.1.1 忘记门

下图所示为忘记门的操作,忘记门决定模型会从细胞状态中丢弃什么信息

忘记门会读取前一序列模型的输出h_{t-1}和当前模型的输入X_{t}来控制细胞状态中的每个数是否保留。

例如:在一个语言模型的例子中,假设细胞状态会包含当前主语的性别,于是根据这个状态便可以选择正确的代词。当我们看到新的主语时,应该把新的主语在记忆中更新。忘记们的功能就是先去记忆中找到一千那个旧的主语(并没有真正执行忘记的操作,只是找到而已。

在上图的LSTM的忘记门中,f_{t}代表忘记门的输出, α代表激活函数,W_{f}代表忘记门的权重,x_{t}代表当前模型的输入,h_{t-1}代表前一个序列模型的输出,b_{f}代表忘记门的偏置。


2.1.2 输入门

输入门可以分为两部分功能,一部分是找到那些需要更新的细胞状态。另一部分是把需要更新的信息更新到细胞状态里

在上面输入门的结构中,I_{t}代表要更新的细胞状态,α代表激活函数,x_{t}代表当前模型的输入,h_{t-1}代表前一个序列模型的输出,W_{t}代表计算I_{t}的权重,b_{t}代表计算I_{t}的偏置,_{}C_{t}代表使用tanh所创建的新细胞状态,W_{c}代表计算C_{t}的权重,b_{c}代表计算C_{t}的偏置。

忘记门找到了需要忘掉的信息f_{t}后,在将它与旧状态相乘,丢弃确定需要丢弃的信息。(如果需要丢弃对应位置权重设置为0),然后,将结果加上I_{t} * C_{t}使细胞状态获得新的信息。这样就完成了细胞状态的更新,如下图输入门的更新图所示。

再上图LSTM输入门的更新图中,B_{t}代表忘记门的输出结果, f_{t}代表忘记门的输出结果,B_{t-1}代表前一个序列模型的细胞状态,I_{t}代表要更新的细胞状态,\widetilde{C_{t}}代表使用tanh所创建的新细胞状态。


2.1.3 输出门

如下图LSTM的输出门结构图所示,在输出门中,通过一个激活函数层(实际使用的是Sigmoid激活函数)来确定哪个部分的信息将输出,接着把细胞状态通过tanh进行处理(得到一个在-1~1的值),并将它和Sigmoid门的输出相乘,得出最终想要输出的那个部分,例如,在语言模型中,假设已经输入了一个代词,便会计算出需要输出一个与该代词相关的信息(词向量)

在LSTM的输出门结构图中,O_{t}代表要输出的信息,α代表激活函数,W_{o}代表计算 O_{t}的权重,b_{o}代表计算O_{t}的偏置,B_{t}代表更新后的细胞状态,h_{t}代表当前序列模型的输出结果。


三、数据集介绍

本文是实战讲解文章,上面主要是简单讲解了一下网络结构比较具体的流程还是很复杂的涉及到很多的数学计算,下面我们来讲一讲模型的实战内容,第一部分是我利用的数据集。

本文我们用到的数据集是ETTh1.csv,该数据集是一个用于时间序列预测的电力负荷数据集,它是 ETTh 数据集系列中的一个。ETTh 数据集系列通常用于测试和评估时间序列预测模型。以下是 ETTh1.csv 数据集的一些内容:

数据内容该数据集通常包含有关电力系统的多种变量,如电力负荷、价格、天气情况等。这些变量可以用于预测未来的电力需求或价格。

时间范围和分辨率数据通常按小时或天记录,涵盖了数月或数年的时间跨度。具体的时间范围和分辨率可能会根据数据集的版本而异。 

以下是该数据集的部分截图->


四、参数讲解 

parser.add_argument('-model', type=str, default='TCN-LSTM', help="模型持续更新")parser.add_argument('-window_size', type=int, default=126, help="时间窗口大小, window_size > pre_len")parser.add_argument('-pre_len', type=int, default=24, help="预测未来数据长度")# dataparser.add_argument('-shuffle', action='store_true', default=True, help="是否打乱数据加载器中的数据顺序")parser.add_argument('-data_path', type=str, default='ETTh1-Test.csv', help="你的数据数据地址")parser.add_argument('-target', type=str, default='OT', help='你需要预测的特征列,这个值会最后保存在csv文件里')parser.add_argument('-input_size', type=int, default=7, help='你的特征个数不算时间那一列')parser.add_argument('-feature', type=str, default='M', help='[M, S, MS],多元预测多元,单元预测单元,多元预测单元')# learningparser.add_argument('-lr', type=float, default=0.001, help="学习率")parser.add_argument('-drop_out', type=float, default=0.05, help="随机丢弃概率,防止过拟合")parser.add_argument('-epochs', type=int, default=20, help="训练轮次")parser.add_argument('-batch_size', type=int, default=16, help="批次大小")parser.add_argument('-save_path', type=str, default='models')# modelparser.add_argument('-hidden_size', type=int, default=64, help="隐藏层单元数")parser.add_argument('-kernel_sizes', type=int, default=3)parser.add_argument('-laryer_num', type=int, default=2)# deviceparser.add_argument('-use_gpu', type=bool, default=True)parser.add_argument('-device', type=int, default=0, help="只设置最多支持单个gpu训练")# optionparser.add_argument('-train', type=bool, default=True)parser.add_argument('-test', type=bool, default=True)parser.add_argument('-predict', type=bool, default=True)parser.add_argument('-inspect_fit', type=bool, default=True)parser.add_argument('-lr-scheduler', type=bool, default=True)

为了大家方便理解,文章中的参数设置我都用的中文,所以大家应该能够更好的理解。下面我在进行一遍讲解。 

参数名称参数类型参数讲解
1modelstr模型名称
2window_sizeint时间窗口大小,用多少条数据去预测未来的数据

3

pre_lenint预测多少条未来的数据
4shufflestore_true是否打乱输入dataloader中的数据,不是数据的顺序

5

data_pathstr你输入数据的地址
6targetstr你想要预测的特征列

7

input_sizeint输入的特征数不包含时间那一列!!!

8

featurestr[M, S, MS],多元预测多元,单元预测单元,多元预测单元
9lrfloat学习率大小

10

drop_out

float丢弃概率
11epochsint训练轮次

12

batch_sizeint批次大小
13svae_pathstr模型的保存路径

14

hidden_sizeint隐藏层大小
15kernel_sizeint卷积核大小

16

layer_numintlstm层数
17use_gpubool是否使用GPU

18

deviceintGPU编号
19trainbool是否进行训练

20

predictbool是否进行预测

21

inspect_fitbool是否进行检验模型
22lr_schdulerbool是否使用学习率计划


五、完整运行代码

复制粘贴到一个文件下并且按照上面的从参数讲解配置好参数即可运行~(极其适合新手和刚入门的读者)

import argparse
import time
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from torch.utils.data import DataLoader
from torch.utils.data import Dataset
from tqdm import tqdm
import torch
import torch.nn as nn
from torch.nn.utils import weight_norm
# 随机数种子
np.random.seed(0)def plot_loss_data(data):# 使用Matplotlib绘制线图plt.figure()plt.plot(data, marker='o')# 添加标题plt.title("loss results Plot")# 显示图例plt.legend(["Loss"])plt.show()class TimeSeriesDataset(Dataset):def __init__(self, sequences):self.sequences = sequencesdef __len__(self):return len(self.sequences)def __getitem__(self, index):sequence, label = self.sequences[index]return torch.Tensor(sequence), torch.Tensor(label)def create_inout_sequences(input_data, tw, pre_len, config):# 创建时间序列数据专用的数据分割器inout_seq = []L = len(input_data)for i in range(L - tw):train_seq = input_data[i:i + tw]if (i + tw + pre_len) > len(input_data):breakif config.feature == 'MS':train_label = input_data[:, -1:][i + tw:i + tw + pre_len]else:train_label = input_data[i + tw:i + tw + pre_len]inout_seq.append((train_seq, train_label))return inout_seqdef calculate_mae(y_true, y_pred):# 平均绝对误差mae = np.mean(np.abs(y_true - y_pred))return maedef create_dataloader(config, device):print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>创建数据加载器<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<")df = pd.read_csv(config.data_path)  # 填你自己的数据地址,自动选取你最后一列数据为特征列 # 添加你想要预测的特征列pre_len = config.pre_len  # 预测未来数据的长度train_window = config.window_size  # 观测窗口# 将特征列移到末尾target_data = df[[config.target]]df = df.drop(config.target, axis=1)df = pd.concat((df, target_data), axis=1)cols_data = df.columns[1:]df_data = df[cols_data]# 这里加一些数据的预处理, 最后需要的格式是pd.seriestrue_data = df_data.values# 定义标准化优化器scaler_train = StandardScaler()scaler_valid = StandardScaler()scaler_test = StandardScaler()train_data = true_data[:int(1 * len(true_data))]valid_data = true_data[int(0.80 * len(true_data)):int(0.85 * len(true_data))]test_data = true_data[int(0.85 * len(true_data)):]print("训练集尺寸:", len(train_data), "测试集尺寸:", len(test_data), "验证集尺寸:", len(valid_data))# 进行标准化处理train_data_normalized = scaler_train.fit_transform(train_data)test_data_normalized = scaler_test.fit_transform(test_data)valid_data_normalized = scaler_valid.fit_transform(valid_data)# 转化为深度学习模型需要的类型Tensortrain_data_normalized = torch.FloatTensor(train_data_normalized).to(device)test_data_normalized = torch.FloatTensor(test_data_normalized).to(device)valid_data_normalized = torch.FloatTensor(valid_data_normalized).to(device)# 定义训练器的的输入train_inout_seq = create_inout_sequences(train_data_normalized, train_window, pre_len, config)test_inout_seq = create_inout_sequences(test_data_normalized, train_window, pre_len, config)valid_inout_seq = create_inout_sequences(valid_data_normalized, train_window, pre_len, config)# 创建数据集train_dataset = TimeSeriesDataset(train_inout_seq)test_dataset = TimeSeriesDataset(test_inout_seq)valid_dataset = TimeSeriesDataset(valid_inout_seq)# 创建 DataLoadertrain_loader = DataLoader(train_dataset, batch_size=args.batch_size, shuffle=True, drop_last=True)test_loader = DataLoader(test_dataset, batch_size=args.batch_size, shuffle=False, drop_last=True)valid_loader = DataLoader(valid_dataset, batch_size=args.batch_size, shuffle=False, drop_last=True)print("通过滑动窗口共有训练集数据:", len(train_inout_seq), "转化为批次数据:", len(train_loader))print("通过滑动窗口共有测试集数据:", len(test_inout_seq), "转化为批次数据:", len(test_loader))print("通过滑动窗口共有验证集数据:", len(valid_inout_seq), "转化为批次数据:", len(valid_loader))print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>创建数据加载器完成<<<<<<<<<<<<<<<<<<<<<<<<<<<")return train_loader, test_loader, valid_loader, scaler_train, scaler_test, scaler_validclass LSTM(nn.Module):def __init__(self, input_size, output_size, pre_len, hidden_size, n_layers,  dropout=0.05):super(LSTM, self).__init__()self.pre_len = pre_lenself.n_layers = n_layersself.hidden_size = hidden_sizeself.hidden = nn.Linear(input_size, self.hidden_size)self.relu = nn.ReLU()self.lstm = nn.LSTM(self.hidden_size, self.hidden_size, n_layers, bias=True, batch_first=True)  # output (batch_size, obs_len, hidden_size)self.linear = nn.Linear(self.hidden_size, output_size)def forward(self, x):batch_size, obs_len, features_size = x.shape  # (batch_size, obs_len, features_size)xconcat = self.hidden(x)  # (batch_size, obs_len, hidden_size)H = torch.zeros(batch_size, obs_len - 1, self.hidden_size).to(device)  # (batch_size, obs_len-1, hidden_size)ht = torch.zeros(self.n_layers, batch_size, self.hidden_size).to(device)  # (num_layers, batch_size, hidden_size)ct = ht.clone()for t in range(obs_len):xt = xconcat[:, t, :].view(batch_size, 1, -1)  # (batch_size, 1, hidden_size)out, (ht, ct) = self.lstm(xt, (ht, ct))  # ht size (num_layers, batch_size, hidden_size)htt = ht[-1, :, :]  # (batch_size, hidden_size)if t != obs_len - 1:H[:, t, :] = httH = self.relu(H)  # (batch_size, obs_len-1, hidden_size)x = self.linear(H)return x[:, -self.pre_len:, :]def train(model, args, device):start_time = time.time()  # 计算起始时间model = modelloss_function = nn.MSELoss()optimizer = torch.optim.Adam(model.parameters(), lr=0.005)epochs = args.epochsmodel.train()  # 训练模式results_loss = []for i in tqdm(range(epochs)):losss = []for seq, labels in train_loader:optimizer.zero_grad()y_pred = model(seq)single_loss = loss_function(y_pred, labels)single_loss.backward()optimizer.step()losss.append(single_loss.detach().cpu().numpy())tqdm.write(f"\t Epoch {i + 1} / {epochs}, Loss: {sum(losss) / len(losss)}")results_loss.append(sum(losss) / len(losss))save_loss = []if save_loss:valid_loss = valid(model, args, scaler_valid, valid_loader)# 尚未引入学习率计划后期补上torch.save(model.state_dict(), 'save_model.pth')time.sleep(0.1)# 保存模型print(f">>>>>>>>>>>>>>>>>>>>>>模型已保存,用时:{(time.time() - start_time) / 60:.4f} min<<<<<<<<<<<<<<<<<<")plot_loss_data(results_loss)return scaler_traindef valid(model, args, scaler, valid_loader):lstm_model = model# 加载模型进行预测lstm_model.load_state_dict(torch.load('save_model.pth'))lstm_model.eval()  # 评估模式losss = []for seq, labels in valid_loader:pred = lstm_model(seq)mae = calculate_mae(pred.detach().numpy().cpu(), np.array(labels.detach().cpu()))  # MAE误差计算绝对值(预测值  - 真实值)losss.append(mae)# print("验证集误差MAE:", losss)return sum(losss)/len(losss)def test(model, args, scaler, test_loader):# 加载模型进行预测losss = []df = pd.read_csv(args.data_path)df_inverse = df[int(0.85 * len(df)):][[args.target]].reset_index(drop=True)scaler_pre = StandardScaler().fit(df_inverse)model = modelmodel.load_state_dict(torch.load('save_model.pth'))model.eval()  # 评估模式results = []labels = []for seq, label in test_loader:pred = model(seq)mae = calculate_mae(pred.detach().cpu().numpy(),np.array(label.detach().cpu()))  # MAE误差计算绝对值(预测值  - 真实值)losss.append(mae)pred = pred[:, 0, :]label = label[:, 0, :]if args.feature == 'M' or args.feature == 'S':pred = scaler_train.inverse_transform(pred.detach().cpu().numpy())label = scaler_train.inverse_transform(label.detach().cpu().numpy())else:pred = scaler_pre.inverse_transform(pred.detach().cpu().numpy())label = scaler_pre.inverse_transform(label.detach().cpu().numpy())for i in range(len(pred)):results.append(pred[i][-1])labels.append(label[i][-1])print("测试集误差MAE:", losss)# 绘制历史数据plt.plot(labels, label='TrueValue')# 绘制预测数据# 注意这里预测数据的起始x坐标是历史数据的最后一个点的x坐标plt.plot(results, label='Prediction')# 添加标题和图例plt.title("test state")plt.legend()plt.show()# 检验模型拟合情况
def inspect_model_fit(model, args, train_loader, scaler_train):df = pd.read_csv(args.data_path)df_inverse = df[:int(0.85 * len(df))][[args.target]].reset_index(drop=True)scaler_pre = StandardScaler().fit(df_inverse)model = modelmodel.load_state_dict(torch.load('save_model.pth'))model.eval()  # 评估模式results = []labels = []for seq, label in train_loader:pred = model(seq)[:, 0, :]label = label[:, 0, :]if args.feature == 'M' or args.feature == 'S':pred = scaler_train.inverse_transform(pred.detach().cpu().numpy())label = scaler_train.inverse_transform(label.detach().cpu().numpy())else:pred = scaler_pre.inverse_transform(pred.detach().cpu().numpy())label = scaler_pre.inverse_transform(label.detach().cpu().numpy())for i in range(len(pred)):results.append(pred[i][-1])labels.append(label[i][-1])# 绘制历史数据plt.plot(labels, label='History')# 绘制预测数据# 注意这里预测数据的起始x坐标是历史数据的最后一个点的x坐标plt.plot(results, label='Prediction')# 添加标题和图例plt.title("inspect model fit state")plt.legend()plt.show()def predict(model, args, device, scaler):# 预测未知数据的功能df = pd.read_csv(args.data_path)scaler_data = df[[args.target]][int(0.3 * len(df)):]scaler_pre = StandardScaler().fit(scaler_data)df = df.iloc[:, 1:][-args.window_size:].values  # 转换为nadarrypre_data = scaler.transform(df)tensor_pred = torch.FloatTensor(pre_data).to(device)tensor_pred = tensor_pred.unsqueeze(0)   # 单次预测 , 滚动预测功能暂未开发后期补上model = modelmodel.load_state_dict(torch.load('save_model.pth'))model.eval()  # 评估模式pred = model(tensor_pred)[0]if args.feature == 'M' or args.feature == 'S':pred = scaler.inverse_transform(pred.detach().cpu().numpy())else:pred = scaler_pre.inverse_transform(pred.detach().cpu().numpy())# 假设 df 和 pred 是你的历史和预测数据# 计算历史数据的长度history_length = len(df[:, -1])# 为历史数据生成x轴坐标history_x = range(history_length)# 为预测数据生成x轴坐标# 开始于历史数据的最后一个点的x坐标prediction_x = range(history_length - 1, history_length + len(pred[:, -1]) - 1)# 绘制历史数据plt.plot(history_x, df[:, -1], label='History')# 绘制预测数据# 注意这里预测数据的起始x坐标是历史数据的最后一个点的x坐标plt.plot(prediction_x, pred[:, -1], label='Prediction')plt.axvline(history_length - 1, color='red')  # 在图像的x位置处画一条红色竖线# 添加标题和图例plt.title("History and Prediction")plt.legend()if __name__ == '__main__':parser = argparse.ArgumentParser(description='Time Series forecast')parser.add_argument('-model', type=str, default='TCN-LSTM', help="模型持续更新")parser.add_argument('-window_size', type=int, default=126, help="时间窗口大小, window_size > pre_len")parser.add_argument('-pre_len', type=int, default=24, help="预测未来数据长度")# dataparser.add_argument('-shuffle', action='store_true', default=True, help="是否打乱数据加载器中的数据顺序")parser.add_argument('-data_path', type=str, default='ETTh1-Test.csv', help="你的数据数据地址")parser.add_argument('-target', type=str, default='OT', help='你需要预测的特征列,这个值会最后保存在csv文件里')parser.add_argument('-input_size', type=int, default=7, help='你的特征个数不算时间那一列')parser.add_argument('-feature', type=str, default='M', help='[M, S, MS],多元预测多元,单元预测单元,多元预测单元')# learningparser.add_argument('-lr', type=float, default=0.001, help="学习率")parser.add_argument('-drop_out', type=float, default=0.05, help="随机丢弃概率,防止过拟合")parser.add_argument('-epochs', type=int, default=20, help="训练轮次")parser.add_argument('-batch_size', type=int, default=16, help="批次大小")parser.add_argument('-save_path', type=str, default='models')# modelparser.add_argument('-hidden_size', type=int, default=64, help="隐藏层单元数")parser.add_argument('-kernel_sizes', type=int, default=3)parser.add_argument('-laryer_num', type=int, default=2)# deviceparser.add_argument('-use_gpu', type=bool, default=True)parser.add_argument('-device', type=int, default=0, help="只设置最多支持单个gpu训练")# optionparser.add_argument('-train', type=bool, default=True)parser.add_argument('-test', type=bool, default=True)parser.add_argument('-predict', type=bool, default=True)parser.add_argument('-inspect_fit', type=bool, default=True)parser.add_argument('-lr-scheduler', type=bool, default=True)args = parser.parse_args()if isinstance(args.device, int) and args.use_gpu:device = torch.device("cuda:" + f'{args.device}')else:device = torch.device("cpu")print("使用设备:", device)train_loader, test_loader, valid_loader, scaler_train, scaler_test, scaler_valid = create_dataloader(args, device)if args.feature == 'MS' or args.feature == 'S':args.output_size = 1else:args.output_size = args.input_size# 实例化模型try:print(f">>>>>>>>>>>>>>>>>>>>>>>>>开始初始化{args.model}模型<<<<<<<<<<<<<<<<<<<<<<<<<<<")model = LSTM(args.input_size, args.output_size, args.pre_len, args.hidden_size , args.laryer_num, args.drop_out).to(device)print(f">>>>>>>>>>>>>>>>>>>>>>>>>开始初始化{args.model}模型成功<<<<<<<<<<<<<<<<<<<<<<<<<<<")except:print(f">>>>>>>>>>>>>>>>>>>>>>>>>开始初始化{args.model}模型失败<<<<<<<<<<<<<<<<<<<<<<<<<<<")# 训练模型if args.train:print(f">>>>>>>>>>>>>>>>>>>>>>>>>开始{args.model}模型训练<<<<<<<<<<<<<<<<<<<<<<<<<<<")train(model, args, device)if args.test:print(f">>>>>>>>>>>>>>>>>>>>>>>>>开始{args.model}模型测试<<<<<<<<<<<<<<<<<<<<<<<<<<<")test(model, args, scaler_test, test_loader)if args.inspect_fit:print(f">>>>>>>>>>>>>>>>>>>>>>>>>开始检验{args.model}模型拟合情况<<<<<<<<<<<<<<<<<<<<<<<<<<<")inspect_model_fit(model, args, train_loader, scaler_train)if args.predict:print(f">>>>>>>>>>>>>>>>>>>>>>>>>预测未来{args.pre_len}条数据<<<<<<<<<<<<<<<<<<<<<<<<<<<")predict(model, args, device, scaler_train)plt.show()


六、训练模型 

我们配置好所有参数之后就可以开始训练模型了,根据我前面讲解的参数部分进行配置,不懂得可以评论区留言。


七、预测结果

7.1 预测未知数据效果图

LSTM的预测效果图(这里我只预测了未来24个时间段的值为未来一天的预测值,个人觉得LSTM的极限就在20左右)->


7.2 测试集效果图 

测试集上的表现->

可以看出测试集上的表现还可以,毕竟只有一个LSTM没有加入任何其它的机制,LSTM作为最经典的时间序列预测模型效果还是可圈可点的。


7.3 CSV文件生成效果图 

同时我也可以将输出结果用csv文件保存,但是功能还没有做,我在另一篇informer的文章里实习了这个功能大家如果有需要可以评论区留言,有时间我会移植过来。

另一篇文章链接->时间序列预测实战(十九)魔改Informer模型进行滚动长期预测(科研版本,结果可视化)

将滚动预测结果生成了csv文件方便大家对比和评估,以下是我生成的csv文件可以说是非常的直观。

 我们可以利用其进行画图从而评估结果-> 


7.4 检验模型拟合效果图

检验模型拟合情况->

(从下面的图片可以看出模型拟合的情况很好) 


八、全文总结

 到此本文的正式分享内容就结束了,在这里给大家推荐我的时间序列专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的模型进行补充,目前本专栏免费阅读(暂时,大家尽早关注不迷路~)如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

 专栏回顾: 时间序列预测专栏——持续复习各种顶会内容——科研必备

如果大家有不懂的也可以评论区留言一些报错什么的大家可以讨论讨论看到我也会给大家解答如何解决!最后希望大家工作顺利学业有成!

相关文章:

时间序列预测实战(二十三)进阶版LSTM多元和单元预测(课程设计毕业设计首选)

一、本文介绍 本篇文章给大家带来的是利用我个人编写的架构进行LSTM模型进行时间序列建模&#xff08;专门为了时间序列领域新人编写的架构&#xff0c;简单且不同于市面上大家用GPT写的代码&#xff09;&#xff0c;包括结果可视化、支持单元预测、多元预测、模型拟合效果检测…...

Python之Appium 2自动化测试(Android篇)

一、环境搭建及准备工作 1、Appium 2 环境搭建 请参考另一篇文章: Windows系统搭建Appium 2 和 Appium Inspector 环境 2、安装 Appium-Python-Client&#xff0c;版本要求3.0及以上 pip install Appium-Python-ClientVersion: 3.1.03、手机连接电脑&#xff0c;并在dos窗口…...

chromium通信系统-ipcz系统(四)-ipcz-分层、和mojo的关系以及handle

在只有mojo的情况下&#xff0c; 进程间通信都是靠unix 域套接字来完成了&#xff0c;由于这种方式比较低效&#xff0c;并且不够灵活&#xff0c;后来引入了ipcz。 但是系统中基本上使用mojo做进程间通信&#xff0c;想要一步到位迁移到ipcz系统是比较困难的。 所以chrome团队…...

推荐一些研发人员经常用到的免费API接口

快递物流订阅与推送&#xff08;含物流轨迹&#xff09;&#xff1a;【物流订阅与推送、H5物流轨迹、单号识别】支持单号的订阅与推送&#xff0c;订阅国内物流信息&#xff0c;当信息有变化时&#xff0c;推送到您的回调地址。地图轨迹支持在地图中展示包裹运输轨迹。包括顺丰…...

高薪资是跳出来的,好工作是面出来的~

听人劝、吃饱饭,奉劝各位小伙伴,不要订阅该文所属专栏。 如需要项目实战或者是体系化资源,文末名片加V! 作者:哈哥撩编程,工作十余年, 从事过全栈研发、产品经理等工作,目前在公司担任研发部门CTO。荣誉:2022年度博客之星Top4、2023年度超级个体得主、谷歌与亚马逊开发…...

记QListWidget中QPushButton QSS样式失效的“bug”

一、场景 有一个QListWidget的列表&#xff1b;里面存放了若干QListWidgetItem&#xff1b;每个QListWidgetItem与一个自定义类对象绑定——通过QListWidget的setItemWidget()实现。自定义对象继承于QWidget&#xff0c;且内含QPushButton。 二、bug描述 在该QListWidget的外…...

python提取通话记录中的时间信息

您需要安装适合中文的SpaCy模型。您可以通过运行 pip install spacypython -m spacy download zh_core_web_sm来安装和下载所需的模型。 import spacy# 加载中文模型 nlp spacy.load(zh_core_web_sm)# 示例电话记录文本 text """ Agent: 今天我们解决一下这…...

DSShop移动商城网店系统 反序列化RCE漏洞复现

0x01 产品简介 DSShop是长沙德尚网络科技有限公司推出的一款单店铺移动商城网店系统,能够帮助企业和个人快速构建手机移动商城,并减少二次开发带来的成本。 以其丰富的营销功能,精细化的用户运营,解决电商引流、推广难题,帮助企业打造生态级B2C盈利模式商业平台。完备的电商…...

docker搭建node环境开发服务器

docker搭建node环境开发服务器 本文章是我自己搭建node环境开发服务器的过程记录&#xff0c;不一定完全适用所有人。根据个人情况&#xff0c;按需取用。 命名项目路径 为了方便cd到项目路径&#xff0c;将项目路径重命名&#xff0c;方便输入。 vim /etc/profile # 修改p…...

传统制造业企业如何实现数字化转型?

传统制造企业的数字化转型涉及利用数字技术来提高效率、生产力和整体业务流程。以下是实现制造业数字化转型的关键步骤和策略&#xff1a; 1.当前流程的评估&#xff1a; 确定可以从数字化转型中受益的领域。这可能包括生产流程、供应链管理、库存控制和客户关系。 评估技术集…...

面试:说一下深拷贝,浅拷贝,引用拷贝吧;Object类中的clone是哪种呢?

目录 深拷贝、浅拷贝、引用拷贝Object类的clone()方法 深拷贝、浅拷贝、引用拷贝 ● 浅拷贝&#xff1a; 对基本数据类型进行值传递&#xff1b; 对引用类型&#xff0c;复制了一份引用类型的变量 里面存储的内存地址一样 指向的对象也一样。 ● 深拷贝&#xff1a;对基本数据…...

接口压测指南

接口压测指南 一、 为什么需要进行接口压测二 、接口压测的目标是什么三、 用什么工具进行接口压测四、 接口压测核心指标4.1 JMeter的报告模板4.2 ApiPost报告模板 五、 接口慢如何排查5.1 大体排查思路5.2 排查工具5.3 压测经验 一、 为什么需要进行接口压测 突然有一天领导…...

计算机辅助药物设计AIDD-小分子-蛋白质|分子生成|蛋白质配体相互作用预测

文章目录 计算机辅助药物设计AIDD【小分子专题】AIDD概述及药物综合数据库学习机器学习辅助药物设计图神经网络辅助药物设计自然语言处理辅助药物设计药物设计与分子生成 计算机辅助药物设计【蛋白质专题】蛋白质数据结构激酶-Kinase相似性学习基于序列的蛋白质属性预测基于结构…...

深度学习-yolo目标检测-机器学习-计算机视觉-python学习路线(呕心沥血出品-绝对精品-附资源链接)

学习路线 1. 计算机视觉基础知识 图像处理基础:了解图像的基本处理技术,如滤波、边缘检测、直方图等。数字图像处理:熟悉数字图像的表示、颜色模型、图像增强等基本概念。opencv课程链接:Python for Computer Vision with OpenCV and Deep Learning资料推荐: 书籍:《数字…...

ubuntu2204 防火墙ufw限制某ip对某端口的访问

公司内部有个ip为10.10.10.1的网关&#xff0c;每天定时端口扫描&#xff0c;然后扫描发送的数据包http server解析不了&#xff0c;日志里就会记录这个错误&#xff0c;有点烦&#xff0c; 用防火墙过滤一下 ubuntu的防火墙命令是 ufw&#xff0c; 跟ufo挺像的&#xff0c;也…...

常见代码优化案例记录

1. 使用StringBuilder优化字符串拼接&#xff1a; // 不优化的写法 String result ""; for (int i 0; i < 1000; i) {result i; }// 优化的写法 StringBuilder resultBuilder new StringBuilder(); for (int i 0; i < 1000; i) {resultBuilder.append(i)…...

【android开发-04】android中activity的生命周期介绍

1&#xff0c;返回栈 android中使用任务task来管理activity&#xff0c;一个任务就是一组存放在栈里的活动的集合&#xff0c;这个栈被称为返回栈。栈是一种先进先出的数据结构。当我们启动一个新的活动&#xff0c;他会在返回栈中人栈&#xff0c;并处以栈顶的位置&#xff0…...

java后端技术演变杂谈(未完结)

1.0版本javaWeb&#xff1a;原始servletjspjsbc 早期的jsp&#xff1a;htmljava&#xff0c;页面先在后端被解析&#xff0c;里面的java代码动态渲染完成后&#xff0c;成为纯html&#xff0c;再通过服务器发送给浏览器显示。 缺点&#xff1a; 服务器压力很大&#xff0c;因为…...

UDS 诊断报文格式

文章目录 网络层目的N_PDU 格式诊断报文的分类&#xff1a;单帧、多帧 网络层目的 N_PDU(network protocol data unit)&#xff0c;即网络层协议数据单元 网络层最重要的目的就是把数据转换成符合标准的单一数据帧&#xff08;符合can总线规范的&#xff09;&#xff0c;从而…...

kafka的详细安装部署

introduce Kafka是一个分布式流处理平台&#xff0c;主要用于处理高吞吐量的实时数据流。Kafka最初由LinkedIn公司开发&#xff0c;现在由Apache Software Foundation维护和开发。 Kafka的核心是一个分布式发布-订阅消息系统&#xff0c;它可以处理大量的消息流&#xff0c;并…...

【数据分享】2015-2023年我国区县逐月二手房房价数据(Excel/Shp格式)

房价是一个城市发展程度的重要体现&#xff0c;一个城市的房价越高通常代表这个城市越发达&#xff0c;对于人口的吸引力越大&#xff01;因此&#xff0c;房价数据是我们在各项城市研究中都非常常用的数据&#xff01;之前我们分享过2015-2023年我国地级市逐月房价数据&#x…...

PTA 7-226 sdut-C语言实验-矩阵输出(数组移位)

输入N个整数&#xff0c;输出由这些整数组成的n行矩阵。 输入格式: 第一行输入一个正整数N&#xff08;N<20&#xff09;&#xff0c;表示后面要输入的整数个数。 下面依次输入N个整数。 输出格式: 以输入的整数为基础&#xff0c;输出有规律的N行数据。 输入样例: 在…...

Android 各平台推送通知栏点击处理方案

示例代码如下&#xff1a; RongPushClient.setPushEventListener( new PushEventListener() { Override public boolean preNotificationMessageArrived( Context context, PushType pushType, PushNotificationMessage notificationMessage) { //透传通知时&#xff0c;调用。…...

什么是网络安全 ?

网络安全已成为我们生活的数字时代最重要的话题之一。随着连接设备数量的增加、互联网的普及和在线数据的指数级增长&#xff0c;网络攻击的风险呈指数级增长。 但网络安全是什么意思&#xff1f; 简而言之&#xff0c;网络安全是一组旨在保护网络、设备和数据免受网络攻击、…...

【前端】-【electron】

文章目录 介绍electron工作流程环境搭建 electron生命周期&#xff08;app的生命周期&#xff09;窗口尺寸窗口标题自定义窗口的实现阻止窗口关闭父子及模态窗口自定义菜单 介绍 electron技术架构&#xff1a;chromium、node.js、native.apis electron工作流程 桌面应用就是…...

Python中的类(Class)和对象(Object)

目录 一、引言 二、类&#xff08;Class&#xff09; 1、类的定义 2、类的实例化 三、对象&#xff08;Object&#xff09; 1、对象的属性 2、对象的方法 四、类和对象的继承和多态性 1、继承 2、多态性 五、类与对象的封装性 1、封装的概念 2、Python中的封装实现…...

dp-拦截导弹2

所有代码均来自于acwing中的算法基础课和算法提高课 Description 某国为了防御敌国的导弹袭击&#xff0c;发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷&#xff1a;虽然它的第一发炮弹能够到达任意的高度&#xff0c; 但是以后每一发炮弹都不能高于前一发的高度。…...

初识动态规划算法(题目加解析)

文章目录 什么是动态规划正文力扣题第 N 个泰波那契数三步问题使用最小花费爬楼梯 总结 什么是动态规划 线性动态规划&#xff1a;是可以用一个dp表来存储内容&#xff0c;并且找到规律存储,按照规律存储。让第i个位置的值等于题目要求的答案 >dp表&#xff1a;dp表就是用一…...

Vue2.0与Vue3.0的区别

一、Vue2和Vue3的数据双向绑定原理发生了改变 Vue2的双向数据绑定是利用ES5的一个API&#xff0c;Object.definePropert()对数据进行劫持 结合 发布 订阅模式的方式来实现的。通过Object.defineProperty来劫持数据的setter&#xff0c;getter&#xff0c;在数据变动时发布消息…...

探索人工智能领域——每日20个名词详解【day6】

目录 前言 正文 总结 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Filotimo__✍️原创&#xff0c;首发于CSDN&#x1f4da;。 &#x1f4e3;如需转载&#xff0c;请事先与我联系以…...

卡盟做网站/可以下载新闻视频的网站

git 设置不需要输入密码, 去除 fetch / pull 代码每次都需要输入密码的烦恼https方式每次都要输入密码&#xff0c;按照如下设置即可输入一次就不用再手输入密码的困扰而且又享受https带来的极速设置记住密码(默认15分钟)&#xff1a;git config –global credential.helper ca…...

德州公司做网站/seo搜索引擎优化平台

计算机科学与技术学科为甘肃省省级重点学科&#xff0c;为硕士一级学科授权点&#xff0c;拥有国家级计算机实验教学示范中心、国家级交通信息类创新人才培养模式实验区。专业师资力量雄厚&#xff0c;2009年被授予国家级“计算机软件技术基础课程教学团队”。近年来承担科研项…...

做贸易怎么找客户/网站seo

Sqoop-1.4.6使用手册-v1.0-import部分安装使用Sqoop-1.4.6.jarJDBC包导入从RDB导入数据至HDFSOracleMySQL从RDB导入数据至HiveOracleMySQL导入全部表空值处理增量导入导入新数据导入更新数据导入数据表的子集保存上次导入的值增量导入总结密码保护压缩关于版本转载请注明出处&a…...

环境设计排版素材网站/百度网站怎样优化排名

转载自&#xff1a;http://www.cocoachina.com/gamedev/misc/2011/0627/2981.html 游戏一直是 App Store 应用里最热门、最赚钱的一大分类&#xff0c;iOS 游戏强调创意和趣味性的特点也让国内开发团队有更多一鸣惊人的机会。针对市场、玩家、开发商、成功案例等游戏开发要素&a…...

成品超市网站/seo排名查询软件

我们打开昨天已经创建好的项目myself.pro.注意保存的项目路径不能含有中文.接下来我们继续来学习,看如何进行可视化编程. 双点你的工程管理窗口中界面文件mainwindow.ui.双点后如图所示. 控件组窗口包含所有控件(控件就是一个叫法而已,例如按钮,文本框,标签等都被称为控件),使…...

国内做网站公司哪家好/抚顺网站seo

● 把电脑的第一启动项设为USB设备启动以往用光盘装系统&#xff0c;必须调整启动项为光驱启动&#xff0c;而现在我们要用U盘装系统&#xff0c;所以要调整为U盘启动。关于这个&#xff0c;不同电脑不同版本的bios有不同的设置方法&#xff0c;不过都大同小异&#xff0c;目的…...