南江网站建设,网站建设百度知道,河南郑州房价,做企业宣传网站一、本文介绍
本文给大家带来的时间序列模型是Seq2Seq#xff0c;这个概念相信大家都不陌生了#xff0c;网上的讲解已经满天飞了#xff0c;但是本文给大家带来的是我在Seq2Seq思想上开发的一个模型和新的架构#xff0c;架构前面的文章已经说过很多次了#xff0c;其是…一、本文介绍
本文给大家带来的时间序列模型是Seq2Seq这个概念相信大家都不陌生了网上的讲解已经满天飞了但是本文给大家带来的是我在Seq2Seq思想上开发的一个模型和新的架构架构前面的文章已经说过很多次了其是专门为新手开发的而且为了方便大家使用只定义了一个文件方便大家复制粘贴架构功能包括结果可视化、支持单元预测、多元预测、模型拟合效果检测、预测未知数据、以及滚动长期预测功能。Seq2Seq模型是一种处理序列数据的深度学习模型广泛用于机器翻译、语音识别和文本摘要等任务(也能用于时间序列)。其核心思想是编码器-解码器。
需要注意得是本文的模型和结构均为自研在Seq2Seq的思想上进行了一定的扩展。 专栏目录时间序列预测目录深度学习、机器学习、融合模型、创新模型实战案例 专栏 时间序列预测专栏基础知识数据分析机器学习深度学习Transformer创新模型 预测功能效果展示(不是测试集是预测未知数据所以图中没有对比的数据)- 损失截图(损失这里我先展示一个训练过程中的后面会自动生成损失图像)-
根据损失来看模型的拟合效果还是很好的但后面还是做了检验模型拟合效果的功能让大家真正的评估模型的效果。
测试集状况-
这个结构是我发这么多基础模型里效果最好的模型拟合和测试集表现均为最好。 目录
一、本文介绍
二、Seq2Seq思想原理
2.1 Seq2Seq的基本原理
2.1.1 编码器-解码器介绍
2.1.2 编码器-解码器结构图
三、数据集介绍
四、参数讲解
五、完整代码
六、训练模型
七、预测结果
7.1 预测未知数据效果图
7.2 测试集效果图
7.3 CSV文件生成效果图
7.4 检验模型拟合效果图
八、全文总结 二、Seq2Seq思想原理 2.1 Seq2Seq的基本原理
Seq2SeqSequence-to-Sequence模型是一种处理序列数据的深度学习模型广泛用于机器翻译、语音识别和文本摘要等任务。其核心思想是将一个序列如一句话转换成另一个序列这两个序列的长度可以不同。
Seq2Seq模型主要包括以下几个机制和原理
1. 编码器-解码器架构Seq2Seq模型通常由两部分组成编码器和解码器。编码器负责读取并理解输入序列将其转换成一个固定长度的上下文向量context vector。解码器则利用这个上下文向量生成目标序列其实最核心的就是这个下面都是具体的应用了。
2. 循环神经网络RNN在传统的Seq2Seq模型中编码器和解码器通常是循环神经网络如LSTM或GRU。RNN可以处理不同长度的输入序列并在其隐藏层保持序列的状态信息。
3.注意力机制Attention注意力机制是后来引入Seq2Seq模型的一项重要改进。它允许模型在生成每个目标词时“关注”输入序列的不同部分从而提高了模型处理长句子时的效果和准确性。
4. 长短期记忆网络LSTM/门控循环单元GRU为了解决RNN中的长期依赖问题LSTM和GRU这样的网络结构被引入。它们能更好地捕捉序列中的长期依赖关系。 个人总结我个人觉得Seq2Seq模型就像是学习语言的人。首先通过“编码器”理解输入的句子然后用“解码器”来表达新的句子。就像我们学外语时先理解一句话的意思再用自己的语言表达出来。加上“注意力机制”模型还能更聪明地关注输入句子中最重要的部分就好比我们在听别人说话时会注意对方重点强调的内容。 2.1.1 编码器-解码器介绍
通过上面我们知道Seq2Seq的主要核心思想是编码器和解码器Seq2Seq一开始被发明出来是用于一些本文处理的但是本文是时间序列领域的文章所以我主要讲解一下编码器-解码器在时间序列领域的应用大家需要注意的是这里的编码器和解码器和Transformer当中的还不一样是有着根本的区别的。Seq2Seq模型的编码器和解码器如下工作
编码器在时间序列领域的作用是理解和编码输入序列的历史数据。 1. 处理时间序列输入编码器接收时间序列数据例如过去几天的股票价格或气温记录。这些数据通常是连续的数值。 2. 特征提取通过RNN(本文是用的GRU类似于LSTM和RNN以后也会单独出文章)网络编码器可以捕捉时间序列的特征和内在模式。RNN通过其时间递归结构有效地处理时间序列数据中的时序依赖关系。 3. 上下文向量编码器输出一个上下文向量该向量是输入时间序列的压缩表示包含了对过去数据的理解和总结。 解码器在时间序列领域的作用是基于编码器提供的信息来预测未来的时间序列数据。 1. 初始状态和输入解码器的初始状态通常由编码器的最终状态设置。解码器的第一个输入可能是序列的最后一个观测值或特殊标记我设置为解码器的输入是编码器的最后一个输出因为我觉得这个状态的过去信息是最足的。 2. 逐步预测在每个时间步解码器基于当前状态和前一步的预测输出或初始输入来生成下一个时间点的预测值。 3. 迭代更新解码器的输出用于更新其状态并作为下一个时间步的输入。这个过程在生成整个预测序列期间重复进行。 4. 序列生成这个过程持续进行直到生成了预定长度的预测序列。 总结在时间序列领域Seq2Seq模型的编码器-解码器结构使其能够有效处理具有复杂时间依赖性的序列数据。编码器学习并压缩历史数据的关键信息而解码器则利用这些信息来预测未来的趋势和模式。 2.1.2 编码器-解码器结构图
下面的图是我编码器-解码器的结构图其中包含了编码器Encoder和解码器Decoder的具体实现细节需要注意的是这个图和本文模型无关这里举出来只是为了让大家对编码器和解码器的流程有一个更清晰的认知。下面是对这个图示的详细解释 编码器部分左侧 嵌入层Embed这个层将输入的一热编码one-hot vector转换为嵌入向量。在此图中嵌入层将每个输入token转换为一个256维的向量。 GRU层门控循环单元Gated Recurrent UnitGRU是RNN的一种变体可以捕捉长期依赖关系同时缓解了传统RNN的梯度消失问题。在此模型中每个时间步的GRU层接收前一时间步的隐藏状态和当前时间步的嵌入向量然后输出新的隐藏状态。 时间步t时间步是序列中的位置指示从t−2开始直至t0表示输入序列的处理进程。 位置标记Pos. T这可能表示当前处理的token位于输入序列的最后一个位置意味着编码器即将完成对输入序列的处理。
解码器部分右侧 嵌入层解码器的嵌入层将一热编码的输出token转换为嵌入向量。 GRU层解码器的GRU层接收来自上一时间步的隐藏状态和当前时间步的嵌入向量或初始状态从编码器传来的上下文向量然后输出新的隐藏状态。 全连接层在每个时间步全连接层将GRU的输出转换为词汇表大小的向量这个向量包含了输出序列中下一个token的概率分布。 输出概率这是解码器产生的表示下一个可能输出token的概率分布。 SOS这是“Start of Sequence”的缩写表示解码器开始生成序列的信号。 时间步t在解码器部分时间步从t1开始直至tT1其中T可能表示目标序列的长度。 整个过程是这样的编码器读取输入序列的token并逐个更新其隐藏状态。当编码器读取完所有的输入token后最后的隐藏状态ℎ0被传递到解码器作为其初始状态。解码器从一个特殊的SOS token开始逐步生成输出序列的token。在每一步解码器基于当前的隐藏状态和上一步产生的token预测下一个token直到生成EOS token表示序列生成结束。 概念部分的就讲这么多网上有很多概念理解的好博客大家有兴趣都可以自己查找看看本文是实战博客内容不多讲啦~ 三、数据集介绍
本文是实战讲解文章上面主要是简单讲解了一下网络结构比较具体的流程还是很复杂的涉及到很多的数学计算下面我们来讲一讲模型的实战内容第一部分是我利用的数据集。
本文我们用到的数据集是ETTh1.csv该数据集是一个用于时间序列预测的电力负荷数据集它是 ETTh 数据集系列中的一个。ETTh 数据集系列通常用于测试和评估时间序列预测模型。以下是 ETTh1.csv 数据集的一些内容
数据内容该数据集通常包含有关电力系统的多种变量如电力负荷、价格、天气情况等。这些变量可以用于预测未来的电力需求或价格。
时间范围和分辨率数据通常按小时或天记录涵盖了数月或数年的时间跨度。具体的时间范围和分辨率可能会根据数据集的版本而异。
以下是该数据集的部分截图- 四、参数讲解
parser.add_argument(-model, typestr, defaultRNN, help模型持续更新)parser.add_argument(-window_size, typeint, default126, help时间窗口大小, window_size pre_len)parser.add_argument(-pre_len, typeint, default24, help预测未来数据长度)# dataparser.add_argument(-shuffle, actionstore_true, defaultTrue, help是否打乱数据加载器中的数据顺序)parser.add_argument(-data_path, typestr, defaultETTh1-Test.csv, help你的数据数据地址)parser.add_argument(-target, typestr, defaultOT, help你需要预测的特征列这个值会最后保存在csv文件里)parser.add_argument(-input_size, typeint, default7, help你的特征个数不算时间那一列)parser.add_argument(-feature, typestr, defaultM, help[M, S, MS],多元预测多元,单元预测单元,多元预测单元)# learningparser.add_argument(-lr, typefloat, default0.001, help学习率)parser.add_argument(-drop_out, typefloat, default0.05, help随机丢弃概率,防止过拟合)parser.add_argument(-epochs, typeint, default20, help训练轮次)parser.add_argument(-batch_size, typeint, default16, help批次大小)parser.add_argument(-save_path, typestr, defaultmodels)# modelparser.add_argument(-hidden_size, typeint, default64, help隐藏层单元数)parser.add_argument(-kernel_sizes, typeint, default3)parser.add_argument(-laryer_num, typeint, default2)# deviceparser.add_argument(-use_gpu, typebool, defaultTrue)parser.add_argument(-device, typeint, default0, help只设置最多支持单个gpu训练)# optionparser.add_argument(-train, typebool, defaultTrue)parser.add_argument(-test, typebool, defaultTrue)parser.add_argument(-predict, typebool, defaultTrue)parser.add_argument(-inspect_fit, typebool, defaultTrue)parser.add_argument(-lr-scheduler, typebool, defaultTrue)
为了大家方便理解文章中的参数设置我都用的中文所以大家应该能够更好的理解。下面我在进行一遍讲解。
参数名称参数类型参数讲解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
import torch
import torch.nn as nn
from matplotlib import pyplot as plt
from torch.utils.data import DataLoader
from torch.utils.data import Dataset
from tqdm import tqdm
import torch.nn.functional as F# 随机数种子
np.random.seed(0)class StandardScaler():def __init__(self):self.mean 0.self.std 1.def fit(self, data):self.mean data.mean(0)self.std data.std(0)def transform(self, data):mean torch.from_numpy(self.mean).type_as(data).to(data.device) if torch.is_tensor(data) else self.meanstd torch.from_numpy(self.std).type_as(data).to(data.device) if torch.is_tensor(data) else self.stdreturn (data - mean) / stddef inverse_transform(self, data):mean torch.from_numpy(self.mean).type_as(data).to(data.device) if torch.is_tensor(data) else self.meanstd torch.from_numpy(self.std).type_as(data).to(data.device) if torch.is_tensor(data) else self.stdif data.shape[-1] ! mean.shape[-1]:mean mean[-1:]std std[-1:]return (data * std) meandef plot_loss_data(data):# 使用Matplotlib绘制线图plt.figure()plt.figure(figsize(10, 5))plt.plot(data, markero)# 添加标题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, axis1)df pd.concat((df, target_data), axis1)cols_data df.columns[1:]df_data df[cols_data]# 这里加一些数据的预处理, 最后需要的格式是pd.seriestrue_data df_data.values# 定义标准化优化器scaler StandardScaler()scaler.fit(true_data)train_data true_data[int(0.3 * len(true_data)):]valid_data true_data[int(0.15 * len(true_data)):int(0.30 * len(true_data))]test_data true_data[:int(0.15 * len(true_data))]print(训练集尺寸:, len(train_data), 测试集尺寸:, len(test_data), 验证集尺寸:, len(valid_data))# 进行标准化处理train_data_normalized scaler.transform(train_data)test_data_normalized scaler.transform(test_data)valid_data_normalized scaler.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_sizeargs.batch_size, shuffleTrue, drop_lastTrue)test_loader DataLoader(test_dataset, batch_sizeargs.batch_size, shuffleFalse, drop_lastTrue)valid_loader DataLoader(valid_dataset, batch_sizeargs.batch_size, shuffleFalse, drop_lastTrue)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, scalerclass RNNEncoder(nn.Module):def __init__(self, rnn_num_layers1, input_feature_len1, sequence_len168, hidden_size100, bidirectionalFalse):super().__init__()self.sequence_len sequence_lenself.hidden_size hidden_sizeself.input_feature_len input_feature_lenself.num_layers rnn_num_layersself.rnn_directions 2 if bidirectional else 1self.gru nn.GRU(num_layersrnn_num_layers,input_sizeinput_feature_len,hidden_sizehidden_size,batch_firstTrue,bidirectionalbidirectional)def forward(self, input_seq):ht torch.zeros(self.num_layers * self.rnn_directions, input_seq.size(0), self.hidden_size, devicecuda)if input_seq.ndim 3:input_seq.unsqueeze_(2)gru_out, hidden self.gru(input_seq, ht)if self.rnn_directions 1:gru_out gru_out.view(input_seq.size(0), self.sequence_len, self.rnn_directions, self.hidden_size)gru_out torch.sum(gru_out, axis2)return gru_out, hidden.squeeze(0)class AttentionDecoderCell(nn.Module):def __init__(self, input_feature_len, out_put, sequence_len, hidden_size):super().__init__()# attention - inputs - (decoder_inputs, prev_hidden)self.attention_linear nn.Linear(hidden_size input_feature_len, sequence_len)# attention_combine - inputs - (decoder_inputs, attention * encoder_outputs)self.decoder_rnn_cell nn.GRUCell(input_sizehidden_size,hidden_sizehidden_size,)self.out nn.Linear(hidden_size, input_feature_len)def forward(self, encoder_output, prev_hidden, y):if prev_hidden.ndimension() 3:prev_hidden prev_hidden[-1] # 保留最后一层的信息attention_input torch.cat((prev_hidden, y), axis1)attention_weights F.softmax(self.attention_linear(attention_input), dim-1).unsqueeze(1)attention_combine torch.bmm(attention_weights, encoder_output).squeeze(1)rnn_hidden self.decoder_rnn_cell(attention_combine, prev_hidden)output self.out(rnn_hidden)return output, rnn_hiddenclass EncoderDecoderWrapper(nn.Module):def __init__(self, input_size, output_size, hidden_size, num_layers, pred_len, window_size, teacher_forcing0.3):super().__init__()self.encoder RNNEncoder(num_layers, input_size, window_size, hidden_size)self.decoder_cell AttentionDecoderCell(input_size, output_size, window_size, hidden_size)self.output_size output_sizeself.input_size input_sizeself.pred_len pred_lenself.teacher_forcing teacher_forcingself.linear nn.Linear(input_size,output_size)def __call__(self, xb, ybNone):input_seq xbencoder_output, encoder_hidden self.encoder(input_seq)prev_hidden encoder_hiddenif torch.cuda.is_available():outputs torch.zeros(self.pred_len, input_seq.size(0), self.input_size, devicecuda)else:outputs torch.zeros(input_seq.size(0), self.output_size)y_prev input_seq[:, -1, :]for i in range(self.pred_len):if (yb is not None) and (i 0) and (torch.rand(1) self.teacher_forcing):y_prev yb[:, i].unsqueeze(1)rnn_output, prev_hidden self.decoder_cell(encoder_output, prev_hidden, y_prev)y_prev rnn_outputoutputs[i, :, :] rnn_outputoutputs outputs.permute(1, 0, 2)if self.output_size 1:outputs self.linear(outputs)return outputsdef train(model, args, scaler, device):start_time time.time() # 计算起始时间model modelloss_function nn.MSELoss()optimizer torch.optim.Adam(model.parameters(), lr0.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))torch.save(model.state_dict(), save_model.pth)time.sleep(0.1)# valid_loss valid(model, args, scaler, valid_loader)# 尚未引入学习率计划后期补上# 保存模型print(f模型已保存,用时:{(time.time() - start_time) / 60:.4f} min)plot_loss_data(results_loss)def 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, test_loader, scaler):# 加载模型进行预测losss []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, :]pred scaler.inverse_transform(pred.detach().cpu().numpy())label scaler.inverse_transform(label.detach().cpu().numpy())for i in range(len(pred)):results.append(pred[i][-1])labels.append(label[i][-1])plt.figure(figsize(10, 5))print(测试集误差MAE:, losss)# 绘制历史数据plt.plot(labels, labelTrueValue)# 绘制预测数据# 注意这里预测数据的起始x坐标是历史数据的最后一个点的x坐标plt.plot(results, labelPrediction)# 添加标题和图例plt.title(test state)plt.legend()plt.show()# 检验模型拟合情况
def inspect_model_fit(model, args, train_loader, scaler):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, :]pred scaler.inverse_transform(pred.detach().cpu().numpy())label scaler.inverse_transform(label.detach().cpu().numpy())for i in range(len(pred)):results.append(pred[i][-1])labels.append(label[i][-1])plt.figure(figsize(10, 5))# 绘制历史数据plt.plot(labels, labelHistory)# 绘制预测数据# 注意这里预测数据的起始x坐标是历史数据的最后一个点的x坐标plt.plot(results, labelPrediction)# 添加标题和图例plt.title(inspect model fit state)plt.legend()plt.show()def predict(model, args, device, scaler):# 预测未知数据的功能df pd.read_csv(args.data_path)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]pred scaler.inverse_transform(pred.detach().cpu().numpy())# 假设 df 和 pred 是你的历史和预测数据# 计算历史数据的长度history_length len(df[:, -1])# 为历史数据生成x轴坐标history_x range(history_length)plt.figure(figsize(10, 5))# 为预测数据生成x轴坐标# 开始于历史数据的最后一个点的x坐标prediction_x range(history_length - 1, history_length len(pred[:, -1]) - 1)# 绘制历史数据plt.plot(history_x, df[:, -1], labelHistory)# 绘制预测数据# 注意这里预测数据的起始x坐标是历史数据的最后一个点的x坐标plt.plot(prediction_x, pred[:, -1], markero, labelPrediction)plt.axvline(history_length - 1, colorred) # 在图像的x位置处画一条红色竖线# 添加标题和图例plt.title(History and Prediction)plt.legend()if __name__ __main__:parser argparse.ArgumentParser(descriptionTime Series forecast)parser.add_argument(-model, typestr, defaultRNN, help模型持续更新)parser.add_argument(-window_size, typeint, default126, help时间窗口大小, window_size pre_len)parser.add_argument(-pre_len, typeint, default24, help预测未来数据长度)# dataparser.add_argument(-shuffle, actionstore_true, defaultTrue, help是否打乱数据加载器中的数据顺序)parser.add_argument(-data_path, typestr, defaultETTh1-Test.csv, help你的数据数据地址)parser.add_argument(-target, typestr, defaultOT, help你需要预测的特征列这个值会最后保存在csv文件里)parser.add_argument(-input_size, typeint, default7, help你的特征个数不算时间那一列)parser.add_argument(-feature, typestr, defaultM, help[M, S, MS],多元预测多元,单元预测单元,多元预测单元)# learningparser.add_argument(-lr, typefloat, default0.001, help学习率)parser.add_argument(-drop_out, typefloat, default0.05, help随机丢弃概率,防止过拟合)parser.add_argument(-epochs, typeint, default20, help训练轮次)parser.add_argument(-batch_size, typeint, default16, help批次大小)parser.add_argument(-save_path, typestr, defaultmodels)# modelparser.add_argument(-hidden_size, typeint, default128, help隐藏层单元数)parser.add_argument(-laryer_num, typeint, default1)# deviceparser.add_argument(-use_gpu, typebool, defaultTrue)parser.add_argument(-device, typeint, default0, help只设置最多支持单个gpu训练)# optionparser.add_argument(-train, typebool, defaultTrue)parser.add_argument(-test, typebool, defaultTrue)parser.add_argument(-predict, typebool, defaultTrue)parser.add_argument(-inspect_fit, typebool, defaultTrue)parser.add_argument(-lr-scheduler, typebool, defaultTrue)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 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 EncoderDecoderWrapper(args.input_size, args.output_size, args.hidden_size, args.laryer_num, args.pre_len, args.window_size).to(device)print(f开始初始化{args.model}模型成功)except:print(f开始初始化{args.model}模型失败)# 训练模型if args.train:print(f开始{args.model}模型训练)train(model, args, scaler, device)if args.test:print(f开始{args.model}模型测试)test(model, args, test_loader, scaler)if args.inspect_fit:print(f开始检验{args.model}模型拟合情况)inspect_model_fit(model, args, train_loader, scaler)if args.predict:print(f预测未来{args.pre_len}条数据)predict(model, args, device, scaler)plt.show()六、训练模型
我们配置好所有参数之后就可以开始训练模型了根据我前面讲解的参数部分进行配置不懂得可以评论区留言。 七、预测结果
7.1 预测未知数据效果图
Seq2Seq(GRU)的预测效果图(这里我只预测了未来24个时间段的值为未来一天的预测值)- 7.2 测试集效果图
测试集上的表现- 7.3 CSV文件生成效果图
同时我也可以将输出结果用csv文件保存但是功能还没有做我在另一篇informer的文章里实习了这个功能大家如果有需要可以评论区留言有时间我会移植过来最近一直在搞图像领域的文章因为时间序列看的人还是太少了。
另一篇文章链接-时间序列预测实战(十九)魔改Informer模型进行滚动长期预测科研版本结果可视化 将滚动预测结果生成了csv文件方便大家对比和评估以下是我生成的csv文件可以说是非常的直观。 我们可以利用其进行画图从而评估结果- 7.4 检验模型拟合效果图
检验模型拟合情况-
(从下面的图片可以看出模型拟合的情况还行上一篇RNN的有一点过拟合了其实则会个表现还是很正常的) 八、全文总结
到此本文的正式分享内容就结束了在这里给大家推荐我的时间序列专栏本专栏目前为新开的平均质量分98分后期我会根据各种最新的前沿顶会进行论文复现也会对一些老的模型进行补充目前本专栏免费阅读(暂时大家尽早关注不迷路~)如果大家觉得本文帮助到你了订阅本专栏关注后续更多的更新~ 专栏回顾 时间序列预测专栏——持续复习各种顶会内容——科研必备 如果大家有不懂的也可以评论区留言一些报错什么的大家可以讨论讨论看到我也会给大家解答如何解决最后希望大家工作顺利学业有成