时间序列预测18:ConvLSTM 实现用电量/发电量预测

2023-10-18 16:30

本文主要是介绍时间序列预测18:ConvLSTM 实现用电量/发电量预测,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


【时间序列预测/分类】 全系列60篇由浅入深的博文汇总:传送门


接上文,本文介绍了ConvLSTM模型实现用电量/发电量预测。


LSTM 处理用电量/发电量预测任务的文章:

【Part1】Encoder-Decoder LSTM 模型 实现用电量/发电量预测
【Part2】CNN-LSTM 模型 实现用电量/发电量预测
【Part3】本文


文章目录

  • 1. ConvLSTM
    • 1.1 CNN 模型
    • 1.2 完整代码
  • 扩展
  • 总结


1. ConvLSTM

1.1 CNN 模型

CNN-LSTM方法的进一步扩展是执行CNN的卷积(例如CNN如何读取输入序列数据)作为LSTM的一部分用于每个时间步。这种组合称为ConvLSTM,与CNN-LSTM一样,它也用于时空数据。与直接读取数据以计算内部状态和状态转换的LSTM不同,与解释CNN模型输出的CNN-LSTM也不同,ConvLSTM直接使用卷积作为读取LSTM单元输入的一部分。Keras库提供了ConvLSTM2D类,该类支持二维数据的ConvLSTM模型。它可以配置为一维多变量时间序列预测。默认情况下,ConvLSTM2D类要求输入数据的形状为:[samples,timesteps,rows,cols,channels]

其中数据的每个时间步均定义为(行×列)数据点的图像。我们正在处理总功耗的一维序列,如果我们假设我们使用两周的数据作为输入,则行为1,列为14。ConvLSTM将一次读取这些数据,即LSTM读取一个14天的时间步长,并在这些时间步长上进行卷积。

在我们的任务中,可以将14天分成两个子序列,每个子序列的长度为7天。然后,ConvLSTM可以读取两个时间步长,并对每个时间步长中的7天数据执行CNN处理。因此,对于此问题的选定框架,ConvLSTM2D的输入shape为:[n,2,1,7,1]。参数说明:

  • 样本(samples):n,表示训练数据集中的样本数。
  • 时间步长(timesteps):2,表示将一个窗口宽度为14天的采样数据分为两个子序列。
  • 行(rows):1,表示每个子序列的一维形状,即有多少行。
  • 列(cols):7,表示每个子序列,有多少列。
  • 通道(channels):1,在图像识别任务中的概念,通道数。在时间序列预测任务中其实就是特征数(features),这个概念在之前的文章中反复提及强调。因为本例的业务需求是通过日总功耗来预测下周的日总功耗,所以通道数(特征数)为1,即代表日总功耗。如果要添加其他的特征,这个尺寸要做相应改变。再看下数据集情况,就一目了然了。
    在这里插入图片描述
    还可以探索其他配置,例如使用前21天的总功耗作为输入,并将其分为3个子序列,和/或提供所有八个功能或通道作为输入。ConvLSTM2D的数据输入要求必须将训练数据集重塑为[样本,时间步长,行,列,通道]([samples, timesteps, rows, cols, channels])的结构。对比CNN-LSTM完整代码,需要在此基础上做如下修改:

1. 重塑训练样本的shape:

train_x = train_x.reshape((train_x.shape[0], n_steps, 1, n_length, n_features))

2. 设定ConvLSTM模型的输入尺寸参数:

model.add(ConvLSTM2D(filters=64, kernel_size=(1,3), activation='relu',input_shape=(sw_width, 1, n_length, n_features)))
model.add(Flatten())

3. 重塑测试样本的shape:

input_x = input_x.reshape((1, sw_width, 1, n_length, 1))

1.2 完整代码

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt# 设置中文显示
plt.rcParams['font.sans-serif'] = ['Microsoft JhengHei']
plt.rcParams['axes.unicode_minus'] = Falseimport math
import sklearn.metrics as skm
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense
from tensorflow.keras.layers import RepeatVector, TimeDistributed
from tensorflow.keras.layers import ConvLSTM2Ddef split_dataset(data):'''该函数实现以周为单位切分训练数据和测试数据'''# data为按天的耗电量统计数据,shape为(1442, 8)# 测试集取最后一年的46周(322天)数据,剩下的159周(1113天)数据为训练集,以下的切片实现此功能。train, test = data[1:-328], data[-328:-6]train = np.array(np.split(train, len(train)/7)) # 将数据划分为按周为单位的数据test = np.array(np.split(test, len(test)/7))return train, testdef evaluate_forecasts(actual, predicted):'''该函数实现根据预期值评估一个或多个周预测损失思路:统计所有单日预测的 RMSE'''scores = list()for i in range(actual.shape[1]):mse = skm.mean_squared_error(actual[:, i], predicted[:, i])rmse = math.sqrt(mse)scores.append(rmse)s = 0 # 计算总的 RMSEfor row in range(actual.shape[0]):for col in range(actual.shape[1]):s += (actual[row, col] - predicted[row, col]) ** 2score = math.sqrt(s / (actual.shape[0] * actual.shape[1]))print('actual.shape[0]:{}, actual.shape[1]:{}'.format(actual.shape[0], actual.shape[1]))return score, scoresdef summarize_scores(name, score, scores):s_scores = ', '.join(['%.1f' % s for s in scores])print('%s: [%.3f] %s\n' % (name, score, s_scores))def sliding_window(train, sw_width=7, n_out=7, in_start=0):'''该函数实现窗口宽度为7、滑动步长为1的滑动窗口截取序列数据'''data = train.reshape((train.shape[0] * train.shape[1], train.shape[2])) # 将以周为单位的样本展平为以天为单位的序列X, y = [], []for _ in range(len(data)):in_end = in_start + sw_widthout_end = in_end + n_out# 保证截取样本完整,最大元素索引不超过原序列索引,则截取数据;否则丢弃该样本if out_end < len(data):# 训练数据以滑动步长1截取train_seq = data[in_start:in_end, 0]train_seq = train_seq.reshape((len(train_seq), 1))X.append(train_seq)y.append(data[in_end:out_end, 0])in_start += 1return np.array(X), np.array(y)def conv_lstm_model(train, sw_width, n_steps, n_length, in_start=0, verbose_set=0, epochs_num=20, batch_size_set=4):'''该函数定义 Encoder-Decoder LSTM 模型'''train_x, train_y = sliding_window(train, sw_width, in_start=0)n_timesteps, n_features, n_outputs = train_x.shape[1], train_x.shape[2], train_y.shape[1]train_x = train_x.reshape((train_x.shape[0], n_steps, 1, n_length, n_features))train_y = train_y.reshape((train_y.shape[0], train_y.shape[1], 1))model = Sequential()model.add(ConvLSTM2D(filters=64, kernel_size=(1,3), activation='relu',input_shape=(n_steps, 1, n_length, n_features)))model.add(Flatten())model.add(RepeatVector(n_outputs))model.add(LSTM(200, activation='relu', return_sequences=True))model.add(TimeDistributed(Dense(100, activation='relu')))model.add(TimeDistributed(Dense(1)))model.compile(loss='mse', optimizer='adam', metrics=['accuracy'])print(model.summary())model.fit(train_x, train_y,epochs=epochs_num, batch_size=batch_size_set, verbose=verbose_set)return modeldef forecast(model, pred_seq, sw_width, n_length, n_steps):'''该函数实现对输入数据的预测'''data = np.array(pred_seq)data = data.reshape((data.shape[0]*data.shape[1], data.shape[2]))input_x = data[-sw_width:, 0] # 获取输入数据的最后一周的数据input_x = input_x.reshape((1, n_steps, 1, n_length, 1))yhat = model.predict(input_x, verbose=0) # 预测下周数据yhat = yhat[0] # 获取预测向量return yhatdef evaluate_model(model, train, test, sd_width, n_length, n_steps):'''该函数实现模型评估'''history_fore = [x for x in train]predictions = list() # 用于保存每周的前向验证结果;for i in range(len(test)):yhat_sequence = forecast(model, history_fore, sd_width, n_length, n_steps) # 预测下周的数据predictions.append(yhat_sequence) # 保存预测结果history_fore.append(test[i, :]) # 得到真实的观察结果并添加到历史中以预测下周predictions = np.array(predictions) # 评估一周中每天的预测结果score, scores = evaluate_forecasts(test[:, :, 0], predictions)return score, scoresdef model_plot(score, scores, days, name):'''该函数实现绘制RMSE曲线图'''plt.figure(figsize=(8,6), dpi=150)plt.plot(days, scores, marker='o', label=name)plt.grid(linestyle='--', alpha=0.5)plt.ylabel(r'$RMSE$', size=15)plt.title('Conv-LSTM 模型预测结果',  size=18)plt.legend()plt.show()def main_run(dataset, sw_width, days, name, in_start, verbose, epochs, batch_size, n_steps, n_length):'''主函数:数据处理、模型训练流程'''# 划分训练集和测试集train, test = split_dataset(dataset.values)# 训练模型model = conv_lstm_model(train, sw_width,  n_steps, n_length, in_start, verbose_set=0, epochs_num=20, batch_size_set=4)# 计算RMSEscore, scores = evaluate_model(model, train, test, sw_width, n_length, n_steps)# 打印分数summarize_scores(name, score, scores)# 绘图model_plot(score, scores, days, name)if __name__ == '__main__':dataset = pd.read_csv('household_power_consumption_days.csv', header=0, infer_datetime_format=True, engine='c',parse_dates=['datetime'], index_col=['datetime'])days = ['sun', 'mon', 'tue', 'wed', 'thr', 'fri', 'sat']name = 'Conv-LSTM'# 定义序列的数量和长度'''n_steps:子序列划分的数量,本例为2,将14天的数据划分为两个7的子序列;n_length:子序列每行的元素数,即列数。'''n_steps, n_length = 2, 7sliding_window_width= n_length * n_stepsinput_sequence_start=0epochs_num=20batch_size_set=16verbose_set=0main_run(dataset, sliding_window_width, days, name, input_sequence_start,verbose_set, epochs_num, batch_size_set, n_steps, n_length)

输出:

Model: "sequential_12"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv_lst_m2d_2 (ConvLSTM2D)  (None, 1, 5, 64)          50176     
_________________________________________________________________
flatten_3 (Flatten)          (None, 320)               0         
_________________________________________________________________
repeat_vector_8 (RepeatVecto (None, 7, 320)            0         
_________________________________________________________________
lstm_16 (LSTM)               (None, 7, 200)            416800    
_________________________________________________________________
time_distributed_16 (TimeDis (None, 7, 100)            20100     
_________________________________________________________________
time_distributed_17 (TimeDis (None, 7, 1)              101       
=================================================================
Total params: 487,177
Trainable params: 487,177
Non-trainable params: 0
_________________________________________________________________
None
actual.shape[0]:46, actual.shape[1]:7
Conv-LSTM: [382.156] 391.3, 386.4, 340.5, 388.9, 364.4, 309.1, 473.6

运行示例总结测试集的性能。实验表明,使用两个卷积层使模型比仅使用单个层更稳定。可以看到,在这种情况下,该模型表现较好,总体RMSE得分约为382千瓦。


扩展

  • 输入大小:探索模型的输入天数,例如3天,21天,30天等等。
  • 模型调整:调整模型的结构和超参数,并进一步提升模型性能。
  • 数据缩放:探索是否可以使用数据缩放(例如标准化和规范化)来改善LSTM模型的性能。
  • 学习诊断:使用诊断(例如训练的学习曲线和验证损失以及均方误差)来帮助调整LSTM模型的结构和超参数。

总结

三篇文章介绍了如何开发LSTM来进行家庭用电量的多步时间序列预测。主要有以下内容:

  • 如何开发和评估用于多步时间序列预测的单变量和多变量Encoder-Decoder LSTM 模型。
  • 如何开发和评估用于多步时间序列预测的CNN-LSTM Encoder-Decoder 模型。
  • 如何开发和评估用于多步时间序列预测的ConvLSTM Encoder-Decoder 模型。

关于时间序列预测用电量预测任务先告一段落,下篇文章开始介绍时间序列分类任务,比如人类行为识别,车辆驾驶行为识别。


这篇关于时间序列预测18:ConvLSTM 实现用电量/发电量预测的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/233790

相关文章

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

uva 10131 最长子序列

题意: 给大象的体重和智商,求体重按从大到小,智商从高到低的最长子序列,并输出路径。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vect

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、