PyTorch搭建LSTM实现时间序列预测(负荷预测)

2023-11-06

I. 前言

在上一篇文章深入理解PyTorch中LSTM的输入和输出(从input输入到Linear输出)中,我详细地解释了如何利用PyTorch来搭建一个LSTM模型,本篇文章的主要目的是搭建一个LSTM模型用于时间序列预测。

系列文章:

  1. 深入理解PyTorch中LSTM的输入和输出(从input输入到Linear输出)
  2. PyTorch搭建LSTM实现时间序列预测(负荷预测)
  3. PyTorch中利用LSTMCell搭建多层LSTM实现时间序列预测
  4. PyTorch搭建LSTM实现多变量时间序列预测(负荷预测)
  5. PyTorch搭建双向LSTM实现时间序列预测(负荷预测)
  6. PyTorch搭建LSTM实现多变量多步长时间序列预测(一):直接多输出
  7. PyTorch搭建LSTM实现多变量多步长时间序列预测(二):单步滚动预测
  8. PyTorch搭建LSTM实现多变量多步长时间序列预测(三):多模型单步预测
  9. PyTorch搭建LSTM实现多变量多步长时间序列预测(四):多模型滚动预测
  10. PyTorch搭建LSTM实现多变量多步长时间序列预测(五):seq2seq
  11. PyTorch中实现LSTM多步长时间序列预测的几种方法总结(负荷预测)
  12. PyTorch-LSTM时间序列预测中如何预测真正的未来值
  13. PyTorch搭建LSTM实现多变量输入多变量输出时间序列预测(多任务学习)
  14. PyTorch搭建ANN实现时间序列预测(风速预测)
  15. PyTorch搭建CNN实现时间序列预测(风速预测)
  16. PyTorch搭建CNN-LSTM混合模型实现多变量多步长时间序列预测(负荷预测)
  17. PyTorch搭建Transformer实现多变量多步长时间序列预测(负荷预测)
  18. PyTorch时间序列预测系列文章总结(代码使用方法)
  19. TensorFlow搭建LSTM实现时间序列预测(负荷预测)
  20. TensorFlow搭建LSTM实现多变量时间序列预测(负荷预测)
  21. TensorFlow搭建双向LSTM实现时间序列预测(负荷预测)
  22. TensorFlow搭建LSTM实现多变量多步长时间序列预测(一):直接多输出
  23. TensorFlow搭建LSTM实现多变量多步长时间序列预测(二):单步滚动预测
  24. TensorFlow搭建LSTM实现多变量多步长时间序列预测(三):多模型单步预测
  25. TensorFlow搭建LSTM实现多变量多步长时间序列预测(四):多模型滚动预测
  26. TensorFlow搭建LSTM实现多变量多步长时间序列预测(五):seq2seq
  27. TensorFlow搭建LSTM实现多变量输入多变量输出时间序列预测(多任务学习)
  28. TensorFlow搭建ANN实现时间序列预测(风速预测)
  29. TensorFlow搭建CNN实现时间序列预测(风速预测)
  30. TensorFlow搭建CNN-LSTM混合模型实现多变量多步长时间序列预测(负荷预测)
  31. PyG搭建图神经网络实现多变量输入多变量输出时间序列预测
  32. PyTorch搭建GNN-LSTM和LSTM-GNN模型实现多变量输入多变量输出时间序列预测
  33. PyG Temporal搭建STGCN实现多变量输入多变量输出时间序列预测
  34. 时序预测中Attention机制是否真的有效?盘点LSTM/RNN中24种Attention机制+效果对比

II. 数据处理

数据集为某个地区某段时间内的电力负荷数据,除了负荷以外,还包括温度、湿度等信息。

本篇文章暂时不考虑其它变量,只考虑用历史负荷来预测未来负荷。本文中,我们根据前24个时刻的负荷下一时刻的负荷。有关多变量预测请参考:PyTorch搭建LSTM实现多变量时间序列预测(负荷预测)

def load_data(file_name):
    df = pd.read_csv('data/new_data/' + file_name, encoding='gbk')
    columns = df.columns
    df.fillna(df.mean(), inplace=True)
    return df


class MyDataset(Dataset):
    def __init__(self, data):
        self.data = data

    def __getitem__(self, item):
        return self.data[item]

    def __len__(self):
        return len(self.data)
    
    
def nn_seq_us(B):
    print('data processing...')
    dataset = load_data()
    # split
    train = dataset[:int(len(dataset) * 0.6)]
    val = dataset[int(len(dataset) * 0.6):int(len(dataset) * 0.8)]
    test = dataset[int(len(dataset) * 0.8):len(dataset)]
    m, n = np.max(train[train.columns[1]]), np.min(train[train.columns[1]])

    def process(data, batch_size, shuffle):
        load = data[data.columns[1]]
        load = load.tolist()
        data = data.values.tolist()
        load = (load - n) / (m - n)
        seq = []
        for i in range(len(data) - 24):
            train_seq = []
            train_label = []
            for j in range(i, i + 24):
                x = [load[j]]
                train_seq.append(x)
            # for c in range(2, 8):
            #     train_seq.append(data[i + 24][c])
            train_label.append(load[i + 24])
            train_seq = torch.FloatTensor(train_seq)
            train_label = torch.FloatTensor(train_label).view(-1)
            seq.append((train_seq, train_label))

        # print(seq[-1])
        seq = MyDataset(seq)
        seq = DataLoader(dataset=seq, batch_size=batch_size, shuffle=shuffle, num_workers=0, drop_last=True)

        return seq

    Dtr = process(train, B, True)
    Val = process(val, B, True)
    Dte = process(test, B, False)

    return Dtr, Val, Dte, m, n

上面代码用了DataLoader来对原始数据进行处理,最终得到了batch_size=B的数据集Dtr、Val以及Dte,Dtr为训练集,Val为验证集,Dte为测试集。

III. LSTM模型

这里采用了深入理解PyTorch中LSTM的输入和输出(从input输入到Linear输出)中的模型:

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 # 单向LSTM
        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):
        batch_size, seq_len = input_seq.shape[0], input_seq.shape[1]
        h_0 = torch.randn(self.num_directions * self.num_layers, self.batch_size, self.hidden_size).to(device)
        c_0 = torch.randn(self.num_directions * self.num_layers, self.batch_size, self.hidden_size).to(device)
        # output(batch_size, seq_len, num_directions * hidden_size)
        output, _ = self.lstm(input_seq, (h_0, c_0)) # output(5, 30, 64)
        pred = self.linear(output)  # (5, 30, 1)
        pred = pred[:, -1, :]  # (5, 1)
        return pred

IV. 训练

def train(args, Dtr, Val, path):
    input_size, hidden_size, num_layers = args.input_size, args.hidden_size, args.num_layers
    output_size = args.output_size
    if args.bidirectional:
        model = BiLSTM(input_size, hidden_size, num_layers, output_size, batch_size=args.batch_size).to(device)
    else:
        model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=args.batch_size).to(device)

    loss_function = nn.MSELoss().to(device)
    if args.optimizer == 'adam':
        optimizer = torch.optim.Adam(model.parameters(), lr=args.lr,
                                     weight_decay=args.weight_decay)
    else:
        optimizer = torch.optim.SGD(model.parameters(), lr=args.lr,
                                    momentum=0.9, weight_decay=args.weight_decay)
    scheduler = StepLR(optimizer, step_size=args.step_size, gamma=args.gamma)
    # training
    min_epochs = 10
    best_model = None
    min_val_loss = 5
    for epoch in tqdm(range(args.epochs)):
        train_loss = []
        for (seq, label) in Dtr:
            seq = seq.to(device)
            label = label.to(device)
            y_pred = model(seq)
            loss = loss_function(y_pred, label)
            train_loss.append(loss.item())
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

        scheduler.step()
        # validation
        val_loss = get_val_loss(args, model, Val)
        if epoch > min_epochs and val_loss < min_val_loss:
            min_val_loss = val_loss
            best_model = copy.deepcopy(model)

        print('epoch {:03d} train_loss {:.8f} val_loss {:.8f}'.format(epoch, np.mean(train_loss), val_loss))
        model.train()

    state = {'models': best_model.state_dict()}
    torch.save(state, path)

保存训练过程中在验证集上表现最好的模型。

V. 测试

def test(args, Dte, path, m, n):
    pred = []
    y = []
    print('loading models...')
    input_size, hidden_size, num_layers = args.input_size, args.hidden_size, args.num_layers
    output_size = args.output_size
    if args.bidirectional:
        model = BiLSTM(input_size, hidden_size, num_layers, output_size, batch_size=args.batch_size).to(device)
    else:
        model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=args.batch_size).to(device)
    # models = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=args.batch_size).to(device)
    model.load_state_dict(torch.load(path)['models'])
    model.eval()
    print('predicting...')
    for (seq, target) in tqdm(Dte):
        target = list(chain.from_iterable(target.data.tolist()))
        y.extend(target)
        seq = seq.to(device)
        with torch.no_grad():
            y_pred = model(seq)
            y_pred = list(chain.from_iterable(y_pred.data.tolist()))
            pred.extend(y_pred)

    y, pred = np.array(y), np.array(pred)
    y = (m - n) * y + n
    pred = (m - n) * pred + n
    print('mape:', get_mape(y, pred))
    # plot
    x = [i for i in range(1, 151)]
    x_smooth = np.linspace(np.min(x), np.max(x), 900)
    y_smooth = make_interp_spline(x, y[150:300])(x_smooth)
    plt.plot(x_smooth, y_smooth, c='green', marker='*', ms=1, alpha=0.75, label='true')

    y_smooth = make_interp_spline(x, pred[150:300])(x_smooth)
    plt.plot(x_smooth, y_smooth, c='red', marker='o', ms=1, alpha=0.75, label='pred')
    plt.grid(axis='y')
    plt.legend()
    plt.show()

简单训练30轮,MAPE为5.77%:
在这里插入图片描述

VI. 源码及数据

暂无。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PyTorch搭建LSTM实现时间序列预测(负荷预测) 的相关文章

随机推荐

  • 解决pycharm安装好后打不开的问题

    你最近应该把带有Visual C 字样的东西卸载了吧 把 Visual C 安装回来就OK了 安装网址 https support microsoft com zh cn help 2977003 the latest supported
  • 树莓派4B下opencv3.4.0的安装测试与所有错误处理

    1 opencv3 4 0的下载 可以在树莓派的终端界面通过wegt命令下载 但下载速度可能很慢 终端输入下列代码进行下载 cd home pi Downloads wget https github com Itseez opencv a
  • Erlang数据类型的表示和实现(5)——binary

    binary 是 Erlang 中一个具有特色的数据结构 用于处理大块的 原始的 字节块 如果没有 binary 这种数据类型 在 Erlang 中处理字节流的话可能还需要像列表或元组这样的数据结构 根据之前对这些数据结构 Eterm 的描
  • VI/VIM 键盘图 及常规快捷操作

    一 VI VIM 键盘图 二 模式转换 2 1 一般模式 2 2 编辑模式 2 3 命令模式
  • EasyExcel导出图片到Excel

    EasyExcel导出图片到Excel 需要自己重新写转换器 但是1000张以下导出是没问题的 10000以上会卡顿 有意向的小伙伴可以一起讨论下 如何处理大数量的图片导出到excel import com alibaba excel co
  • GCC详解-总览

    1 GCC是什么 早期 GCC 的全拼为 GNU C Compiler 即 GUN 计划诞生的 C 语言编译器 显然最初 GCC 的定位确实只用于编译 C 语言 但经过这些年不断的迭代 GCC 的功能得到了很大的扩展 它不仅可以用来编译 C
  • 数字IC设计学习笔记_静态时序分析STA_配置STA环境2

    数字IC设计学习笔记 配置STA环境2 1 约束 Input path 和 Output path 2 时序路径组Timing path groups 3 外部属性建模 1 约束 Input path 和 Output path 约束 In
  • 【华为OD机试真题 python】识图谱新词挖掘【2023 Q1

    题目描述 识图谱新词挖掘 小华负责公司知识图谱产品 现在要通过新词挖掘完善知识图谱 新词挖掘 给出一个待挖掘文本内容字符串Content和一个词的字符串word 找到content中所有word的新词 新词 使用词word的字符排列形成的字
  • ES6入门:iterator迭代器

    迭代模式 ES6迭代器标准化接口 迭代循环 自定义迭代器 迭代器消耗 一 迭代模式 迭代模式中 通常有一个包含某种数据集合的对象 该数据可能存在一个复杂数据结构内部 而要提供一种简单的方法能够访问数据结构中每个元素 对象消费者并不需要知道如
  • 二、redis中String和List两种数据类型和应用场景

    导读 前面文章 一 深入理解redis之需要掌握的知识点 中 我们对redis需要学习的内容进行了一个梳理 从本篇文章开始 我们将要对redis中各个知识点做详细的学习和分析 本篇文章我们学习的是redis中基础数据类型String和Lis
  • matlab如何求矩阵特征值

    根据线性代数理论 特征值与特征向量只存在于方阵 如下所示为一方阵A 在matlab输入矩阵 A 1 2 4 4 0 7 9 1 3 查阅matlab help可以知道 利用eig函数可以快速求解矩阵的特征值与特征向量 格式 V D eig
  • 【踩坑】AES256解密失败,jasypt解密失败 最简单解决办法(本地环境)

    背景 最近被拉去一个新项目组 他们用的jasypt加密方式为数据库信息加密 我拉取代码后一跑 果然报错了 Unable to decrypt ENC xxxx 在试了n中方法 包括 创建新项目使用jasypt复现 写demo直接用jasyp
  • 给你们讲个笑话——低代码会取代程序员

    今天是正经男 我们严肃讨论一下一直以来争吵不休的取代问题 低代码开发平台 低代码技术会取代开发人员么 一 背景 低代码开发平台的普及 让很多公司对快速生成应用抱有很大期望 甚至有人认为 低代码开发平台未来会 干掉 开发者 这是真的吗 好久没
  • 压缩感知入门

    学习资料 网站http dsp rice edu cs 具有相关大量详细介绍的论文
  • idea 编译和构建 Java Web 项目后,没有生成 target 文件夹,且生成的 out 文件夹中没有 class 文件

    问题 在用 idea 编译和构建 Java Web 项目的时候 项目的目录中没有 target文件夹 生成的 out 文件夹中 没有 class 文件 办法 出现这种情况 很可能是因为未加载的模块出现在了 iml 文件中 导致生成 tage
  • Unity Animation -- 导入动画

    尽管Unity中的动画工具已经比较强大了 但对于非常复杂的或很长的动画 通常是由外部DCC创建 特别是对于角色动画来说 需要在动画过程中进行复杂的控制 因此我们通常需要将外部制作的动画导入到Unity中 动画能被共享吗 对于复杂的动画 制作
  • 阿里云-对象存储OSS

    大家好 我是 码赛客1024 今天我们一起来学习阿里云的对象存储服务OSS 一 介绍 阿里云对象存储OSS Object Storage Service 是一款海量 安全 低成本 高可靠的云存储服务 提供99 9999999999 12个9
  • 树的高度和深度

    用到树的数据结构时 经常会考虑树的高度和深度 但是lz总是搞混了 总虽然比较简单 就是个定义 记住就行了 但是因为长时间总是弄错 所以写一篇博文 加深一下印象 1 树的深度 树的深度可以这样理解 计算一个节点的深度 从根节点算起 记住从1开
  • LeetCode 之 Search for a Range

    题目链接 Search for a Range 对于一个按照升序排序的整数数组 找到给定目标值的开始位置和结束位置 且时间复杂度为O log n 如果在数组中找不到目标值 则返回 1 1 例如 数组为 5 7 7 8 8 10 和目标值8
  • PyTorch搭建LSTM实现时间序列预测(负荷预测)

    目录 I 前言 II 数据处理 III LSTM模型 IV 训练 V 测试 VI 源码及数据 I 前言 在上一篇文章深入理解PyTorch中LSTM的输入和输出 从input输入到Linear输出 中 我详细地解释了如何利用PyTorch来