时间序列预测17:CNN-LSTM 实现用电量/发电量预测

news/2024/11/19 5:50:26/

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


接上文,本文介绍了CNN-LSTM模型实现单、多变量多时间步预测的家庭用电量预测任务。


文章目录

  • 1. CNN-LSTM
    • 1.1 CNN 模型
    • 1.2 完整代码


1. CNN-LSTM

1.1 CNN 模型

卷积神经网络(CNN)可用作编码器-解码器结构中的编码器。 CNN不直接支持序列输入;相反,一维CNN能够读取序列输入并自动学习显着特征。然后可以由LSTM解码器解释这些内容。CNN和LSTM的混合模型称为CNN-LSTM模型,在编码器-解码器结构中一起使用。CNN希望输入的数据具有与LSTM模型相同的3D结构,尽管将多个特征作为不同的通道读取,但效果相同。

为简化示例,重点放在具有单变量输入的CNN-LSTM上,但是可以很容易地对其进行更新以使用多变量输入,这是一项练习。和以前一样,使用14天的每日总功耗输入序列。编码器为一个简单有效的CNN模型,由两个卷积层和一个最大池化层组成,然后将其结果平坦化。

第一层卷积读取输入序列,并将结果投影到特征图上。第二层卷积在第一层创建的特征图上执行相同的操作,尝试放大其显著特征。每个卷积层使用64个特征图(filters=64),并以3个时间步长的内核大小(kernel_size=3)读取输入序列。最大池化层降采样成原来特征图尺寸的1/4来简化特征图。然后将提取的特征图展平为一个长向量,将其用作解码过程的输入。代码实现:

model.add(Conv1D(filters=64, kernel_size=3, activation='relu',input_shape=(n_timesteps,n_features)))
model.add(Conv1D(filters=64, kernel_size=3, activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(Flatten())

1.2 完整代码

完整代码以单变量多步预测演示,要想修改多变量,只需要修改sliding_window()forecast() 函数即可,可以参考上一篇文章:👉传送门。

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, TimeDistributeddef 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 cnn_lstm_model(train, sw_width, 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_y = train_y.reshape((train_y.shape[0], train_y.shape[1], 1))model = Sequential()model.add(Conv1D(filters=64, kernel_size=3, activation='relu',input_shape=(n_timesteps,n_features)))model.add(Conv1D(filters=64, kernel_size=3, activation='relu'))model.add(MaxPooling1D(pool_size=2))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):'''该函数实现对输入数据的预测'''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, len(input_x), 1)) # 重塑形状[1, sw_width, 1]yhat = model.predict(input_x, verbose=0) # 预测下周数据yhat = yhat[0] # 获取预测向量return yhatdef evaluate_model(model, train, test, sd_width):'''该函数实现模型评估'''history_fore = [x for x in train]predictions = list() # 用于保存每周的前向验证结果;for i in range(len(test)):yhat_sequence = forecast(model, history_fore, sd_width) # 预测下周的数据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('CNN-LSTM 模型预测结果',  size=18)plt.legend()plt.show()def main_run(dataset, sw_width, days, name, in_start, verbose, epochs, batch_size):'''主函数:数据处理、模型训练流程'''# 划分训练集和测试集train, test = split_dataset(dataset.values)# 训练模型model = cnn_lstm_model(train, sw_width, in_start, verbose_set=0, epochs_num=20, batch_size_set=4)# 计算RMSEscore, scores = evaluate_model(model, train, test, sw_width)# 打印分数summarize_scores(name, score, scores)# 绘图model_plot(score, scores, days, name)print('------头发不够,帽子来凑-----')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 = 'CNN-LSTM'sliding_window_width= 14input_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)

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

Model: "sequential_9"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv1d (Conv1D)              (None, 12, 64)            256       
_________________________________________________________________
conv1d_1 (Conv1D)            (None, 10, 64)            12352     
_________________________________________________________________
max_pooling1d (MaxPooling1D) (None, 5, 64)             0         
_________________________________________________________________
flatten (Flatten)            (None, 320)               0         
_________________________________________________________________
repeat_vector_5 (RepeatVecto (None, 7, 320)            0         
_________________________________________________________________
lstm_13 (LSTM)               (None, 7, 200)            416800    
_________________________________________________________________
time_distributed_10 (TimeDis (None, 7, 100)            20100     
_________________________________________________________________
time_distributed_11 (TimeDis (None, 7, 1)              101       
=================================================================
Total params: 449,609
Trainable params: 449,609
Non-trainable params: 0
_________________________________________________________________
None
actual.shape[0]:46, actual.shape[1]:7
CNN-LSTM: [390.960] 411.0, 380.4, 339.6, 391.1, 375.2, 312.5, 499.6

RMSE曲线:
在这里插入图片描述

可以看到星期二和星期五是比较容易预测的日期,星期天是最不容易预测的日期。


本文以单变量为例讲解了CNN-LSTM处理时间序列预测的建模思路,关于多变量预测,只需要修改sliding_window()forecast() 函数即可,可以参考上一篇文章:👉传送门。

注意,以上的实现方法仅仅是使用for循环实现滑动步长为1的滑动窗口来截取数据,在实际应用过程中,可以通过自定义函数,实现任意步长的滑动窗口,实现方法在以后的文章会介绍。


下一篇介绍ConvLSTM模型来实现家庭用电数据集的预测。



http://www.ppmy.cn/news/651081.html

相关文章

时间序列预测14:CNN 实现用电量/发电量预测

【时间序列预测/分类】 全系列60篇由浅入深的博文汇总&#xff1a;传送门 文章目录 前言适用于多时间步预测的CNN模型1 单变量多步预测 CNN 模型1.1 业务需求1.2 1D CNN 模型1.3 完整代码 前言 与其他机器学习算法不同&#xff0c;卷积神经网络能够从序列数据中自动学习特征&a…

实训1:拉格朗日法插补用户用电量数据缺失值

实训1&#xff1a;拉格朗日法插补用户用电量数据缺失值 实训任务&#xff1a; 读取missing_data.csv表查询缺失值位置 3.使用SciPy库中的interpolate模块下的lagrange对数据进行拉格朗日插值使用数据查看是否存在缺失值&#xff0c;不存在则说明插值成功 查询缺失值位置 is…

大工业用电计费及其相关知识

电费计算方法主要分为大工业用电和一般工商业用电、农业生产用电用电、居民生活用电。 1、概念 大工业用电指受电变压器&#xff08;含不通过受电变压器的高压电动机&#xff09;容量在315千伏安及以上的下列用电&#xff1a; &#xff08;1&#xff09;以电为原动力&#xf…

时间序列预测:用电量预测 02 KNN(K邻近算法)

&#x1f32e;开发平台&#xff1a;jupyter lab &#x1f356;运行环境&#xff1a;python3、TensorFlow2.x ----------------------------------------------- 2022.9.16 测验成功 ---------------------------------------------------------------- 1. 时间序列预测&#x…

线性回归入门案例 家庭用电量预测

本博客是线性回归的入门案例&#xff0c;仅用到一阶线性回归 代码中用到的数据集下载地址 [link] https://pan.baidu.com/s/12wSIOVMQ3zS3jK0FcwkTSw[ python3版本代码段 导包 #导包 import numpy as np import matplotlib.pyplot as plt import pandas as pd import time…

时间序列预测11:用电量预测 01 数据分析与建模

【时间序列预测/分类】 全系列60篇由浅入深的博文汇总&#xff1a;传送门 写在前面 通过之前有关LSTM的8遍基础教程和10篇处理时间序列预测任务的教程介绍&#xff0c;使用简单的序列数据示例&#xff0c;已经把LSTM的原理&#xff0c;数据处理流程&#xff0c;模型架构&#…

python用支持向量机回归(SVR)模型分析用电量预测电力消费

最近我们被客户要求撰写关于支持向量机回归的研究报告&#xff0c;包括一些图形和统计输出。 本文描述了训练支持向量回归模型的过程&#xff0c;该模型用于预测基于几个天气变量、一天中的某个小时、以及这一天是周末/假日/在家工作日还是普通工作日的用电量。 【视频】支持向…

算力网络:十大技术发展方向

摘自&#xff1a;https://mp.weixin.qq.com/s/yykVHtdUVGL7G9E1jtMIxg 在社会算力并网场景下&#xff0c;将联合超算、智算等社会算力开展算力并网验证&#xff1b;在云边端协同场景下&#xff0c;打造算网融合创新技术方案&#xff0c;探索算网大脑雏形&#xff0c;深入车联网…