数模创新时序预测算法 | CEEMDAN-CNN-LSTM算法

在这里插入图片描述欢迎来到Easy数模!我们致力于分享简明、高质的数学建模知识,以实现数模技术普及和平权,今天我承接上篇CEEMDAN-LSTM算法,来继续聊一聊改进算法CEEMDAN-CNN-LSTM!欢迎关注Easy数模!带你一步步成为数模大佬!


在这个数据驱动的时代,精准预测未来需求、市场趋势甚至是健康状况,已成为各行各业保持竞争力的关键。

无论是电网中的电力负荷,金融市场的股价波动,还是零售行业的销量预测,我们都需要从复杂的时间序列数据中提取潜在规律。

今天,我们将介绍一套被称为“CEEMDAN-CNN-LSTM”的前沿算法,它结合了数据分解和深度学习的优势,让我们一起深入了解,这套“黑科技”算法如何让未来预测更精确、更智能!

算法白话文介绍

我们首先拿电力负荷预测场景来解读,预测电力负荷其实就像天气预报一样,必须得先把各种“天气因素”搞清楚。想象一下,电力负荷的变化就像天气,既有“气温”这种短期波动,也有“季节”这种长期趋势,要让预测精准,得把这两方面的“玄机”都搞透了。

那怎么搞呢?这就是我们今天要说的这套CEEMDAN-CNN-LSTM大法:

  1. CEEMDAN:分解隐藏的“天气图”
    想象电力负荷的原始数据是个复杂的“天气系统”,CEEMDAN方法相当于一个高科技显微镜,把这个系统层层剖析,分成了多个内在模态函数(IMF),也就是不同频率的“子天气图”。每张“子天气图”代表一个频率的波动,比如有的图显示“日常波动”,有的显示“月度变化”,各司其职又相互独立。这样一来,原本复杂的负荷数据就被拆成几部分,便于分析了。

  2. CNN:细细分析每张“天气图”
    CNN(卷积神经网络)是数据处理的能手,尤其适合抓住数据的“微妙纹路”。我们让CNN对每张“子天气图”进行处理,把数据中的局部特征挖掘出来。就好比天气预报员通过气压、温度等局部数据来推测天气趋势。这样,CNN帮助我们提取了数据中的短期波动特征,为后续的深度分析奠定了基础。

  3. LSTM:记住“昨天的天气”,预测“明天的温度”
    这里的LSTM(长短期记忆网络)好比一个超强记忆的天气预报员,它会记住昨天、前天等多天的数据,然后根据这些历史记录推测未来的负荷情况。LSTM尤其擅长处理时间序列,能从时间上的前后关联性中找到规律,用历史信息来更准确地预测未来。

  4. 多步预测:一口气预测未来几天
    电力需求预测往往需要提前预测多个时间点的值,而不仅仅是预测接下来的一个时刻。这就是所谓的多步预测。借助LSTM,我们可以设定未来多个时间步的预测范围,一步一步地推出未来的负荷需求,就像天气预报可以给出未来几天的降水和温度变化。

  5. 误差评估:预测到底准不准?
    最后一步,自然是评估一下预测效果。我们用了MSE、RMSE、MAE、MAPE和 ( R^2 ) 这几个“评分员”来打分,看预测结果是否“接地气”,准不准。预测准确率越高,我们的算法就越靠谱。

模型结构

本算法主要分为三个部分:数据分解、特征提取与时序预测。
在这里插入图片描述

  1. CEEMDAN数据分解
    CEEMDAN(Complete Ensemble Empirical Mode Decomposition with Adaptive Noise)是一种信号分解方法,将复杂时间序列分解成多个内在模态函数(IMFs)。每个IMF代表了不同频率的信息,有助于将数据分解成较为独立的分量,便于特征提取。

    • 公式:设原始电力负荷时间序列为 X ( t ) X(t) X(t),CEEMDAN分解得到的内在模态函数为 I M F i ( t ) IMF_i(t) IMFi(t),则:
      X ( t ) = ∑ i = 1 n I M F i ( t ) + R ( t ) X(t) = \sum_{i=1}^{n} IMF_i(t) + R(t) X(t)=i=1nIMFi(t)+R(t)
      其中 R ( t ) R(t) R(t) 为残差项,表示分解后的低频趋势部分。
  2. 卷积神经网络(CNN)特征提取
    卷积神经网络在图像和序列数据处理中表现优异,尤其适合提取局部特征。本文利用一维卷积层(1D-CNN)提取每个IMF中的局部高频特征,进一步输入至LSTM网络中,以捕捉复杂的短期依赖关系。

    • 公式:一维卷积计算过程:
      y [ i ] = ∑ j = 1 k x [ i + j − 1 ] ⋅ w [ j ] y[i] = \sum_{j=1}^{k} x[i+j-1] \cdot w[j] y[i]=j=1kx[i+j1]w[j]
      其中, x x x 为输入数据, w w w 为卷积核, k k k 为卷积核大小。
  3. LSTM网络的时序预测
    长短时记忆网络(LSTM)对时序数据中的长短期依赖具有良好记忆和建模能力。模型将从CNN提取的特征传入LSTM,进一步预测未来的电力负荷数值。通过在LSTM中设置多步预测,模型可以逐步输出未来多个时间步的预测值。

    • 公式:LSTM单元计算公式:
      f t = σ ( W f ⋅ [ h t − 1 , x t ] + b f ) f_t = \sigma(W_f \cdot [h_{t-1}, x_t] + b_f) ft=σ(Wf[ht1,xt]+bf)
      i t = σ ( W i ⋅ [ h t − 1 , x t ] + b i ) i_t = \sigma(W_i \cdot [h_{t-1}, x_t] + b_i) it=σ(Wi[ht1,xt]+bi)
      C ~ t = tanh ⁡ ( W C ⋅ [ h t − 1 , x t ] + b C ) \tilde{C}_t = \tanh(W_C \cdot [h_{t-1}, x_t] + b_C) C~t=tanh(WC[ht1,xt]+bC)
      C t = f t ⋅ C t − 1 + i t ⋅ C ~ t C_t = f_t \cdot C_{t-1} + i_t \cdot \tilde{C}_t Ct=ftCt1+itC~t
      o t = σ ( W o ⋅ [ h t − 1 , x t ] + b o ) o_t = \sigma(W_o \cdot [h_{t-1}, x_t] + b_o) ot=σ(Wo[ht1,xt]+bo)
      h t = o t ⋅ tanh ⁡ ( C t ) h_t = o_t \cdot \tanh(C_t) ht=ottanh(Ct)
      其中, f t f_t ft i t i_t it o t o_t ot 分别为遗忘门、输入门和输出门; h t h_t ht 为隐藏状态, C t C_t Ct 为单元状态。
  4. 误差评估指标
    为了评估预测效果,我们采用均方误差(MSE)、均方根误差(RMSE)、平均绝对误差(MAE)、平均绝对百分比误差(MAPE)和 R 2 R^2 R2 评估模型性能。

    • 均方误差(MSE)
      M S E = 1 n ∑ i = 1 n ( y i − y ^ i ) 2 MSE = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 MSE=n1i=1n(yiy^i)2
    • 均方根误差(RMSE)
      R M S E = 1 n ∑ i = 1 n ( y i − y ^ i ) 2 RMSE = \sqrt{\frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2} RMSE=n1i=1n(yiy^i)2
    • 平均绝对误差(MAE)
      M A E = 1 n ∑ i = 1 n ∣ y i − y ^ i ∣ MAE = \frac{1}{n} \sum_{i=1}^{n} |y_i - \hat{y}_i| MAE=n1i=1nyiy^i
    • 平均绝对百分比误差(MAPE)
      M A P E = 100 % n ∑ i = 1 n ∣ y i − y ^ i y i ∣ MAPE = \frac{100\%}{n} \sum_{i=1}^{n} \left| \frac{y_i - \hat{y}_i}{y_i} \right| MAPE=n100%i=1n yiyiy^i
    • R 2 R^2 R2:衡量模型拟合度,值越接近1表示模型越准确。
      R 2 = 1 − ∑ i = 1 n ( y i − y ^ i ) 2 ∑ i = 1 n ( y i − y ˉ ) 2 R^2 = 1 - \frac{\sum_{i=1}^{n} (y_i - \hat{y}_i)^2}{\sum_{i=1}^{n} (y_i - \bar{y})^2} R2=1i=1n(yiyˉ)2i=1n(yiy^i)2

python代码案例

导入必要库

首先导入各类Python库,包括pandasnumpymatplotlibtensorflow.keras等,用于数据处理、深度学习模型构建、特征预处理和评估等任务。

import os  # 系统操作功能
import math  # 提供数学计算功能
import pandas as pd  # 用于数据处理和分析
import numpy as np  # 用于数值计算和数据操作
from math import sqrt  # 用于计算平方根
from numpy import concatenate  # 数组拼接
import matplotlib.pyplot as plt  # 数据可视化
from sklearn.preprocessing import MinMaxScaler, StandardScaler, LabelEncoder  # 特征缩放与标签编码
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score  # 误差计算
from tensorflow.keras.layers import *  # 导入深度学习网络各类层
from tensorflow.keras.models import *  # 导入神经网络模型构建工具
from scipy.io import savemat, loadmat  # 读取和保存MATLAB文件
from sklearn.neural_network import MLPRegressor  # 多层感知器回归模型
from keras.callbacks import LearningRateScheduler  # 动态学习率调整
import warnings  # 消除警告信息
from prettytable import PrettyTable  # 美观打印表格结果
warnings.filterwarnings("ignore")  # 取消警告
  • pandasnumpy用于加载和操作数据。
  • tensorflow.keras.layers中的卷积层(Conv1D)、池化层(MaxPooling1D)、LSTM和全连接层(Dense)用于构建深度学习模型。
  • MinMaxScaler用于将数据标准化到 [0,1] 区间,mean_squared_error等用于计算误差。

数据加载与预处理

通过pandas库加载电力负荷数据的CSV文件和CEEMDAN分解的Excel文件,并确保数据类型一致。

dataset = pd.read_csv("电力负荷预测数据.csv", encoding='gb2312')
dataset_vmd = pd.read_excel("CEEMDAN.xlsx")
values = dataset.values[:, 1:].astype('float32')  # 只取特征数据
values_vmd = dataset_vmd.values.astype('float32')  # CEEMDAN分解数据
  • dataset:加载原始电力负荷数据。
  • dataset_vmd:加载CEEMDAN分解的IMF数据。
  • valuesvalues_vmd分别存储特征数据和分解后的数据,并转换为 float32 类型,确保数据一致性。

数据构建函数

data_collation函数使用滑窗方法处理数据,将多步预测的数据构建为输入和输出对。

def data_collation(data, n_in, n_out, or_dim, scroll_window, num_samples):
    res = np.zeros((num_samples, n_in * or_dim + n_out))
    for i in range(num_samples):
        h1 = data[scroll_window * i: n_in + scroll_window * i, 0:or_dim]
        h2 = h1.reshape(1, n_in * or_dim)
        h3 = data[n_in + scroll_window * i: n_in + scroll_window * i + n_out, -1].T
        res[i, :] = np.hstack((h2, h3))
    return res
  • n_in:输入的时间步长(可以调节),例如 n_in=5 表示使用前5行数据作为模型输入。
  • n_out:输出的预测步数(可以调节),例如 n_out=1 表示预测未来1步的数据。
  • scroll_window:滑动窗口的移动步长(可以调节),例如 scroll_window=1 表示每次滑动1行。
  • 函数返回二维数组 res,每一行包含 n_in 步的输入和 n_out 步的输出。

CNN-LSTM模型构建函数

cnn_lstm_model函数定义了一个CNN-LSTM结构,用于时序数据的特征提取和预测。

def cnn_lstm_model():
    inputs = Input(shape=(vp_train.shape[1], vp_train.shape[2]))
    conv1d = Conv1D(filters=32, kernel_size=2, activation='relu')(inputs)
    maxpooling = MaxPooling1D(pool_size=2)(conv1d)
    reshaped = Reshape((-1, 32))(maxpooling)
    lstm = LSTM(128, activation='selu', return_sequences=False)(reshaped)
    outputs = Dense(vt_train.shape[1])(lstm)
    model = Model(inputs=inputs, outputs=outputs)
    model.compile(loss='mse', optimizer='Adam')
    model.summary()
    return model
  • Conv1D:一维卷积层,32个过滤器,卷积核大小为2,activation='relu'。该层提取局部特征。
  • MaxPooling1D:最大池化层,pool_size=2 表示池化核大小为2。
  • Reshape:将数据的形状调整为 (-1, 32),以匹配LSTM层的输入。
  • LSTM:LSTM层,128个神经元,activation='selu',处理时间序列特征。
  • Dense:全连接层,输出的神经元数量与 vt_train.shape[1] 相同,用于生成预测输出。
  • model.compile(loss='mse', optimizer='Adam'):指定损失函数为MSE(均方误差),优化器为Adam。

数据构建与归一化

将特征和标签划分为训练集和测试集,且在构建完训练集和测试集后进行归一化处理。

n_train_number = int(num_samples * 0.85)  # 85%用于训练
Xtrain = combined_data[:n_train_number, :n_in * or_dim]
Ytrain = combined_data[:n_train_number, n_in * or_dim:]
Xtest = combined_data[n_train_number:, :n_in * or_dim]
Ytest = combined_data[n_train_number:, n_in * or_dim:]
m_in = MinMaxScaler()
vp_train = m_in.fit_transform(Xtrain)
vp_test = m_in.transform(Xtest)
m_out = MinMaxScaler()
vt_train = m_out.fit_transform(Ytrain)
vt_test = m_out.transform(Ytest)
  • n_train_number:设置训练集大小(可调),例如 85% 表示数据的85%用于训练。
  • XtrainYtrain:训练集的输入和输出数据。
  • XtestYtest:测试集的输入和输出数据。
  • MinMaxScaler用于将数据归一化到 [0, 1] 区间,提升模型的训练效果。

模型训练与预测

使用构建好的CNN-LSTM模型进行训练,并对测试集生成预测。

model = cnn_lstm_model()
model.fit(vp_train, vt_train, batch_size=32, epochs=50, validation_split=0.25, verbose=2)
yhat = model.predict(vp_test)
yy = m_out.inverse_transform(yhat.reshape(num_samples - n_train_number, n_out))
predicted_data.append(yy)
actual_data.append(Ytest)
  • batch_size=32:每次迭代的样本数(可调),例如 batch_size=32 表示每批次处理32个样本。
  • epochs=50:训练轮数(可调),例如 epochs=50 表示数据迭代50次。
  • validation_split=0.25:25%数据用于验证。
  • yhat为预测值,反归一化后得到实际预测值。

模型评估

定义evaluate_forecasts函数,使用多种指标评估模型性能。

def evaluate_forecasts(Ytest, predicted_data, n_out):
    table = PrettyTable(['测试集指标','MSE', 'RMSE', 'MAE', 'MAPE','R2'])
    for i in range(n_out):
        actual = [float(row[i]) for row in Ytest]
        predicted = [float(row[i]) for row in predicted_data]
        mse = mean_squared_error(actual, predicted)
        rmse = sqrt(mse)
        mae = mean_absolute_error(actual, predicted)
        MApe = mape(actual

, predicted)
        r2 = r2_score(actual, predicted)
        strr = '预测结果指标:' if n_out == 1 else '第' + str(i + 1) + '步预测结果指标:'
        table.add_row([strr, mse, rmse, mae, f"{MApe}%", f"{r2*100}%"])
    return table
  • 使用MSE、RMSE、MAE、MAPE和 R 2 R^2 R2 评估模型的预测效果。
  • PrettyTable以表格形式展示各项指标,直观了解模型性能。

预测结果绘图

使用matplotlib绘制预测和实际值的对比图,直观展示预测效果。

for ii in range(n_out):
    plt.style.use('cyberpunk')
    plt.figure(figsize=(10, 2), dpi=300)
    x = range(1, len(actual_test) + 1)
    plt.xticks(x[::int((len(actual_test)+1))])
    plt.plot(x, pre_test[:,ii], linestyle="--", linewidth=0.5, label='predict')
    plt.plot(x, actual_test[:,ii], linestyle="-", linewidth=0.5,label='Real')
    plt.legend(loc='upper right', frameon=False)
    plt.xlabel("Sample points", fontsize=5)
    plt.ylabel("value", fontsize=5)
    plt.title(f"{ii+1} step of CEEMDAN-CNN-LSTM prediction\nMAPE: {mape(actual_test[:,ii], pre_test[:,ii])} %")
plt.show()
  • plt.plot绘制预测值和实际值,linestyle="--" 设置预测值为虚线,实际值为实线。
  • x轴为样本点,y轴为值,标题显示预测步数和MAPE误差。

模型优化

最后,模型引入注意力机制(Attention Mechanism)可以提高CEEMDAN-CNN-LSTM算法在预测中的表现。

Attention机制允许模型在处理时间序列数据时,动态分配不同时间步的权重,使模型能够关注对预测结果影响较大的关键数据点。

这在长序列预测中尤其有效,能够缓解信息随时间衰减的问题,提高预测精度。通过在LSTM层后加入Attention层,模型能更好地捕捉数据中的重要特征,优化未来趋势的预测效果。

感兴趣的小伙伴可以大胆尝试一下哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值