时间序列预测 — VMD-LSTM实现单变量多步光伏预测(Tensorflow):单变量转为多变量预测多变量

news2024/11/18 15:23:51

目录

1 数据处理

1.1 导入库文件

1.2 导入数据集

​1.3 缺失值分析

2 VMD经验模态分解

2.1 VMD分解实验

2.2 VMD-LSTM预测思路

3 构造训练数据

4 LSTM模型训练

5 LSTM模型预测

5.1 分量预测

5.2 可视化


时间序列预测专栏链接:https://blog.csdn.net/qq_41921826/category_12495091.html

1 数据处理

1.1 导入库文件

import time
import datetime
import pandas as pd 
import numpy as np 
import matplotlib.pyplot as plt  
from sampen import sampen2  # sampen库用于计算样本熵
from vmdpy import VMD  # VMD分解库
from itertools import cycle

import tensorflow as tf 
from sklearn.cluster import KMeans
from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error, mean_absolute_percentage_error 
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation, Dropout, LSTM, GRU, Reshape, BatchNormalization
from tensorflow.keras.callbacks import ReduceLROnPlateau, EarlyStopping, ModelCheckpoint
from tensorflow.keras.optimizers import Adam

# 忽略警告信息
import warnings
warnings.filterwarnings('ignore'))  
plt.rcParams['font.sans-serif'] = ['SimHei']     # 显示中文
plt.rcParams['axes.unicode_minus'] = False  # 显示负号
plt.rcParams.update({'font.size':18})  #统一字体字号

1.2 导入数据集

实验数据集采用数据集8:新疆光伏风电数据集(下载链接),数据集包括组件温度(℃) 、温度(°)    气压(hPa)、湿度(%)、总辐射(W/m2)、直射辐射(W/m2)、散射辐射(W/m2)、实际发电功率(mw)特征,时间间隔15min。对数据进行可视化:

# 导入数据
data_raw = pd.read_excel("E:\\课题\\08数据集\\新疆风电光伏数据\\光伏2019.xlsx")
data_raw
from itertools import cycle
# 可视化数据
def visualize_data(data, row, col):
    cycol = cycle('bgrcmk')
    cols = list(data.columns)
    fig, axes = plt.subplots(row, col, figsize=(16, 4))
    fig.tight_layout()
    if row == 1 and col == 1:  # 处理只有1行1列的情况
        axes = [axes]  # 转换为列表,方便统一处理
    for i, ax in enumerate(axes.flat):
        if i < len(cols):
            ax.plot(data.iloc[:,i], c=next(cycol))
            ax.set_title(cols[i])
        else:
            ax.axis('off')  # 如果数据列数小于子图数量,关闭多余的子图
    plt.subplots_adjust(hspace=0.6)
    plt.show()

visualize_data(data_raw.iloc[:,1:], 2, 4)

​单独查看部分功率数据,发现有较强的规律性。

​1.3 缺失值分析

首先查看数据的信息,发现并没有缺失值

data_raw.info()

​ 进一步统计缺失值

data_raw.isnull().sum()

2 VMD经验模态分解

2.1 VMD分解实验

使用VMD将目标信号分解成若干个模态,进一步可视化分解结果

# VMD分解函数
# signal: 输入信号
# alpha: 正则化参数
# tau: 时间尺度参数
# K: 分量数量
# DC: 是否包括直流分量
# init: 初始化方法
# tol: 收敛容限
# n_ite: 最大迭代次数
def vmd_decompose(series=None, alpha=2000, tau=0, K=6, DC=0, init=1, tol=1e-7, draw=True): 
    # 得到 VMD 分解后的各个分量、分解后的信号和频率
    imfs_vmd, imfs_hat, omega = VMD(series, alpha, tau, K, DC, init, tol)  
    # 将 VMD 分解分量转换为 DataFrame, 并重命名
    df_vmd = pd.DataFrame(imfs_vmd.T)
    df_vmd.columns = ['imf'+str(i) for i in range(K)]
    return df_vmd

因为只是单变量预测,只选取实际发电功率(mw)数据进行实验 

df_vmd = vmd_decompose(data_raw['实际发电功率(mw)'])  # 对 df_raw_data['AQI'] 进行 VMD 分解,并将结果赋值给 df_vmd
# 绘制 df_vmd 的数据,以子图形式显示每个分量
ax = df_vmd.plot(title='VMD Decomposition', figsize=(16,8), subplots=True,fontsize=16)
for a in ax:
    a.legend(loc='upper right',prop={'size': 14})
    plt.subplots_adjust(hspace=0.5)

​查看分解后的数据:

df_vmd

​这里我们验证一下分解效果,通过分解变量求和和实际功率值进行可视化比较,发现基本相同。

# 验证分解效果
plt.figure(dpi=100,figsize=(14,5))
plt.plot(df_vmd.iloc[:96*10,:-1].sum(axis=1))
plt.plot(data_raw['实际发电功率(mw)'][:96*10])
plt.legend(['VMD分解求和','原始负荷']) 
# 坐标描述
plt.xlabel('时间')
plt.ylabel('功率(kW)')

2.2 VMD-LSTM预测思路

这里利用VMD-LSTM进行预测的思路是通过VMD将原始功率分解为多个变量,然后将每个分解变量都进行预测,接着将预测的结果添加到历史数据中进行滚动预测,得到需要预测的步数,最后将每个分解变量的预测结果相加得到最终的预测结果。

3 构造训练数据

构造数据前先将数据变为数值类型

df_vmd = df_vmd.values

构造训练数据,也是真正预测未来的关键。首先设置预测的timesteps时间步、predict_steps预测的步长(预测的步长应该比总的预测步长小),length总的预测步长,参数可以根据需要更改。

timesteps = 96*7 #构造x,为72个数据,表示每次用前72个数据作为一段
predict_steps = 12 #构造y,为12个数据,表示用后12个数据作为一段
length = 96 #预测多步,预测96个数据,每次预测96个,想想要怎么构造预测才能满足96?
feature_num = 7 #特征个数?

通过前timesteps个数据预测后面predict_steps个数据,需要对数据集进行滚动划分(也就是前timesteps行的数据和后predict_steps行的数据训练,后面预测时就可通过timesteps行数据预测未来的predict_steps行数据)。这里需要注意的是,因为是多变量预测多变量,特征就是标签(例如,前5行[imf_0, imf_1, imf_2, imf_3, imf_4, imf_5]预测第6行[imf_0, imf_1, imf_2, imf_3, imf_4, imf_5],划分数据集时,就用前5行当做train_x,第6行作为train_y,此时的train_y有多列,而不是只有1列)。

# 构造数据集,用于真正预测未来数据
# 整体的思路也就是,前面通过前timesteps个数据训练后面的predict_steps个未来数据
# 预测时取出前timesteps个数据预测未来的predict_steps个未来数据。
def create_dataset(datasetx, datasety=None, timesteps=96*7, predict_size=12):
    datax = []  # 构造x
    datay = []  # 构造y
    for each in range(len(datasetx) - timesteps - predict_size):
        x = datasetx[each:each + timesteps]
        # 判断是否是单变量分解还是多变量分解
        if datasety is not None:
            y = datasety[each + timesteps:each + timesteps + predict_size]
        else:
            y = datasetx[each + timesteps:each + timesteps + predict_size]
        datax.append(x)
        datay.append(y)
    return datax, datay

​数据处理前,需要对数据进行归一化,按照上面的方法划分数据,这里返回划分的数据和归一化模型(变量和多变量的归一化不同,多变量归一化需要将X和Y分开归一化,不然会出现信息泄露的问题),此时的归一化相当于是单变量归一化,函数的定义如下:

# 数据归一化操作
def data_scaler(datax, datay=None, timesteps=36, predict_steps=6):
    # 数据归一化操作
    scaler1 = MinMaxScaler(feature_range=(0, 1))   
    datax = scaler1.fit_transform(datax)
    # 用前面的数据进行训练,留最后的数据进行预测
    # 判断是否是单变量分解还是多变量分解
    if datay is not None:
        scaler2 = MinMaxScaler(feature_range=(0, 1))
        datay = scaler2.fit_transform(datay)
        trainx, trainy = create_dataset(datax, datay, timesteps, predict_steps)
        trainx = np.array(trainx)
        trainy = np.array(trainy)
        return trainx, trainy, scaler1, scaler2
    else:
        trainx, trainy = create_dataset(datax, timesteps=timesteps, predict_size=predict_steps)
        trainx = np.array(trainx)
        trainy = np.array(trainy)
        return trainx, trainy, scaler1, None

然后分解的数据进行划分和归一化。通过前7天的96*7行数据预测后一天的96个数据,需要对数据集进行滚动划分(也就是前96*7行的数据和后12行的数据训练,后面预测时就可通过96*7行数据测未来的12行数据,然后将12行预测值添加到历史数据中,历史数据变为96*7+12个,再取出后96*7行数据进行预测,得到12行预测值,滚动进行预测直到预测完成,注意此时的预测值是行而不是个)

trainx, trainy, scalerx, scalery = data_scaler(df_vmd, timesteps=timesteps, predict_steps=predict_steps)

4 LSTM模型训练

首先划分训练集、测试集、验证数据:

train_x = trainx[:int(trainx.shape[0] * 0.8)]
train_y = trainy[:int(trainy.shape[0] * 0.8)]
test_x = trainx[int(trainx.shape[0] * 0.8):]
test_y = trainy[int(trainy.shape[0] * 0.8):]
test_x.shape, test_y.shape, train_x.shape, train_y.shape

首先搭建模型的常规操作,然后使用训练数据trainx和trainy进行训练,进行50个epochs的训练,每个batch包含64个样本(建议使用GPU进行训练)。

# 搭建LSTM训练函数
def LSTM_model_train(trainx, trainy, valx, valy, timesteps, predict_steps):
    # 调用GPU加速
    gpus = tf.config.experimental.list_physical_devices(device_type='GPU')
    for gpu in gpus:
        tf.config.experimental.set_memory_growth(gpu, True)

    # 搭建LSTM模型
    start_time = datetime.datetime.now()
    model = Sequential()
    model.add(LSTM(128, input_shape=(timesteps, trainx.shape[2]), return_sequences=True))
    model.add(BatchNormalization())  # 添加BatchNormalization层
    model.add(Dropout(0.2))
    model.add(LSTM(64, return_sequences=False))
    model.add(Dense(predict_steps * trainy.shape[2]))
    model.add(Reshape((predict_steps, trainy.shape[2])))

    # 使用自定义的Adam优化器
    opt = Adam(learning_rate=0.001)
    model.compile(loss="mean_squared_error", optimizer=opt)
    
    # 添加早停和模型保存的回调函数
    es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=10)
    mc = ModelCheckpoint('best_model.h5', monitor='val_loss', mode='min', save_best_only=True)

    # 训练模型,这里我假设你有一个验证集(valx, valy)
    history = model.fit(trainx, trainy, validation_data=(valx, valy), epochs=50, batch_size=64, callbacks=[es, mc])

    # 记录训练损失
    loss_history = history.history['loss']

    end_time = datetime.datetime.now()
    running_time = end_time - start_time

    return model, loss_history, running_time

然后进行训练,将训练的模型、损失和训练时间保存。

#模型训练
model, loss_history, running_time = LSTM_model_train(train_x, train_y, test_x, test_y, timesteps, predict_steps)
# 将模型保存为文件
model.save('emd_lstm_model.h5')

5 LSTM模型预测

5.1 分量预测

下面介绍文章中最重要,也是真正没有未来特征的情况下预测未来标签的方法。整体的思路也就是取出预测前96*6行数据预测未来的12行数据,然后见12行数据添加进历史数据,再预测12行数据,滚动预测。因为每次只能预测12行数据,但是我要预测96个数据,所以采用的就是循环预测的思路。每次预测的12行数据,添加到数据集中充当预测x,然后在预测新的12行y,再添加到预测x列表中,如此往复,最终预测出96行。(注意多变量预测多变量预测的是多列,预测单变量只有一列)

# #滚动predict
# #因为每次只能预测12个数据,但是我要预测96个数据,所以采用的就是循环预测的思路。
# #每次预测的12个数据,添加到数据集中充当预测x,然后在预测新的12个y,再添加到预测x列表中,如此往复,最终预测出96个点。
def predict_using_LSTM(model, data, timesteps, predict_steps, feature_num, length, scaler):
    predict_xlist = np.array(data).reshape(1, timesteps, feature_num) 
    predict_y = np.array([]).reshape(0, feature_num)  # 初始化为空的二维数组
    print('predict_xlist', predict_xlist.shape)
    
    while len(predict_y) < length:
        # 从最新的predict_xlist取出timesteps个数据,预测新的predict_steps个数据
        predictx = predict_xlist[:,-timesteps:,:]
        # 变换格式,适应LSTM模型
        predictx = np.reshape(predictx, (1, timesteps, feature_num)) 
        print('predictx.shape', predictx.shape)
        
        # 预测新值
        lstm_predict = model.predict(predictx)
        print('lstm_predict.shape', lstm_predict.shape)
        
        # 滚动预测
        # 将新预测出来的predict_steps个数据,加入predict_xlist列表,用于下次预测
        print('predict_xlist.shape', predict_xlist.shape)
        predict_xlist = np.concatenate((predict_xlist, lstm_predict), axis=1)
        print('predict_xlist.shape', predict_xlist.shape)
        
        # 预测的结果y,每次预测的12个数据,添加进去,直到预测length个为止
        lstm_predict = scaler.inverse_transform(lstm_predict.reshape(predict_steps, feature_num))
        predict_y = np.concatenate((predict_y, lstm_predict), axis=0)
        print('predict_y', predict_y.shape)
        
    return predict_y

然后对数据进行预测,得到预测结果。

from tensorflow.keras.models import load_model
model = load_model('emd_lstm_model.h5')
pre_x = scalerx.fit_transform(df_vmd[-96*8:-96])
y_predict = predict_using_LSTM(model, pre_x, timesteps, predict_steps, feature_num, length, scalerx)

5.2 可视化

对预测的各分解变量和总的预测结果进行可视化。

#分量预测结果
for i in range(y_predict.shape[1]):
    fig, ax = plt.subplots(dpi=100, figsize=(14, 5))
    ax.plot(df_vmd[-96:, -i], markevery=5, label='IMF'+str(i)+'_true')
    ax.plot(y_predict[:, -i], markevery=5, label='IMF'+str(i)+'_predict')
    ax.set_xlabel('时间')
    ax.set_ylabel('预测值')
    ax.legend(loc = 'upper right')
    plt.show()
# 总预测结果
plt.figure(dpi=100, figsize=(14, 5))
plt.plot(np.sum(y_predict[:, :-1], axis=1), markevery=5, label = 'all_predict')
plt.plot(df_vmd[-96:,-1], markevery=5, label = 'all_true')
plt.legend(loc = 'upper right')

最后对预测结果计算误差。

# 预测并计算误差和可视化
def error_and_plot(y_true,y_predict):
    # 计算误差
    r2 = r2_score(y_true, y_predict)
    rmse = mean_squared_error(y_true, y_predict, squared=False)
    mae = mean_absolute_error(y_true, y_predict)
    mape = mean_absolute_percentage_error(y_true, y_predict)
    print("r2: %.2f\nrmse: %.2f\nmae: %.2f\nmape: %.2f" % (r2, rmse, mae, mape))
    
    # 预测结果可视化
    cycol = cycle('bgrcmk')
    plt.figure(dpi=100, figsize=(14, 5))
    plt.plot(y_true, c=next(cycol), markevery=5)
    plt.plot(y_predict, c=next(cycol), markevery=5)
    plt.legend(['y_true', 'y_predict'])
    plt.xlabel('时间')
    plt.ylabel('功率(kW)')
    plt.show()   
    
    return 0
error_and_plot(df_vmd[-96:,-1], np.sum(y_predict[:, :-1], axis=1) )

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1363030.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端Web系统架构设计

文章目录 1.目录结构定义2. 路由封装2.1 API路由定义2.2 组件路由定义 3. Axios请求开发4. 环境变量封装5. storage模块封装(sessionStorage, localStorage)6. 公共函数封装(日期,金额,权限..)7. 通用交互定义(删除二次确认,类别,面包屑...)8. 接口全貌概览 1.目录结构定义 2. …

Flume基础知识(十):Flume 聚合实战

1&#xff09;案例需求&#xff1a; hadoop100上的 Flume-1 监控文件/opt/module/group.log&#xff0c; hadoop101上的 Flume-2 监控某一个端口的数据流&#xff0c; Flume-1 与 Flume-2 将数据发送给 hadoop102 上的 Flume-3&#xff0c;Flume-3 将最终数据打印 到控制台。…

基于Java实现全功能电子商城

&#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩项目推荐订阅&#x1f447;&#x1f3fb; 不然下次找不到哟 基于SpringBoot的旅游网站 基于SpringBoot的MusiQ音乐网站 感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及…

【数据库】视图索引执行计划多表查询面试题

文章目录 一、视图1.1 概念1.2 视图与数据表的区别1.3 优点1.4 语法1.5 实例 二、索引2.1 什么是索引2.2.为什么要使用索引2.3 优缺点2.4 何时不使用索引2.5 索引何时失效2.6 索引分类2.6.1.普通索引2.6.2.唯一索引2.6.3.主键索引2.6.4.组合索引2.6.5.全文索引 三、执行计划3.1…

2024.1.5 关于 二叉平衡树(AVL 树)详解

目录 二叉搜索树 二叉搜索树的简介 二叉搜索树的查找 二叉搜索树的效率 AVL树 AVL 树的简介 AVL 树的实现 AVL树的旋转 右单旋 左单旋 左右双旋 右左双旋 完整 AVL树插入代码 验证 AVL 树 AVL 树的性能 二叉搜索树 要想了解关于二叉平衡树的相关知识&#xff0c;了…

mnn-llm: 大语言模型端侧CPU推理优化

在大语言模型(LLM)端侧部署上&#xff0c;基于 MNN 实现的 mnn-llm 项目已经展现出业界领先的性能&#xff0c;特别是在 ARM 架构的 CPU 上。目前利用 mnn-llm 的推理能力&#xff0c;qwen-1.8b在mnn-llm的驱动下能够在移动端达到端侧实时会话的能力&#xff0c;能够在较低内存…

安全与认证Week3

目录 Key Management 密钥管理 密钥交换、证书 密钥的类别 密钥管理方面 密钥分发问题 密钥分发方案 混合密钥分发 公钥分发 公钥证书 X.509 理解X.509 X.509证书包含 X.509使用过程 X.509身份验证服务 X.509版本3 取消 由X.509引申关于CA 用户认证、身份管理…

手机上下载 Linux 系统

我们首先要下载 Ternux 点击下载以及vnc viewer (提取码&#xff1a;d9sX)&#xff0c;需要魔法才行 下载完以后我们打开 Ternux 敲第一个命令 pkg upgrade 这个命令是用来跟新软件的 敲完命令就直接回车&#xff0c;如果遇到需要输入 Y/N 的地方全部输入 Y 下一步 #启动TMOE…

HackTheBox - Medium - Linux - Ambassador

Ambassador Ambassador 是一台中等难度的 Linux 机器&#xff0c;用于解决硬编码的明文凭据留在旧版本代码中的问题。首先&#xff0c;“Grafana”CVE &#xff08;“CVE-2021-43798”&#xff09; 用于读取目标上的任意文件。在研究了服务的常见配置方式后&#xff0c;将在其…

原生JS调用OpenAI GPT接口并实现ChatGPT逐字输出效果

效果&#xff1a; 猜你感兴趣&#xff1a;springbootvue实现ChatGPT逐字输出打字效果 附源码&#xff0c;也是小弟原创&#xff0c;感谢支持&#xff01; 没废话&#xff0c;上代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><me…

CRM的request管理笔记

1 request类型 request有两种&#xff0c;device request和link request。 link request link req是对link进行精确控制。 link req是对每个link的请求&#xff0c;比如某一帧是否需要bubble recovery、某一帧是否需要长曝光等feature。device request 对一个设备进行每帧控制…

Linux系统IO—探索输入输出操作的奥秘

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;HEART BEAT—YOASOBI 2:20━━━━━━️&#x1f49f;──────── 5:35 &#x1f504; ◀️ ⏸ ▶️ ☰ …

如何通过绘制【学习曲线】来判断模型是否【过拟合】

学习曲线是一种图形化工具&#xff0c;用于展示模型在训练集和验证集&#xff08;或测试集&#xff09;上的性能随着训练样本数量的增加而如何变化。它可以帮助我们理解模型是否受益于更多的训练数据&#xff0c;以及模型是否可能存在过拟合或欠拟合问题。学习曲线的x轴通常是训…

Win11开始菜单怎么改成经典模式-Win11切换Win10风格开始菜单方法

Win11切换Win10风格开始菜单方法 方法一&#xff1a; 1. 在Win11电脑上下载一个“Startallback”软件&#xff0c;下载安装完成后&#xff0c;在“控制面板”里打开该软件。 2. 打开后&#xff0c;在“欢迎界面”&#xff0c;选择使用“Windows10主题样式”并重启电脑即可。…

CodeWave智能开发平台--03--目标:应用创建--06变量作用域和前后端服务逻辑

摘要 本文是网易数帆CodeWave智能开发平台系列的第08篇&#xff0c;主要介绍了基于CodeWave平台文档的新手入门进行学习&#xff0c;实现一个完整的应用&#xff0c;本文主要完成06变量作用域和前后端服务逻辑 CodeWave智能开发平台的08次接触 CodeWave参考资源 网易数帆Co…

使用C#发送邮箱验证码

使用C#发送邮箱验证码 在很多应用程序中&#xff0c;我们需要使用邮箱来进行用户身份验证。其中一种常见的方式是通过发送验证码到用户的邮箱&#xff0c;然后要求用户输入该验证码进行验证。本文将介绍如何使用 C# 发送邮箱验证码。 声明 验证码登录没有用任何的工具&#…

Linux22.04系统安装显卡驱动,cuda,cudnn流程

1. 安装显卡驱动 ubuntu-drivers deices显示所有适配显卡的驱动型号&#xff0c;recommended为推荐安装 安装 sudo apt install nvidia-driver-440重启 sudo reboot验证 nvidia-smi2. 安装cuda 在 CUDA Toolkit 的下载页面选择系统版本和安装方式&#xff0c;下载并运行…

Vue基础知识三

一 VUE脚手架 1.1 说明 Vue 脚手架是 Vue 官方提供的标准化开发工具&#xff08;开发平台&#xff09;。脚手架最新的版本是 4.x&#xff08;脚手架版本与vue版本无关&#xff0c;我们这里使用脚手架的版本是4.x&#xff09;。文档: https://cli.vuejs.org/zh/。 脚手架官网…

使用Spring Cache优化数据库访问

使用Spring Cache优化数据库访问 在这篇博客中&#xff0c;我们将学习如何使用Spring Cache来优化数据库访问&#xff0c;提高系统性能。我们将创建一个简单的图书管理应用作为示例&#xff0c;并演示如何通过缓存减少对数据库的频繁查询。 1. 项目结构 首先&#xff0c;我们…

【影刀RPA_如何使用影刀的企业微信指令?】

思路&#xff1a;先用python代码过一遍&#xff0c;再将必要参数填到指令里面。 第一步&#xff1a; 1、在企业微信后台新建应用&#xff0c;设置消息接收地址&#xff08;需要服务器的公网ip地址&#xff09;&#xff0c;进行签名验证。然后&#xff0c;从浏览器中查询ip地址…