时间序列预测实战(十七)PyTorch实现LSTM-GRU模型长期预测并可视化结果(附代码+数据集+详细讲解)

使用Pytorch从零开始构建GRU 门控循环单元(GRU),顾名思义,是RNN 架构的一种变体,它使用门控机制来控制和管理神经网络中单元之间的信息流。Cho 等人于 2014 年才引入 GRU。可以被认为是一种相对较新的架构,特别是与Sepp Hochreiter 和 Jürgen Schmidhuber于 1997 年提出的广泛采用的 LSTM 相比。GRU 的结构使其能够自适应地捕获大型数据序列的依赖性,而不会丢弃序列早期部分的信息。这是通过其门控单元实现的,类似于 LSTM 中的门控单元,它解决了传统 RNN 的梯度消失/爆炸问题。 阅读详情
AI摘要

本文从实战角度出发,利用PyTorch实现LSTM - GRU模型进行时间序列预测。介绍了LSTM和GRU的机制原理,包括LSTM的忘记门、输入门、输出门,GRU的更新门和重置门。以电力负荷数据集为例,给出模型完整代码,进行训练、预测并分析结果。

一、本文介绍

本文给大家带来的实战内容是利用PyTorch实现LSTM-GRU模型,LSTM和GRU都分别是RNN中最常用Cell之一,也都是时间序列预测中最常见的结构单元之一,本文的内容将会从实战的角度带你分析LSTM和GRU的机制和效果,同时如果你是时间序列中的新手,这篇文章会带你了解整个时间序列的建模过程,同时本文的实战代码支持多元预测单元、单元预测单元、多元预测多元,本文的实战内容通过时间序列领域最经典的数据集——电力负荷数据集为例进行预测。

内容回顾->时间序列预测专栏——包含上百种时间序列模型带你从入门到精通时间序列预测

预测类型->单元预测、多元预测、长期预测

下面是预测效果图-> 

目录

一、本文介绍

二、LSTM和GRU的机制原理

2.1LSTM的机制原理

2.2.1忘记门

2.2.2输入门

2.2.3输出门

2.2GRU的机制原理 

2.2.1GRU的基本原理

2.2.1GRU的基本框架

2.3 融合思想 

三、数据集介绍 

四、参数讲解 

五、模型实战 

5.1 模型完整代码

5.2 模型训练 

5.3 模型预测 

5.4 结果分析

六、全文总结


二、LSTM和GRU的机制原理

2.1LSTM的机制原理

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

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

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

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

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

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

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

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

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

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

2.2.1忘记门

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

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

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

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

2.2.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.2.3输出门

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

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

2.2GRU的机制原理 

2.2.1GRU的基本原理

GRU(门控循环单元)是一种循环神经网络(RNN)的变体,主要用于处理序列数据,它的基本原理可以概括如下:

  1. 门控机制:GRU的核心是门控机制,包括更新门(update gate)和重置门(reset gate)。这些门控制着信息的流动,即决定哪些信息应该被保留,哪些应该被遗忘。

  2. 更新门:更新门帮助模型决定过去的信息有多少需要保留到当前状态。它是通过当前输入和前一个隐状态计算得出的,用于调节隐状态的更新程度。

  3. 重置门:重置门决定了多少过去的信息需要被忘记。它同样依赖于当前输入和前一个隐状态的信息。当重置门接近0时,模型会“忘记”过去的隐状态,只依赖于当前输入。

  4. 当前隐状态的计算:利用更新门和重置门的输出,结合前一隐状态和当前输入,GRU计算出当前的隐状态。这个隐状态包含了序列到目前为止的重要信息。

  5. 输出:GRU的最终输出通常是在序列的每个时间步上产生的,或者在序列的最后一个时间步产生,取决于具体的应用场景。

总结:GRU相较于传统的RNN,其优势在于能够更有效地处理长序列数据,减轻了梯度消失的问题。同时,它通常比LSTM(长短期记忆网络)更简单,因为它有更少的参数。

2.2.1GRU的基本框架

​

上面的图片为一个GRU的基本结构图,解释如下->

  • 更新门(z) 在决定是否用新的隐藏状态更新当前隐藏状态时扮演重要角色。
  • 重置门(r) 决定是否忽略之前的隐藏状态。

这些部分是GRU的核心组成,它们共同决定了网络如何在序列数据中传递和更新信息,这对于时间序列分析至关重要。

2.3 融合思想 

三、数据集介绍 

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

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

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

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

​

四、参数讲解 

下面的代码是我定义的所有参数,目前只有这些,这个框架我会进行补充,后期也会在这里进行更新。 

 parser = argparse.ArgumentParser(description='Time Series forecast')
    parser.add_argument('-model', type=str, default='LSTM-Attention', help="模型持续更新")
    parser.add_argument('-window_size', type=int, default=128, help="时间窗口大小, window_size > pre_len")
    parser.add_argument('-pre_len', type=int, default=24, help="预测未来数据长度")
    # data
    parser.add_argument('-shuffle', action='store_true', default=True, help="是否打乱数据加载器中的数据顺序")
    parser.add_argument('-data_path', type=str, default='ETTh1Test.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('-output_size', type=int, default=7, help='输出特征个数只有两种选择和你的输入特征一样即输入多少输出多少,另一种就是多元预测单元')
    parser.add_argument('-feature', type=str, default='M', help='[M, S, MS],多元预测多元,单元预测单元,多元预测单元')
    # learning
    parser.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')

    # model
    parser.add_argument('-hidden-size', type=int, default=128, help="隐藏层单元数")
    parser.add_argument('-kernel-sizes', type=str, default='3')
    parser.add_argument('-laryer_num', type=int, default=1)
    # device
    parser.add_argument('-use_gpu', type=bool, default=False)
    parser.add_argument('-device', type=int, default=0, help="只设置最多支持单个gpu训练")

    # option
    parser.add_argument('-train', 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输入的特征数不包含时间那一列!!!
8output_sizeint输出的特征数只可以是1或者是等于你输入的特征数

9

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

11

drop_out

float丢弃概率
12epochsint训练轮次

13

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

15

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

17

layer_numintlstm层数
18use_gpubool是否使用GPU

19

deviceintGPU编号
20trainbool是否进行训练

21

predictbool是否进行预测

22

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

五、模型实战 

5.1 模型完整代码

下面是模型的暂时代码,后期会持续更新内容,以后的实战也会基于这个版本的框架下进行。 

我们将下面的代码创建一个py文件复制进去即可运行。 

import argparse
import numpy as np
import pandas as pd
import torch.nn as nn
from matplotlib import pyplot as plt
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from torch.utils.data import DataLoader
import torch
from torch.utils.data import Dataset
from tqdm import tqdm
import time
# 随机数种子
np.random.seed(1)

def plot_loss_data(data):
    # 使用Matplotlib绘制线图
    plt.figure()

    plt.plot(data)

    # 添加标题
    plt.title("loss results Plot")

    # 显示图例
    plt.legend(["Loss"])



class TimeSeriesDataset(Dataset):
    def __init__(self, sequences):
        self.sequences = sequences

    def __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):
            break
        if config.feature == 'MS' or config.feature == 'S':
            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_seq


def calculate_mae(y_true, y_pred):
    # 平均绝对误差
    mae = np.mean(np.abs(y_true - y_pred))
    return mae


def 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.series
    true_data = df_data.values

    # 定义标准化优化器
    scaler_train = StandardScaler()
    scaler_valid = StandardScaler()
    scaler_test = StandardScaler()

    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_train.fit_transform(train_data)
    test_data_normalized = scaler_test.fit_transform(test_data)
    valid_data_normalized = scaler_valid.fit_transform(valid_data)

    # 转化为深度学习模型需要的类型Tensor
    train_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)

    # 创建 DataLoader
    train_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_valid


class LSTM_GRU(nn.Module):
    def __init__(self, args, device):
        super(LSTM_GRU, self).__init__()
        self.args = args
        self.device = device
        self.dropout = nn.Dropout(args.drop_out)

        self.lstm = nn.LSTM(args.input_size, args.hidden_size, batch_first=True)
        self.gru = nn.GRU(input_size=args.hidden_size, hidden_size=args.hidden_size, num_layers=1, batch_first=True)
        self.linearOut = nn.Linear(args.hidden_size, args.input_size)

    def forward(self, x):
        hidden = ((torch.zeros(1, x.size(0), self.args.hidden_size).to(self.device)),
                  (torch.zeros(1, x.size(0), self.args.hidden_size).to(self.device)))
        x, lstm_h = self.lstm(x, hidden)
        x = self.dropout(x)
        x = torch.tanh(torch.transpose(x, 1, 2))
        x = x.permute(0, 2, 1)
        x, gru_ = self.gru(x)
        x = self.dropout(x)
        x = torch.tanh(torch.transpose(x, 1, 2))
        x = x.permute(0, 2, 1)
        x = self.linearOut(x)
        x = x[:, -args.pre_len:, :]

        return x


def train(model, args, device):
    start_time = time.time()  # 计算起始时间
    lstm_model = model
    loss_function = nn.MSELoss()
    optimizer = torch.optim.Adam(lstm_model.parameters(), lr=0.005)
    epochs = args.epochs
    lstm_model.train()  # 训练模式
    results_loss = []
    for i in tqdm(range(epochs)):
        losss = []
        for seq, labels in train_loader:
            optimizer.zero_grad()
            lstm_model.train()

            optimizer.zero_grad()

            y_pred = lstm_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(lstm_model.state_dict(), 'save_model.pth')
        time.sleep(0.1)

    # 保存模型

    print(f">>>>>>>>>>>>>>>>>>>>>>模型已保存,用时:{(time.time() - start_time) / 60:.4f} min<<<<<<<<<<<<<<<<<<")
    # plot_loss_data(results_loss)
    test(model, args, scaler_test, test_loader)

    return scaler_train


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().cpu().numpy(), np.array(labels.detach().cpu()))  # MAE误差计算绝对值(预测值  - 真实值)
        losss.append(mae)

    # print("验证集误差MAE:", losss)
    return sum(losss)/len(losss)

def test(model, args, scaler, test_loader):
    lstm_model = model
    # 加载模型进行预测
    lstm_model.load_state_dict(torch.load('save_model.pth'))
    lstm_model.eval()  # 评估模式
    losss = []

    for seq, labels in test_loader:
        pred = lstm_model(seq)
        mae = calculate_mae(pred.detach().cpu().numpy(), np.array(labels.detach().cpu()))  # MAE误差计算绝对值(预测值  - 真实值)
        losss.append(mae)
    # 此处缺少一个绘图功能后期补上,检验测试集情况
    print("测试集误差MAE:", losss)


# 检验模型拟合情况
def inspect_model_fit(model, args, train_loader, scaler_train):
    # 后期完善
    print("模型拟合检验情况暂未完善,如有需要请催更博主")
    pass


def predict(model, args, device, scaler):
    # 预测未知数据的功能
    # 重新读取数据
    df = pd.read_csv(args.data_path)
    train_data = df[[args.target]][int(0.3 * len(df)):]
    df = df.iloc[:, 1:][-args.window_size:].values  # 转换为nadarry
    scaler_tr = StandardScaler()
    scaler_tr.fit_transform(train_data.values)
    pre_data = scaler.transform(df)
    tensor_pred = torch.FloatTensor(pre_data).to(device)
    tensor_pred = tensor_pred.unsqueeze(0)   # 单次预测 , 滚动预测功能暂未开发后期补上
    model = model
    model.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_tr.inverse_transform(pred.detach().cpu().numpy())


    # 计算历史数据的长度
    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], marker='o', 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='LSTM-Attention', help="模型持续更新")
    parser.add_argument('-window_size', type=int, default=128, help="时间窗口大小, window_size > pre_len")
    parser.add_argument('-pre_len', type=int, default=24, help="预测未来数据长度")
    # data
    parser.add_argument('-shuffle', action='store_true', default=True, help="是否打乱数据加载器中的数据顺序")
    parser.add_argument('-data_path', type=str, default='ETTh1Test.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('-output_size', type=int, default=7, help='输出特征个数只有两种选择和你的输入特征一样即输入多少输出多少,另一种就是多元预测单元')
    parser.add_argument('-feature', type=str, default='M', help='[M, S, MS],多元预测多元,单元预测单元,多元预测单元')
    # learning
    parser.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')

    # model
    parser.add_argument('-hidden-size', type=int, default=128, help="隐藏层单元数")
    parser.add_argument('-kernel-sizes', type=str, default='3')
    parser.add_argument('-laryer_num', type=int, default=1)
    # device
    parser.add_argument('-use_gpu', type=bool, default=False)
    parser.add_argument('-device', type=int, default=0, help="只设置最多支持单个gpu训练")

    # option
    parser.add_argument('-train', 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)

    # 实例化模型
    try:
        print(f">>>>>>>>>>>>>>>>>>>>>>>>>开始初始化{args.model}模型<<<<<<<<<<<<<<<<<<<<<<<<<<<")
        model = LSTM_GRU(args, device).to(device)
        print(f">>>>>>>>>>>>>>>>>>>>>>>>>开始初始化{args.model}模型成功<<<<<<<<<<<<<<<<<<<<<<<<<<<")
    except:
        print(f">>>>>>>>>>>>>>>>>>>>>>>>>开始初始化{args.model}模型失败<<<<<<<<<<<<<<<<<<<<<<<<<<<")


    # 训练模型
    if args.train:
        print(f">>>>>>>>>>>>>>>>>>>>>>>>>开始{args.model}模型训练<<<<<<<<<<<<<<<<<<<<<<<<<<<")
        train(model, args, device)
    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()

 

5.2 模型训练 

当我们通过章节四配置好所有的参数之后,我们就可以运行我们创建的py文件了,控制台就会进行训练,输出如下内容->

5.3 模型预测 

下面的图片是模型在测试集上的表现, 可以看到效果还可以吧只能说一般,毕竟这两个结构单元只是最普通的,也没有在其中加入任何的其它高等级机制。

5.4 结果分析

当我们预测完成之后,会进行测试集验证同时会输出测试集的表现情况,后期我会添加个绘图功能在这里。 

六、全文总结

到此本文已经全部讲解完成了,希望能够帮助到大家,在这里也给大家推荐一些我其它的博客的时间序列实战案例讲解,其中有数据分析的讲解就是我前面提到的如何设置参数的分析博客,最后希望大家订阅我的专栏,本专栏均分文章均分98,并且免费阅读。

pytorch实现GRU(附code) 接上一篇文章(pytorch实现LSTM),在实现LSTM之后,又发现了GRU网络。 说GRU是LSTM网络的一种效果很好的变体,它较LSTM网络的结构更加简单,而且效果也很好,也是当前非常流形的一种网络。 所以决定尝试一下! 注:数据集仍然使用上文中的IGBT加速老化数据集,数据与处理方法不变,直接上代码!!! 在保证输入样本参数和学习率不变的情况下,即input_size = 5,out_oput = 1,lr = 0.01,试了很多参数,发现在训练集80%,测试集20%,hidden_size 阅读详情

相关推荐

机器学习正则化实战:从原理、调参到产线诊断

正则化是提升模型泛化能力的核心技术,本质是在偏差与方差之间进行动态权衡。它不仅包括L1/L2权重惩罚等显式方法,还涵盖Dropout、BatchNorm、早停法等隐式机制,其有效性取决于数据噪声特性、特征结构先验及业务目标容忍度。在工程实践中,正则强度λ并非超参数黑箱,而是需结合验证集loss曲率拐点、统计显著性或三阶扫描法精准定位的‘模型呼吸阀’。本文深入解析正则化的几何本质、优化器适配陷阱(如Adam中weight_decay≠L2)、GNN/Transformer等新架构下的定制策略,并提供产线级诊断

cuikuangru5755的博客 494

PyTorch nn.GRU 使用详解

我们看官方文档一些参数介绍,以及如下一个简单例子: 看完之后,还是一脸懵逼: 输入什么鬼? 输出又什么鬼? (这里我先把官网中 h0 去掉了,便于大家先理解更重要的概念) import torch from torch import nn rnn = nn.GRU(10, 20, 2) input = torch.randn(5, 3, 10) output, hn = rnn(input) 运行之后,各变量的shape如下: 要使用GRU这个layer,就要明白,要先定义GRU,然后才是调用这个定义

周迪新的博客 4万+

从代码学习深度学习 - GRU PyTorch版

在深度学习领域,循环神经网络(RNN)及其变种如GRU(Gated Recurrent Unit,门控循环单元)在处理序列数据时表现出色。相比传统RNN,GRU通过更新门(Update Gate)和重置门(Reset Gate)简化了结构,同时保持了对长期依赖关系的建模能力。本篇博客将通过PyTorch实现一个基于GRU的文本生成模型,结合《The Time Machine》数据集,逐步解析代码实现的全过程。从数据预处理到模型训练,再到结果可视化,我们将深入探讨每个模块的功能,并展示完整的代码实现。

weixin_43887510的博客 1262

深度学习笔记——pytorch实现双向GRU(BiGRU)

参考视频。

weixin_45978839的博客 4846

详解pytorch中循环神经网络(RNN、LSTM、GRU)的维度

首先如果你对不太熟悉,可点击查看。

NosONE 2592

GRU实现时间序列预测(PyTorch版)

本篇文章我们采用了经典的循环神经网络GRU来对我们的时序数据建模处理,作为该专栏的第一篇文章,本篇将详细介绍项目的每个实现部分以及细节处理,帮助新手小白快速建立起如何处理时序数据的框架。

优快云 精品推荐 6万+

时间序列预测实战(十五)PyTorch实现GRU模型长期预测并可视化结果

本文讲解的实战内容是GRU(门控循环单元),本文的实战内容通过时间序列领域最经典的数据集——电力负荷数据集为例,深入的了解GRU的基本原理和框架,下面是预测值和真实值的对比图先给大家放在前面。预测类型->单元预测、多元预测、长期预测门控机制:GRU的核心是门控机制,包括更新门(update gate)和重置门(reset gate)。这些门控制着信息的流动,即决定哪些信息应该被保留,哪些应该被遗忘。更新门:更新门帮助模型决定过去的信息有多少需要保留到当前状态。

Snu77的博客 1万+

【人工智能】【GPU芯片】第一篇 GPU算子——璧韧篇-02

璧韧GPU采用BR-Vision 3.0视觉处理架构,集成专用图像处理单元、计算机视觉加速器、神经网络视觉处理流水线。本列表包含2,048个图像与视觉算子,涵盖8种图像格式、12种颜色空间、16种滤波算法、24种特征检测方法。指令编码指令名称功能描述图像格式颜色空间内存分配应用场景BR_IMG_0001创建RGBA 8位图像RGBA8RGBA设备内存通用图像处理BR_IMG_0002创建RGB 8位图像RGB8RGB设备内存无Alpha通道BR_IMG_0003创建灰度8位图像L8灰度设备内存单通道处理BR

weixin_49199313的博客 836

【RNN从入门到实战】GRU入门到实战——使用GRU预测股票。

本实例数据集使用上证的收盘价,构建时序数据集,使用GRU对数据预测,从结果上来看,走势有一定的滞后性,由于只是用了价格预测价格,还是太简单了,可以考虑加入更多的特征去优化这一算法。

m0_47867638的博客 1316

【信息科学与工程学】【审计学】第一篇 招投标领域审计算法02

给定人、事、时、地、物等实体集合V和证据事实集合F, 构建一个概率图模型, 计算任意两个实体/事实之间存在关联关系的概率。:构建一个深度贝叶斯网络, 其中顶层为待推断的心理特征P, 中间层为可观测的行为模式B, 底层为多模态证据E。:基于现场痕迹、行为模式、通讯内容等证据E, 推断嫌疑人的心理特征向量P(如反社会性、冲动性、策划能力)。:对高风险的案件, 自动检索关联当事人、律师涉及的其他历史案件, 形成关联视图。:定义如“当事人-律师-当事人”、“当事人-多案件”等路径, 捕捉隐蔽关联。

weixin_49199313的博客 418

【信息科学与工程学】【通信工程】第十八篇 企业网、园区网、数据中心、广域网各类业务网络04

拓扑类型图模型节点数N边数E直径D对分带宽B正则性树形拓扑​无环连通图NN-12⌈log_k N⌉1非正则胖树(Fat-Tree)​三层Clos网络N=5k²/43k²/26k²/2近似正则蝶形网络​多级互连网络N=k·2^k(k+1)·2^k2log₂N2^{k-1}正则超立方体​n维立方体2^nn·2^{n-1}n2^{n-1}n-正则Torus/Mesh​m×n网格m·n2mn-m-nm+n-2min(m,n)内部4-正则DCell​递归结构N=∏_{i=0}^k n_i复杂O(log N)高非正则B

weixin_49199313的博客 796

PyTorch中利用LSTMCell搭建多层LSTM实现时间序列预测

PyTorch中利用LSTMCell搭建多层LSTM实现时间序列预测

KI的博客 8992

解决Cursor AI工具地域限制报错的方法与原理

地理围栏(GEO-fencing)是现代云服务常用的访问控制技术,通过IP地址库匹配、支付系统验证等方式实现区域限制。在AI编程工具领域,这种技术常导致类似Cursor出现的'unsupported country region'报错。从技术实现看,服务商会综合HTTP头信息、时区设置等多维度数据进行地理位置判断。开发者可通过调整网络出口、配置本地模型或使用企业版等方案解决。本文以Cursor为例,详细分析了AI工具地域限制的底层原理,并提供了包括Ollama本地部署在内的多种工程实践方案,特别适合需要稳定

weixin_30820077的博客 974

pytorch 笔记:GRU

在多层GRU中,第 l 层的输入(对于 l≥2)是前一层的隐藏状态乘以概率 dropout。

qq_40206371的博客 2402

VisualSFM+MeshLab 三维重建全过程记录

VisualSFM+MeshLab 三维重建全过程记录,从下载到运行出结果,以及其中一些可能出现的小问题。通过这两个软件熟悉一下多目立体视觉重建的流程。

何似莫相逢 3万+

win 11bitlocker恢复密匙一般情况的解决方式(这里指的是你现在使用的微软账户一直没有变更过)

本来没有打算写这一篇解决帖子的,但是最近好多微博的友友都在私我询问解决方法,孩子虽然很热心,但是真的回复不过来了,打字太累了,这里给大家简单指个路,希望能够对大家有所帮助。 当时出现这个问题的时候,一搜网上的解决方法都是重装系统什么的,真是吓死孩子啦。后来去微软的官网倒腾了半天解决了问题。其实只要你没有改过微软账户,你可以直接试试我这个方法,大概三到五分钟解决问题吧。 和我情况不一样的也可以参考一下贴吧里一些大佬的分享,或者实在着急我感觉去淘宝上找个解决也不是未尝不可。 出现问题: 解决方案: 直接去微软

zhiqingxue的博客 2万+

【PyTorch】torch.nn.GRU 类:门控循环单元

torch.nn.GRU是PyTorch中的一个模块,用于构建GRU层,支持单层或多层GRU堆叠,支持双向GRU。GRU(Gated Recurrent Unit)是RNN的改进版本,具有更新门和重置门,解决了传统RNN的梯度消失问题。参数:input_size、hidden_size、num_layers、batch_first、dropout等用于控制GRU的结构和行为。应用:GRU广泛用于序列建模、时间序列预测、自然语言处理等任务,特别适合长序列数据。

彬彬侠的博客 2166

GD32F4系列Keil工程模板搭建全攻略(手把手教学版)

本文提供了一份详细的GD32F4系列Keil工程模板搭建指南。从软件安装、固件库获取、目录规划,到Keil工程创建、文件添加、关键配置(如编译器选项、头文件路径、时钟设置),再到代码定制与常见问题排查,手把手教你构建一个标准化、模块化的开发基础。文章重点介绍了如何利用官方固件库和代码模板,快速建立稳定高效的开发环境,适用于GD32F407等Cortex-M4内核芯片的入门与项目开发。

weixin_29159995的博客 429

Pytorch快速入门

掌握深度学习框架PyTorch的基本语法熟练使用PyTorch进行数据处理掌握神经网络构建方法,构建各种网络架构图像分类项目实战

机器学习预测股票收益(一)之随机森林模型

机器学习预测股票收益(一)前言一、导入库和数据二、处理数据以及计算特征变量三、使用随机森林回归预测股票收益1.构建训练集和测试集2.查看预测结果四、根据预测结果构建long-short投资组合1.定义投资组合函数2.定义绩效分析函数五、引入Fama-French Factor六、投资组合表现1.超额收益表现2.多因子回归总结 前言 本文将使用Python整理1927-2020年所有美国上市公司股票数据。根据历史收益以及交易量,使用随机森林,支持向量机以及神经网络等机器学习方法预测股票收益。最优结果构建的资产

weixin_47174968的博客 1万+

2026华为OD机试 新系统真题题库目录|机考题库 + 算法考点详解

华为OD机试 新系统真题题库目录|机考题库 + 算法考点详解华为od机试,华为od机试真题,华为od机试E卷,华为odE卷,华为od机试真题E卷,华为OD,华为OD机试,华为OD机试真题,华为od机考,华为od机试D卷,华为od机试真题D卷,华为od手撕代码,华为od,华为od机试C卷,华为od e卷,华为2026e卷,od机试,2026E卷,华为OD机试E卷,什么是华为od,华为od介绍,全面了解华为od,2026华为od,如何备战华为od,华为od算法,华为od手撕代码,华为OD机试2024年最新题库,

KJ.JK 4720

Pytorch之经典神经网络RNN(二) —— GRU()

GRU,Gate Recurrent Unit,是循环神经网络RNN的一种。 和LSTM一样,也是为了解决长期记忆和反向传播中的梯度等问题而提出来的。 GRU和LSTM在很多情况下实际表现上相差无几,那么为什么我们要使用新人GRU(2014年提出)而不是相对经受了更多考验的LSTM(1997提出)呢? 我们在我们的实验中选择GRU是因为它的实验效果与LSTM相似,但是更易于计算。 相比LSTM,使用GRU能够达到相当的效果,并且相比之下更容易进行训练...

hxxjxw的博客 2355

万字详解 PostgreSQL 的详细安装方式(Linux、Windows、macOS、Docker 全平台覆盖)

本文详细介绍了PostgreSQL在四大主流环境下的安装方法: Linux系统:针对Ubuntu/Debian和CentOS/RHEL系,分别提供APT/YUM仓库安装步骤,包括初始化配置和服务管理 Windows系统:通过图形化安装程序指导完成安装,包含组件选择、密码设置和pgAdmin配置 macOS系统:推荐使用Homebrew一键安装,支持Apple Silicon和Intel芯片 Docker容器:提供容器化部署方案(文中未展开) 文章强调安装前的版本选择、权限管理和存储规划,并针对各平台给出验证

数据知道的博客 4506

PyTorch搭建LSTM实现多变量输入多变量输出时间序列预测(多任务学习)

PyTorch搭建LSTM实现多变量输入多变量输出时间序列预测

KI的博客 3万+

pt100和max31865测室温跳变比较大,会从23.04跳到23.47,23.75反复跳变超过了0.5的误差范围,在VDD和GND之间加上0.1和10的滤波电容也不行,如何解决?

🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各类Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验总结所得,数条可行方案供所需之人参考。

**My Coding Family** 2087

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

神经网络时间序列预测PyTorch-Forecastin!

来源:数据STUDIO 深度学习初学者 本文约5200字,建议阅读8分钟 本文为你介绍了神经网络时间序列预测PyTorch-Forecastin。PyTorch-Forecasting[1]使用神经网络的时间序列预测对数据科学工作者和研究人员来说都很简单。为什么准确的预测如此重要?预测时间序列在很多情况下都很重要,与机器学习从业者高度相关。以需求预测为例,许多用例都源于此。几乎每个制造商都会从更好...

数据派THU 1987

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

上一篇: 时间序列预测实战(十八)利用Prophet实现长期预测(附代码+数据集+详细讲解)
下一篇: 时间序列中的6大类10种异常值处理方法(从根源上提高预测精度)
Snu77
Snu77 优质创作者: 人工智能技术领域 优质创作者: 人工智能技术领域
博客等级 码龄5年 11万+粉丝 934原创
评论 52
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Snu77

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值