机器学习算法实战案例:VMD-LSTM实现单变量多步光伏预测

文章目录

      • 机器学习算法实战案例系列
      • 答疑&技术交流
      • [1 数据处理](#1 数据处理)
        • [1.1 导入库文件](#1.1 导入库文件)
        • [1.2 导入数据集](#1.2 导入数据集)
        • [1.3 缺失值分析](#1.3 缺失值分析)
      • [2 VMD经验模态分解](#2 VMD经验模态分解)
      • [3 构造训练数据](#3 构造训练数据)
      • [4 LSTM模型训练](#4 LSTM模型训练)
      • [5 预测](#5 预测)

机器学习算法实战案例系列

答疑&技术交流

技术要学会分享、交流,不建议闭门造车。一个人可以走的很快、一堆人可以走的更远。

本文完整代码、相关资料、技术交流&答疑,均可加我们的交流群获取,群友已超过2000人,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友。

​方式①、微信搜索公众号:Python学习与数据挖掘 ,后台回复:加群

方式②、添加微信号:dkl88194,备注:来自CSDN + 技术交流

1 数据处理

1.1 导入库文件
python 复制代码
import matplotlib.pyplot as plt  

from sampen import sampen2  # sampen库用于计算样本熵

from vmdpy import VMD  # VMD分解库

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

from tensorflow.keras.callbacks import ReduceLROnPlateau, EarlyStopping

warnings.filterwarnings('ignore')  
1.2 导入数据集

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

python 复制代码
data_raw = pd.read_excel("E:\\课题\\08数据集\\新疆风电光伏数据\\光伏2019.xlsx")
python 复制代码
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))

    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])

            ax.axis('off')  # 如果数据列数小于子图数量,关闭多余的子图

    plt.subplots_adjust(hspace=0.6)

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

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

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

1.3 缺失值分析

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

python 复制代码
data_raw.info()

进一步统计缺失值

python 复制代码
data_raw.isnull().sum()

2 VMD经验模态分解

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

python 复制代码
def vmd_decompose(series=None, alpha=2000, tau=0, K=7, 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)]
python 复制代码
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)

    a.legend(loc='upper right',prop={'size': 14})

    plt.subplots_adjust(hspace=0.5)

将原始数据和分解后的模态合并

python 复制代码
df_vmd['sum'] = data_raw['实际发电功率(mw)']  # 将 data_raw['实际发电功率(mw)']添加到 df_vmd 中的 'sum' 列

这里利用VMD-LSTM进行预测的思路是通过VMD将原始功率分解为多个变量,然后将分解变量作为输入特征,将原始出力功率作为标签,将单变量转为多变量进行预测。

3 构造训练数据

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

python 复制代码
timesteps = 96*5 #构造x,为96*5个数据,表示每次用前96*5个数据作为一段

predict_steps = 96 #构造y,为96个数据,表示用后96个数据作为一段

length = 96 #预测多步,预测96个数据

通过前5天的timesteps数据预测后一天的数据predict_steps个,需要对数据集进行滚动划分(也就是前timesteps行的特征和后predict_steps行的标签训练,后面预测时就可通过timesteps行特征预测未来的predict_steps个标签)。因为是多变量,特征和标签分开划分,不然后面归一化会有信息泄露的问题。

python 复制代码
# 整体的思路也就是,前面通过前timesteps个数据训练后面的predict_steps个未来数据

# 预测时取出前timesteps个数据预测未来的predict_steps个未来数据。

def create_dataset(datasetx,datasety,timesteps=36,predict_size=6):

    for each in range(len(datasetx)-timesteps - predict_steps):

        x = datasetx[each:each+timesteps]

        y = datasety[each+timesteps:each+timesteps+predict_steps]

数据处理前,需要对数据进行归一化,按照上面的方法划分数据,这里返回划分的数据和归一化模型,函数的定义如下:

python 复制代码
def data_scaler(datax,datay):

    scaler1 = MinMaxScaler(feature_range=(0,1))

    scaler2 = MinMaxScaler(feature_range=(0,1))

    datax = scaler1.fit_transform(datax)

    datay = scaler2.fit_transform(datay)

    # 用前面的数据进行训练,留最后的数据进行预测

    trainx, trainy = create_dataset(datax[:-timesteps-predict_steps,:],datay[:-timesteps-predict_steps,0],timesteps, predict_steps)

    trainx = np.array(trainx)

    trainy = np.array(trainy)

    return trainx, trainy, scaler1, scaler2

然后对数据按照上面的函数进行划分和归一化。通过前5天的96*5数据预测后一天的数据96个,需要对数据集进行滚动划分(也就是前96*5行的特征和后96行的标签训练,后面预测时就可通过96*5行特征预测未来的96个标签)

python 复制代码
datay = df_vmd[:,-1].reshape(df_vmd.shape[0],1)

trainx, trainy, scaler1, scaler2 = data_scaler(datax, datay)

4 LSTM模型训练

首先搭建模型的常规操作,然后使用训练数据trainx和trainy进行训练,进行50个epochs的训练,每个batch包含128个样本(建议使用GPU进行训练)。预测并计算误差,训练好将模型保存,并进行可视化,将这些步骤封装为函数。

python 复制代码
def LSTM_model_train(trainx, trainy):

    gpus = tf.config.experimental.list_physical_devices(device_type='GPU')

        tf.config.experimental.set_memory_growth(gpu, True)

    start_time = datetime.datetime.now()

    model.add(LSTM(128, input_shape=(timesteps, feature_num), return_sequences=True))

    model.add(Dropout(0.5))

    model.add(LSTM(64, return_sequences=False))

    model.add(Dense(predict_steps))

    model.compile(loss="mean_squared_error", optimizer="adam")

    model.fit(trainx, trainy, epochs=50, batch_size=128)

    end_time = datetime.datetime.now()

    running_time = end_time - start_time

    model.save('vmd_lstm_model.h5')
python 复制代码
model = LSTM_model_train(trainx, trainy)

5 预测

首先加载训练好后的模型

python 复制代码
from tensorflow.keras.models import load_model

model = load_model('vmd_lstm_model.h5')

准备好需要预测的数据,训练时保留了6天的数据,将前5天的数据作为输入预测,将预测的结果和最后一天的真实值进行比较。

python 复制代码
y_true = datay[-timesteps-predict_steps:-timesteps]

x_pred = datax[-timesteps:]

预测并计算误差,并进行可视化,将这些步骤封装为函数。

python 复制代码
def predict_and_plot(x, y_true, model, scaler, timesteps):

    predict_x = np.reshape(x, (1, timesteps, feature_num))  

    predict_y = model.predict(predict_x)

    predict_y = scaler.inverse_transform(predict_y)

    y_predict.extend(predict_y[0])

    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)

    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'])
python 复制代码
y_predict_nowork = predict_and_plot(x_pred, y_true, model, scaler2, timesteps)

最后得到可视化结果,发下可视化结果并不是太好,可以通过调参和数据处理进一步提升模型预测效果。

相关推荐
卷福同学5 小时前
不用服务器,不用配环境,我10分钟上线了一个AI Agent
人工智能·后端·算法
码兄科技6 小时前
Java AI智能体开发实战:从零构建智能对话系统指南
java·开发语言·人工智能
Zik----6 小时前
CCswitch-code
人工智能
至乐活着7 小时前
深入解析跳表SkipList:原理、实现与性能优化实战
数据结构·算法·跳表·skiplist·java实现
AI科技星8 小时前
全域谱分析:无穷维超复数信息场分形统一场论 ——自然、量子、金融多重分形第一性原理完整体系(中英双语终稿)
人工智能·机器学习·金融·乖乖数学·全域数学
stormzhangV8 小时前
为什么你的 AI 像智障
人工智能
Jerry8 小时前
LeetCode 383. 赎金信
算法
ai产品老杨8 小时前
H264 H265视频分析常见问题和排查清单
人工智能·算法·音视频
项目经理老王8 小时前
OpenClaw无捆绑安装包,安全纯净版AI助手部署
人工智能·安全
Jerry9 小时前
LeetCode 454. 四数相加 II
算法