基于VMD分解的VMD-CNN-LSTM时间序列预测模型实现

技术

结合VMD、CNN和LSTM的方法,可以充分利用它们各自的优势,实现对复杂非线性信号的高效建模和预测,通过VMD将原始信号分解为多个模态分量,然后将这些分量作为CNN-LSTM模型的输入,可以更好地捕捉信号的局部特征和时空关系,从而提高了模型的预测能力和泛化能力,本文旨在探讨VMD-CNN-LSTM方法在信号处理和时间序列预测中的应用,重点介绍其算法实现和实验结果

1. VMD-LSTM参考

基于VMD分解的VMD-LSTM时间序列预测模型实现,大力提升预测精度!

VMD-LSTM将VMD用于对原始时间序列进行分解,得到多个本征模态函数, 每个本征模态函数代表了原始信号在不同频率和振幅上的成分,具有更好的局部特征表示,将这些本征模态函数作为输入序列,每个模态分别构建一个LSTM预测模型进行学习预测,从而提高模型的预测性能,在接下来将引入CNN探讨在相同数据集上VMD-CNN-LSTM与VMD-LSTM模型精度比较

picture.image

2. VMD-CNN-LSTM流程图

picture.image

2. 代码实现

2.1 数据解读


          
import pandas as pd
          
df = pd.read_excel('数据.xlsx',index_col=0, parse_dates=['数据时间'])
          
import matplotlib.pyplot as plt
          
plt.rcParams['font.sans-serif'] = 'SimHei' # 设置中文显示
          
plt.rcParams['axes.unicode_minus'] = False
          
plt.figure(figsize=(15, 5))
          
plt.plot(df['总有功功率(kw)'], label='原始数据', color='r',  alpha=0.3)
          
plt.title('时序图')
          
plt.grid(True)
          
plt.legend()
          
plt.show()
      

picture.image

在电力行业,对每日功率波动进行准确预测对于电网调度和能源规划至关重要。通过深度学习模型,可以更好地理解数据的复杂关系,从而提高预测的准确性,首先,加载数据(此数据已经过一定的异常值、缺失值处理)该数据为每日平均总有功功率(kw)

2.2 CNN-LSTM模型建立


          
# 0-1标准化
          
arr_max = np.max(np.array(df))
          
arr_min = np.min(np.array(df))
          
data_bz = (np.array(df)-arr_min)/(arr_max-arr_min)
          
data_bz = data_bz.ravel() # 转换为一维数组
          
def dataset(data, win_size=12):
          

          
    X = []  # 用于存储输入特征的列表
          
    Y = []  # 用于存储目标值的列表
          

          
    # 遍历数据,形成样本窗口
          
    for i in range(len(data) - win_size):
          
        temp_x = data[i:i + win_size]  # 提取窗口大小范围内的输入特征
          
        temp_y = data[i + win_size]    # 提取对应的目标值
          
        X.append(temp_x)
          
        Y.append(temp_y)
          

          
    # 转换列表为 NumPy 数组
          
    X = np.asarray(X)
          
    Y = np.asarray(Y)
          

          
    return X, Y
          
 
          
data_x, data_y = dataset(data_bz, 12)
          
data_x = np.expand_dims(data_x, axis=2) # 为Conv1D扩展维度
          

          
from tensorflow.keras.models import Sequential
          
from tensorflow.keras.layers import LSTM, Dense, Conv1D, MaxPooling1D, Flatten
          
import matplotlib.pyplot as plt
          
from sklearn.model_selection import train_test_split
          
from sklearn import metrics
          
from tensorflow.keras.layers import TimeDistributed
          
plt.rcParams['font.sans-serif'] = 'SimHei' # 设置中文显示
          
plt.rcParams['axes.unicode_minus'] = False
          

          

          
train_x, test_x, train_y, test_y = train_test_split(data_x, data_y, test_size=0.2, shuffle=False)
          
cnn_lstm = Sequential()
          
cnn_lstm.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(train_x.shape[1], train_x.shape[2])))
          
cnn_lstm.add(MaxPooling1D(pool_size=2))
          
cnn_lstm.add(LSTM(256))
          
cnn_lstm.add(Dense(1, activation='sigmoid'))
          
cnn_lstm.compile(loss='mse', optimizer='adam')
          
history = cnn_lstm.fit(train_x, train_y, epochs=18, batch_size=64, validation_split=0.2, shuffle=False)
          

          
plt.plot(history.history['loss'])
          
plt.plot(history.history['val_loss'], c='r')
          
plt.legend(['loss', 'val_loss'])
          
plt.show()
          

          
y_pred = cnn_lstm.predict(test_x)
          
# 计算均方误差(MSE)
          
mse = metrics.mean_squared_error(test_y, np.array([i for arr in y_pred for i in arr]))
          
# 计算均方根误差(RMSE)
          
rmse = np.sqrt(mse)
          
# 计算平均绝对误差(MAE)
          
mae = metrics.mean_absolute_error(test_y, np.array([i for arr in y_pred for i in arr]))
          
from sklearn.metrics import r2_score  # 拟合优度
          
r2 = r2_score(test_y, np.array([i for arr in y_pred for i in arr]))
          
print("均方误差 (MSE):", mse)
          
print("均方根误差 (RMSE):", rmse)
          
print("平均绝对误差 (MAE):", mae)
          
print("拟合优度 (R^2):", r2)
      

picture.image

在这里没有使用包装器(TimeDistributed)处理数据序列,而是直接将数据输入到模型中,通常会导致模型只能处理固定长度的序列,这意味着模型只能接受固定长度的输入序列,并且不会自动适应不同长度的序列,使用包装器处理数据序列可以让模型更灵活地处理不同长度的序列,因为包装器会自动处理序列长度的变化,并将相同的操作应用于每个时间步。这样可以使模型更好地适应不同长度的序列,并且可以提高模型的性能和泛化能力


          
def predict_future_values(model, sequence, future_steps):
          
    prediction_results = []
          
    for _ in range(future_steps):
          
        # 检查序列的维度并调整形状
          
        if len(sequence.shape) == 1:
          
            sequence = sequence.reshape(1, sequence.shape[0], 1)
          
        elif len(sequence.shape) == 2:
          
            sequence = sequence.reshape(1, sequence.shape[0], sequence.shape[1])
          
        # 对当前序列进行预测
          
        next_day_prediction = model.predict(sequence)
          
        # 将预测结果加入到结果列表中
          
        prediction_results.append(next_day_prediction[0, 0])
          
        # 更新序列,舍弃第一个时间步,将预测结果加入序列末尾
          
        sequence = np.append(sequence[:, 1:, :], next_day_prediction.reshape(1, 1, 1), axis=1)
          

          
    return prediction_results
          

          
sequence = test_x[-1]
          
future_predictions = predict_future_values(cnn_lstm, sequence, 30)
          
print("未来30天的预测值:", future_predictions)
          

          
series = np.array(future_predictions)*(arr_max-arr_min)+arr_min
          

          
plt.figure(figsize=(15,4), dpi =300)
          
plt.plot(test_y*(arr_max-arr_min)+arr_min, color = 'c', label = '每日实际功率波动曲线')
          
plt.plot(y_pred*(arr_max-arr_min)+arr_min, color = 'r', label = '预测每日功率波动曲线')
          
plt.plot(range(len(y_pred), len(y_pred)+len(series)), series, color = 'b', label = '向后预测30天')
          
plt.title('每日实际功率波动与预测每日功率波动比对图')
          
plt.grid(True)
          
plt.xlabel('时间')
          
plt.ylabel('总有功功率(kw)')
          
plt.legend()
          
plt.show()
      

picture.image

2.3 VMD分解时间序列


          
from vmdpy import VMD 
          
# VMD 的一些参数
          
alpha = 1300        # 适度的频带宽度约束
          
tau = 0.            # 容忍噪声(没有严格的保真度要求)
          
K = 5               # 3个模态
          
DC = 0              # 不强制直流分量
          
init = 1            # 均匀初始化角频率
          
tol = 1e-7
          

          
# 运行 VMD
          
u, u_hat, omega = VMD(df['总有功功率(kw)'], alpha, tau, K, DC, init, tol)
          
# 可视化分解后的 5 个 IMF
          
# 可视化分解后的 5 个 IMF
          
plt.figure(figsize=(15, 8))
          

          
for i in range(K):
          
    plt.subplot(K, 1, i+1)
          
    plt.plot(u[i, :])
          
    plt.title(f'IMF {i+1}')
          
    plt.xlabel('时间')
          
    plt.ylabel('幅度')
          

          
plt.tight_layout()
          
plt.show()
          

          
# 保存每个 IMF 到不同的 DataFrame
          
imf_dataframes = {}
          
for i in range(len(u)):
          
    imf_name = 'imf_{}'.format(i+1)
          
    imf_dataframes[imf_name] = pd.DataFrame({'Value': u[i]})
      

picture.image

通过代码,可以清晰地展示VMD分解后得到的每个本征模态函数,以及得到分解后的数据(如果为了进一步提高模型可以引入遗传算法等找到最优参数),接下来将对每一个分解数据进行CNN-LSTM模型建立

2.3.1 IMF1-CNN-LSTM


          
arr_max_1 = np.max(np.array(imf_dataframes['imf_1']))
          
arr_min_1 = np.min(np.array(imf_dataframes['imf_1']))
          
data_bz_1 = (np.array(imf_dataframes['imf_1'])-arr_min_1)/(arr_max_1-arr_min_1)
          

          
data_bz_1 = data_bz_1.ravel() # 转换为一维数组
          
data_x_1, data_y_1 = dataset(data_bz_1, 12)
          
data_x_1 = np.expand_dims(data_x_1, axis=2)
          

          
train_x_1, test_x_1, train_y_1, test_y_1 = train_test_split(data_x_1, data_y_1, test_size = 0.2, shuffle = False)
          

          
cnn_lstm_1 =Sequential()
          
cnn_lstm_1.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(train_x_1.shape[1], train_x_1.shape[2])))
          
cnn_lstm_1.add(MaxPooling1D(pool_size=2))
          
cnn_lstm_1.add(LSTM(256))
          
cnn_lstm_1.add(Dense(1, activation='sigmoid'))
          
cnn_lstm_1.compile(loss='mse', optimizer='adam')
          
history_1 = cnn_lstm_1.fit(train_x_1, train_y_1, epochs=18, batch_size=64, validation_split=0.2, shuffle=False)
          

          

          
plt.plot(history_1.history['loss'])
          
plt.plot(history_1.history['val_loss'], c='r')
          
plt.legend(['loss', 'val_loss'])
          
plt.show()
          

          
y_pred_1 = cnn_lstm_1.predict(test_x_1)
          
# 计算均方误差(MSE)
          
mse = metrics.mean_squared_error(test_y_1, np.array([i for arr in y_pred_1 for i in arr]))
          
# 计算均方根误差(RMSE)
          
rmse = np.sqrt(mse)
          
# 计算平均绝对误差(MAE)
          
mae = metrics.mean_absolute_error(test_y_1, np.array([i for arr in y_pred_1 for i in arr]))
          
from sklearn.metrics import r2_score # 拟合优度
          
r2 = r2_score(test_y_1, np.array([i for arr in y_pred_1 for i in arr]))
          
print("均方误差 (MSE):", mse)
          
print("均方根误差 (RMSE):", rmse)
          
print("平均绝对误差 (MAE):", mae)
          
print("拟合优度:", r2)
          

          

          
sequence = test_x_1[-1]
          
future_predictions = predict_future_values(cnn_lstm_1, sequence, 30)
          
print("未来30天的预测值:", future_predictions)
          

          
series_1 = np.array(future_predictions)*(arr_max_1-arr_min_1)+arr_min_1
          

          
plt.figure(figsize=(15,4), dpi =300)
          
plt.plot(test_y_1*(arr_max_1-arr_min_1)+arr_min_1, color = 'c', label = 'imf_1测试集实际功率波动曲线')
          
plt.plot(y_pred_1*(arr_max_1-arr_min_1)+arr_min_1, color = 'r', label = 'imf_1测试集预测功率波动曲线')
          
plt.plot(range(len(y_pred_1), len(y_pred_1)+len(series_1)), series_1, color = 'b', label = 'imf_1向后预测30天功率波动曲线')
          
plt.title('imf_1')
          
plt.grid(True)
          
plt.xlabel('时间')
          
plt.ylabel('总有功功率(kw)')
          
plt.legend()
          
plt.show()
      

picture.image

picture.image

2.3.2 IMF2-CNN-LSTM


          
arr_max_2 = np.max(np.array(imf_dataframes['imf_2']))
          
arr_min_2 = np.min(np.array(imf_dataframes['imf_2']))
          
data_bz_2 = (np.array(imf_dataframes['imf_2'])-arr_min_2)/(arr_max_2-arr_min_2)
          

          
data_bz_2 = data_bz_2.ravel() # 转换为一维数组
          
data_x_2, data_y_2 = dataset(data_bz_2, 12)
          
data_x_2 = np.expand_dims(data_x_2, axis=2)
          

          
train_x_2, test_x_2, train_y_2, test_y_2 = train_test_split(data_x_2, data_y_2, test_size = 0.2, shuffle = False)
          

          
cnn_lstm_2 = Sequential()
          
cnn_lstm_2.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(train_x_2.shape[1], train_x_2.shape[2])))
          
cnn_lstm_2.add(MaxPooling1D(pool_size=2))
          
cnn_lstm_2.add(LSTM(256, return_sequences=True))  # 添加一个额外的LSTM层
          
cnn_lstm_2.add(LSTM(128))  # 添加第二个LSTM层
          
cnn_lstm_2.add(Dense(64, activation='relu'))  # 添加一个全连接层
          
cnn_lstm_2.add(Dense(1, activation='sigmoid'))
          
cnn_lstm_2.compile(loss='mse', optimizer='adam')
          
history_2 = cnn_lstm_2.fit(train_x_2, train_y_2, epochs=50, batch_size=64, validation_split=0.2, shuffle=False)
          

          

          
plt.plot(history_2.history['loss'])
          
plt.plot(history_2.history['val_loss'], c='r')
          
plt.legend(['loss', 'val_loss'])
          
plt.show()
          

          
y_pred_2 = cnn_lstm_2.predict(test_x_2)
          
# 计算均方误差(MSE)
          
mse = metrics.mean_squared_error(test_y_2, np.array([i for arr in y_pred_2 for i in arr]))
          
# 计算均方根误差(RMSE)
          
rmse = np.sqrt(mse)
          
# 计算平均绝对误差(MAE)
          
mae = metrics.mean_absolute_error(test_y_2, np.array([i for arr in y_pred_2 for i in arr]))
          
from sklearn.metrics import r2_score # 拟合优度
          
r2 = r2_score(test_y_2, np.array([i for arr in y_pred_2 for i in arr]))
          
print("均方误差 (MSE):", mse)
          
print("均方根误差 (RMSE):", rmse)
          
print("平均绝对误差 (MAE):", mae)
          
print("拟合优度:", r2)
          

          

          
sequence = test_x_2[-1]
          
future_predictions = predict_future_values(cnn_lstm_2, sequence, 30)
          
print("未来30天的预测值:", future_predictions)
          

          
series_2 = np.array(future_predictions)*(arr_max_2-arr_min_2)+arr_min_2
          

          
plt.figure(figsize=(15,4), dpi =300)
          
plt.plot(test_y_2*(arr_max_2-arr_min_2)+arr_min_2, color = 'c', label = 'imf_2测试集实际功率波动曲线')
          
plt.plot(y_pred_2*(arr_max_2-arr_min_2)+arr_min_2, color = 'r', label = 'imf_2测试集预测功率波动曲线')
          
plt.plot(range(len(y_pred_2), len(y_pred_2)+len(series_2)), series_2, color = 'b', label = 'imf_2向后预测30天功率波动曲线')
          
plt.title('imf_2')
          
plt.grid(True)
          
plt.xlabel('时间')
          
plt.ylabel('总有功功率(kw)')
          
plt.legend()
          
plt.show()
      

picture.image

picture.image

2.3.3 IMF3-CNN-LSTM


          
arr_max_3 = np.max(np.array(imf_dataframes['imf_3']))
          
arr_min_3 = np.min(np.array(imf_dataframes['imf_3']))
          
data_bz_3 = (np.array(imf_dataframes['imf_3'])-arr_min_3)/(arr_max_3-arr_min_3)
          

          
data_bz_3 = data_bz_3.ravel() # 转换为一维数组
          
data_x_3, data_y_3 = dataset(data_bz_3, 12)
          
data_x_3 = np.expand_dims(data_x_3, axis=2)
          

          
train_x_3, test_x_3, train_y_3, test_y_3 = train_test_split(data_x_3, data_y_3, test_size = 0.2, shuffle = False)
          

          
cnn_lstm_3 =Sequential()
          
cnn_lstm_3.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(train_x_3.shape[1], train_x_3.shape[2])))
          
cnn_lstm_3.add(MaxPooling1D(pool_size=2))
          
cnn_lstm_3.add(LSTM(256))
          
cnn_lstm_3.add(Dense(1, activation='sigmoid'))
          
cnn_lstm_3.compile(loss='mse', optimizer='adam')
          
history_3 = cnn_lstm_3.fit(train_x_3, train_y_3, epochs=18, batch_size=64, validation_split=0.2, shuffle=False)
          

          

          
plt.plot(history_3.history['loss'])
          
plt.plot(history_3.history['val_loss'], c='r')
          
plt.legend(['loss', 'val_loss'])
          
plt.show()
          

          
y_pred_3 = cnn_lstm_3.predict(test_x_3)
          
# 计算均方误差(MSE)
          
mse = metrics.mean_squared_error(test_y_3, np.array([i for arr in y_pred_3 for i in arr]))
          
# 计算均方根误差(RMSE)
          
rmse = np.sqrt(mse)
          
# 计算平均绝对误差(MAE)
          
mae = metrics.mean_absolute_error(test_y_3, np.array([i for arr in y_pred_3 for i in arr]))
          
from sklearn.metrics import r2_score # 拟合优度
          
r2 = r2_score(test_y_3, np.array([i for arr in y_pred_3 for i in arr]))
          
print("均方误差 (MSE):", mse)
          
print("均方根误差 (RMSE):", rmse)
          
print("平均绝对误差 (MAE):", mae)
          
print("拟合优度:", r2)
          

          

          
sequence = test_x_3[-1]
          
future_predictions = predict_future_values(cnn_lstm_3, sequence, 30)
          
print("未来30天的预测值:", future_predictions)
          

          
series_3 = np.array(future_predictions)*(arr_max_3-arr_min_3)+arr_min_3
          

          
plt.figure(figsize=(15,4), dpi =300)
          
plt.plot(test_y_3*(arr_max_3-arr_min_3)+arr_min_3, color = 'c', label = 'imf_3测试集实际功率波动曲线')
          
plt.plot(y_pred_3*(arr_max_3-arr_min_3)+arr_min_3, color = 'r', label = 'imf_3测试集预测功率波动曲线')
          
plt.plot(range(len(y_pred_3), len(y_pred_3)+len(series_3)), series_3, color = 'b', label = 'imf_3向后预测30天功率波动曲线')
          
plt.title('imf_3')
          
plt.grid(True)
          
plt.xlabel('时间')
          
plt.ylabel('总有功功率(kw)')
          
plt.legend()
          
plt.show()
      

picture.image

picture.image

2.3.4 IMF4-CNN-LSTM


          
arr_max_4 = np.max(np.array(imf_dataframes['imf_4']))
          
arr_min_4 = np.min(np.array(imf_dataframes['imf_4']))
          
data_bz_4 = (np.array(imf_dataframes['imf_4'])-arr_min_4)/(arr_max_4-arr_min_4)
          

          
data_bz_4 = data_bz_4.ravel() # 转换为一维数组
          
data_x_4, data_y_4 = dataset(data_bz_4, 12)
          
data_x_4 = np.expand_dims(data_x_4, axis=2)
          

          
train_x_4, test_x_4, train_y_4, test_y_4 = train_test_split(data_x_4, data_y_4, test_size = 0.2, shuffle = False)
          

          
cnn_lstm_4 =Sequential()
          
cnn_lstm_4.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(train_x_4.shape[1], train_x_4.shape[2])))
          
cnn_lstm_4.add(MaxPooling1D(pool_size=2))
          
cnn_lstm_4.add(LSTM(256))
          
cnn_lstm_4.add(Dense(1, activation='sigmoid'))
          
cnn_lstm_4.compile(loss='mse', optimizer='adam')
          
history_4 = cnn_lstm_4.fit(train_x_4, train_y_4, epochs=18, batch_size=64, validation_split=0.2, shuffle=False)
          

          

          
plt.plot(history_4.history['loss'])
          
plt.plot(history_4.history['val_loss'], c='r')
          
plt.legend(['loss', 'val_loss'])
          
plt.show()
          

          
y_pred_4 = cnn_lstm_4.predict(test_x_4)
          
# 计算均方误差(MSE)
          
mse = metrics.mean_squared_error(test_y_4, np.array([i for arr in y_pred_4 for i in arr]))
          
# 计算均方根误差(RMSE)
          
rmse = np.sqrt(mse)
          
# 计算平均绝对误差(MAE)
          
mae = metrics.mean_absolute_error(test_y_4, np.array([i for arr in y_pred_4 for i in arr]))
          
from sklearn.metrics import r2_score # 拟合优度
          
r2 = r2_score(test_y_4, np.array([i for arr in y_pred_4 for i in arr]))
          
print("均方误差 (MSE):", mse)
          
print("均方根误差 (RMSE):", rmse)
          
print("平均绝对误差 (MAE):", mae)
          
print("拟合优度:", r2)
          

          

          
sequence = test_x_4[-1]
          
future_predictions = predict_future_values(cnn_lstm_4, sequence, 30)
          
print("未来30天的预测值:", future_predictions)
          

          
series_4 = np.array(future_predictions)*(arr_max_4-arr_min_4)+arr_min_4
          

          
plt.figure(figsize=(15,4), dpi =300)
          
plt.plot(test_y_4*(arr_max_4-arr_min_4)+arr_min_4, color = 'c', label = 'imf_4测试集实际功率波动曲线')
          
plt.plot(y_pred_4*(arr_max_4-arr_min_4)+arr_min_4, color = 'r', label = 'imf_4测试集预测功率波动曲线')
          
plt.plot(range(len(y_pred_4), len(y_pred_4)+len(series_4)), series_4, color = 'b', label = 'imf_4向后预测30天功率波动曲线')
          
plt.title('imf_4')
          
plt.grid(True)
          
plt.xlabel('时间')
          
plt.ylabel('总有功功率(kw)')
          
plt.legend()
          
plt.show()
      

picture.image

picture.image

2.3.5 IMF5-CNN-LSTM


          
arr_max_5 = np.max(np.array(imf_dataframes['imf_5']))
          
arr_min_5 = np.min(np.array(imf_dataframes['imf_5']))
          
data_bz_5 = (np.array(imf_dataframes['imf_5'])-arr_min_5)/(arr_max_5-arr_min_5)
          

          
data_bz_5 = data_bz_5.ravel() # 转换为一维数组
          
data_x_5, data_y_5 = dataset(data_bz_5, 12)
          
data_x_5 = np.expand_dims(data_x_5, axis=2)
          

          
train_x_5, test_x_5, train_y_5, test_y_5 = train_test_split(data_x_5, data_y_5, test_size = 0.2, shuffle = False)
          

          
cnn_lstm_5 =Sequential()
          
cnn_lstm_5.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(train_x_5.shape[1], train_x_5.shape[2])))
          
cnn_lstm_5.add(MaxPooling1D(pool_size=2))
          
cnn_lstm_5.add(LSTM(256))
          
cnn_lstm_5.add(Dense(1, activation='sigmoid'))
          
cnn_lstm_5.compile(loss='mse', optimizer='adam')
          
history_5 = cnn_lstm_5.fit(train_x_5, train_y_5, epochs=18, batch_size=64, validation_split=0.2, shuffle=False)
          

          

          
plt.plot(history_5.history['loss'])
          
plt.plot(history_5.history['val_loss'], c='r')
          
plt.legend(['loss', 'val_loss'])
          
plt.show()
          

          
y_pred_5 = cnn_lstm_5.predict(test_x_5)
          
# 计算均方误差(MSE)
          
mse = metrics.mean_squared_error(test_y_5, np.array([i for arr in y_pred_5 for i in arr]))
          
# 计算均方根误差(RMSE)
          
rmse = np.sqrt(mse)
          
# 计算平均绝对误差(MAE)
          
mae = metrics.mean_absolute_error(test_y_5, np.array([i for arr in y_pred_5 for i in arr]))
          
from sklearn.metrics import r2_score # 拟合优度
          
r2 = r2_score(test_y_5, np.array([i for arr in y_pred_5 for i in arr]))
          
print("均方误差 (MSE):", mse)
          
print("均方根误差 (RMSE):", rmse)
          
print("平均绝对误差 (MAE):", mae)
          
print("拟合优度:", r2)
          

          

          
sequence = test_x_5[-1]
          
future_predictions = predict_future_values(cnn_lstm_5, sequence, 30)
          
print("未来30天的预测值:", future_predictions)
          

          
series_5 = np.array(future_predictions)*(arr_max_5-arr_min_5)+arr_min_5
          

          
plt.figure(figsize=(15,4), dpi =300)
          
plt.plot(test_y_5*(arr_max_5-arr_min_5)+arr_min_5, color = 'c', label = 'imf_5测试集实际功率波动曲线')
          
plt.plot(y_pred_5*(arr_max_5-arr_min_5)+arr_min_5, color = 'r', label = 'imf_5测试集预测功率波动曲线')
          
plt.plot(range(len(y_pred_5), len(y_pred_5)+len(series_5)), series_5, color = 'b', label = 'imf_5向后预测30天功率波动曲线')
          
plt.title('imf_5')
          
plt.grid(True)
          
plt.xlabel('时间')
          
plt.ylabel('总有功功率(kw)')
          
plt.legend()
          
plt.show()
      

picture.image

picture.image

2.4 VMD-CNN-LSTM


          
pred = y_pred_1*(arr_max_1-arr_min_1)+arr_min_1+y_pred_2*(arr_max_2-arr_min_2)+arr_min_2+y_pred_3*(arr_max_3-arr_min_3)+arr_min_3+y_pred_4*(arr_max_4-arr_min_4)+arr_min_4+y_pred_5*(arr_max_5-arr_min_5)+arr_min_5
          
prophet = series_1+series_2+series_3+series_4+series_5
          
test = test_y*(arr_max-arr_min)+arr_min
          

          
plt.figure(figsize=(15,4), dpi =300)
          
plt.plot(test, color = 'c', label = '测试集实际功率波动曲线')
          
plt.plot(pred, color = 'r', label = 'vmd_lstm测试集预测功率波动曲线')
          
plt.plot(range(len(pred), len(pred)+len(prophet)), prophet, color = 'b', label = 'vmd_lstm向后预测30天功率波动曲线')
          
plt.title('vmd_lstm')
          
plt.grid(True)
          
plt.xlabel('时间')
          
plt.ylabel('总有功功率(kw)')
          
plt.legend()
          
plt.show()
      

picture.image

2.5 模型评价指标比较


          
# 计算均方误差(MSE)
          
mse = metrics.mean_squared_error(test, np.array([i for arr in pred for i in arr]))
          
# 计算均方根误差(RMSE)
          
rmse = np.sqrt(mse)
          
# 计算平均绝对误差(MAE)
          
mae = metrics.mean_absolute_error(test, np.array([i for arr in pred for i in arr]))
          
from sklearn.metrics import r2_score # 拟合优度
          
r2 = r2_score(test, np.array([i for arr in pred for i in arr]))
          
print("均方误差 (MSE):", mse)
          
print("均方根误差 (RMSE):", rmse)
          
print("平均绝对误差 (MAE):", mae)
          
print("拟合优度:", r2)
      

picture.image

这里的均方误差、均方根误差、平均绝对误差都是对归一化还原数据进行计算得到,前文的CNN-LSTM模型评价指标是对归一化的数据计算得到,为了比较两个模型的差异对前文CNN-LSTM模型也进行还原数据计算评价指标


          
# 更好对比对lstm数据进行归一化还原输出评价指标
          
# 计算均方误差(MSE)
          
test = test_y*(arr_max-arr_min)+arr_min
          
pred_1 = y_pred*(arr_max-arr_min)+arr_min
          
mse = metrics.mean_squared_error(test, np.array([i for arr in pred_1 for i in arr]))
          
# 计算均方根误差(RMSE)
          
rmse = np.sqrt(mse)
          
# 计算平均绝对误差(MAE)
          
mae = metrics.mean_absolute_error(test, np.array([i for arr in pred_1 for i in arr]))
          
from sklearn.metrics import r2_score # 拟合优度
          
r2 = r2_score(test, np.array([i for arr in pred_1 for i in arr]))
          
print("均方误差 (MSE):", mse)
          
print("均方根误差 (RMSE):", rmse)
          
print("平均绝对误差 (MAE):", mae)
          
print("拟合优度:", r2)
      

picture.image

picture.image

结合文章’基于VMD分解的VMD-LSTM时间序列预测模型实现,大力提升预测精度!‘给出完整的模型精度表,综合来看,在同一个数据集下,VMD-CNN-LSTM模型在所有指标(MSE、RMSE、MAE、R2)上表现最佳,其次是VMD-LSTM模型,而LSTM模型表现最差

3. 往期推荐

基于VMD分解的VMD-LSTM时间序列预测模型实现,大力提升预测精度!

长短期记忆网络LSTM在时序数据预测演示

时间序列预测神器Prophet python实现

特征工程——数据转换

可解释性机器学习库Shapash——鸢尾花XGBoost分类解释实现

LightGBM模型房价预测实现

如果你对类似于这样的文章感兴趣。

欢迎关注、点赞、转发~

0
0
0
0
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论