1.3 參考文獻

2. 代碼實現(xiàn)

2.1 數(shù)據(jù)解讀

import pandas as pd
df = pd.read_excel('數(shù)據(jù).xlsx',index_col=0, parse_dates=['數(shù)據(jù)時間'])
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='原始數(shù)據(jù)', color='r', alpha=0.3)
plt.title('時序圖')
plt.grid(True)
plt.legend()
plt.show()

在電力行業(yè),對每日功率波動進行準確預測對于電網(wǎng)調(diào)度和能源規(guī)劃至關重要。通過深度學習模型,可以更好地理解數(shù)據(jù)的復雜關系,從而提高預測的準確性,首先,加載數(shù)據(jù)(此數(shù)據(jù)已經(jīng)過一定的異常值、缺失值處理)該數(shù)據(jù)為每日平均總有功功率(kw)。

2.2 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() # 轉(zhuǎn)換為一維數(shù)組
def dataset(data, win_size=12):

X = [] # 用于存儲輸入特征的列表
Y = [] # 用于存儲目標值的列表

# 遍歷數(shù)據(jù),形成樣本窗口
for i in range(len(data) - win_size):
temp_x = data[i:i + win_size] # 提取窗口大小范圍內(nèi)的輸入特征
temp_y = data[i + win_size] # 提取對應的目標值
X.append(temp_x)
Y.append(temp_y)

# 轉(zhuǎn)換列表為 NumPy 數(shù)組
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=1)
from sklearn.model_selection import train_test_split
from keras.layers import LSTM, Dense
from keras.models import Sequential

train_x, test_x, train_y, test_y = train_test_split(data_x, data_y, test_size = 0.2, shuffle = False)

# 使用 Sequential API 構(gòu)建模型
model =Sequential()

# LSTM 層中有 256 個隱藏單元 input_shape參數(shù)指定輸入數(shù)據(jù)的形狀,這里為(1, 時間步數(shù))
model.add(LSTM(256, input_shape=(train_x.shape[1], train_x.shape[2])))

# 這里定義激活函數(shù)為sigmoid(請文對輸出數(shù)據(jù)進行歸一化處理)
model.add(Dense(1, activation='sigmoid'))
# 編譯模型
# 損失函數(shù)(loss)為均方誤差(Mean Squared Error),適用于回歸問題
# 優(yōu)化器(optimizer)為 Adam,是一種常用的優(yōu)化算法
model.compile(loss='mse', optimizer='adam')

# 訓練模型
# epochs:訓練的輪數(shù),即遍歷整個訓練數(shù)據(jù)的次數(shù)
# batch_size:每批次訓練的樣本數(shù)
# validation_split:用于在訓練過程中劃分一部分數(shù)據(jù)作為驗證集,這里是取訓練數(shù)據(jù)的20%作為驗證集
# shuffle:是否在每個 epoch 之前隨機打亂訓練數(shù)據(jù)
history = model.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()
from sklearn import metrics
# 計算均方誤差(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 # 擬合優(yōu)度
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("擬合優(yōu)度:", r2)
def predict_all(model, last_x, num=24):
pred_y=[]
for i in range(num):
temp_y = model.predict(last_x)
pred_y.append(temp_y[0,0])
temp_y = np.expand_dims(temp_y, 0)
last_x = np.concatenate([last_x[:,:,1:], temp_y], axis = 2)
return np.asarray(pred_y)

last_x = test_x[-1]
last_x = np.expand_dims(last_x, 0)

series_pre = predict_all(model, last_x, num=30)
series = series_pre*(arr_max-arr_min)+arr_min # 未來30天波動預測值歸一化數(shù)據(jù)還原

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

這里將不進行代碼解讀,代碼解讀請參考往期文章末尾也將給出往期文章鏈接,通過建立LSTM模型可以發(fā)現(xiàn)普通的LSTM模型對于預測任務的表現(xiàn)不夠理想,預測結(jié)果與實際結(jié)果之間存在較大的誤差,擬合優(yōu)度也不高,說明模型并未很好地擬合數(shù)據(jù)的變異性??赡苄枰M一步優(yōu)化模型結(jié)構(gòu)、調(diào)整超參數(shù)或者嘗試其他模型來提高預測精度,為了提高模型精確度接下來將引入模型VMD-LSTM進行模型建立。

2.3 VMD分解時間序列

from vmdpy import VMD 
# VMD 的一些參數(shù)
alpha = 1300 # 適度的頻帶寬度約束
tau = 0. # 容忍噪聲(沒有嚴格的保真度要求)
K = 5 # 3個模態(tài)
DC = 0 # 不強制直流分量
init = 1 # 均勻初始化角頻率
tol = 1e-7

# 運行 VMD
u, u_hat, omega = VMD(df['總有功功率(kw)'], alpha, tau, K, DC, init, tol)
# 可視化分解后的 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]})

通過代碼,可以清晰地展示VMD分解后得到的每個本征模態(tài)函數(shù),以及得到分解后的數(shù)據(jù),接下來將對每一個分解數(shù)據(jù)進行LSTM模型建立。

2.3.1 IMF1—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() # 轉(zhuǎn)換為一維數(shù)組
data_x_1, data_y_1 = dataset(data_bz_1, 12)
data_x_1 = np.expand_dims(data_x_1, axis=1)
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)
model_1 =Sequential()
model_1.add(LSTM(256, input_shape=(train_x_1.shape[1], train_x_1.shape[2])))
model_1.add(Dense(1, activation='sigmoid'))
model_1.compile(loss='mse', optimizer='adam')
history_1 = model_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 = model_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 # 擬合優(yōu)度
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("擬合優(yōu)度:", r2)
last_x_1 = test_x_1[-1]
last_x_1 = np.expand_dims(last_x_1, 0)

series_pre_1 = predict_all(model_1, last_x_1, num=30)
series_1 = series_pre_1*(arr_max_1-arr_min_1)+arr_min_1 # 未來10天波動預測值歸一化數(shù)據(jù)還原

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, color = 'b', label = 'imf_1向后預測30天功率波動曲線')
plt.title('imf_1')
plt.grid(True)
plt.xlabel('時間')
plt.ylabel('總有功功率(kw)')
plt.legend()
plt.show()

2.3.2?IMF2—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() # 轉(zhuǎn)換為一維數(shù)組
data_x_2, data_y_2 = dataset(data_bz_2, 12)
data_x_2 = np.expand_dims(data_x_2, axis=1)
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)
model_2 =Sequential()
model_2.add(LSTM(256, input_shape=(train_x_2.shape[1], train_x_2.shape[2])))
model_2.add(Dense(1, activation='sigmoid'))
model_2.compile(loss='mse', optimizer='adam')
history_2 = model_2.fit(train_x_2, train_y_2, epochs=18, 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 = model_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 # 擬合優(yōu)度
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("擬合優(yōu)度:", r2)

last_x_2 = test_x_2[-1]
last_x_2 = np.expand_dims(last_x_2, 0)

series_pre_2 = predict_all(model_2, last_x_2, num=30)
series_2 = series_pre_2*(arr_max_2-arr_min_2)+arr_min_2 # 未來10天波動預測值歸一化數(shù)據(jù)還原

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

2.3.3 IMF3—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() # 轉(zhuǎn)換為一維數(shù)組
data_x_3, data_y_3 = dataset(data_bz_3, 12)
data_x_3 = np.expand_dims(data_x_3, axis=1)
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)
model_3 =Sequential()
model_3.add(LSTM(256, input_shape=(train_x_3.shape[1], train_x_3.shape[2])))
model_3.add(Dense(1, activation='sigmoid'))
model_3.compile(loss='mse', optimizer='adam')
history_3 = model_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 = model_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 # 擬合優(yōu)度
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("擬合優(yōu)度:", r2)

last_x_3 = test_x_3[-1]
last_x_3 = np.expand_dims(last_x_3, 0)

series_pre_3 = predict_all(model_3, last_x_3, num=30)
series_3 = series_pre_3*(arr_max_3-arr_min_3)+arr_min_3 # 未來10天波動預測值歸一化數(shù)據(jù)還原

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

2.3.4 IMF4—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() # 轉(zhuǎn)換為一維數(shù)組
data_x_4, data_y_4 = dataset(data_bz_4, 12)
data_x_4 = np.expand_dims(data_x_4, axis=1)
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)
model_4 =Sequential()
model_4.add(LSTM(256, input_shape=(train_x_4.shape[1], train_x_4.shape[2])))
model_4.add(Dense(1, activation='sigmoid'))
model_4.compile(loss='mse', optimizer='adam')
history_4 = model_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 = model_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 # 擬合優(yōu)度
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("擬合優(yōu)度:", r2)

last_x_4 = test_x_4[-1]
last_x_4 = np.expand_dims(last_x_4, 0)

series_pre_4 = predict_all(model_4, last_x_4, num=30)
series_4 = series_pre_4*(arr_max_4-arr_min_4)+arr_min_4 # 未來10天波動預測值歸一化數(shù)據(jù)還原

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

2.3.5?IMF5—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() # 轉(zhuǎn)換為一維數(shù)組
data_x_5, data_y_5 = dataset(data_bz_5, 12)
data_x_5 = np.expand_dims(data_x_5, axis=1)
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)
model_5 =Sequential()
model_5.add(LSTM(256, input_shape=(train_x_5.shape[1], train_x_5.shape[2])))
model_5.add(Dense(1, activation='sigmoid'))
model_5.compile(loss='mse', optimizer='adam')
history_5 = model_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 = model_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 # 擬合優(yōu)度
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("擬合優(yōu)度:", r2)

last_x_5 = test_x_5[-1]
last_x_5 = np.expand_dims(last_x_5, 0)

series_pre_5 = predict_all(model_5, last_x_5, num=30)
series_5 = series_pre_5*(arr_max_5-arr_min_5)+arr_min_5 # 未來10天波動預測值歸一化數(shù)據(jù)還原

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

這里的模型雖然是一模一樣的只是更改了數(shù)據(jù)集沒有利用循環(huán)來進行建立模型是為了去強調(diào)每次建立的LSTM模型可以修改相關參數(shù)進行模型優(yōu)化,并不影響VMD-LSTM最后的構(gòu)建。

如果不需要參數(shù)修改,直接進行for循環(huán)構(gòu)建模型省略代碼復雜度請參考以下代碼。

from vmdpy import VMD 
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense
from tensorflow.keras import metrics

plt.rcParams['font.sans-serif'] = 'SimHei' # 設置中文顯示
plt.rcParams['axes.unicode_minus'] = False

# VMD 的一些參數(shù)
alpha = 1300 # 適度的頻帶寬度約束
tau = 0. # 容忍噪聲(沒有嚴格的保真度要求)
K = 5 # 5個模態(tài)
DC = 0 # 不強制直流分量
init = 1 # 均勻初始化角頻率
tol = 1e-7

# 運行 VMD
u, _, _ = VMD(df['總有功功率(kw)'], alpha, tau, K, DC, init, tol)

# 創(chuàng)建 LSTM 模型
def create_lstm_model(input_shape):
model = Sequential()
model.add(LSTM(256, input_shape=input_shape))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='mse', optimizer='adam')
return model

# 準備訓練數(shù)據(jù)
def prepare_data(imf_data):
arr_max = np.max(np.array(imf_data))
arr_min = np.min(np.array(imf_data))
data_bz = (np.array(imf_data) - arr_min) / (arr_max - arr_min)
data_bz = data_bz.ravel() # 轉(zhuǎn)換為一維數(shù)組
data_x, data_y = dataset(data_bz, 12)
data_x = np.expand_dims(data_x, axis=1)
train_x, test_x, train_y, test_y = train_test_split(data_x, data_y, test_size=0.2, shuffle=False)
return train_x, test_x, train_y, test_y, arr_max, arr_min

# 訓練模型并進行預測
def train_and_predict(model, train_x, train_y, test_x, test_y, arr_max, arr_min):
history = model.fit(train_x, train_y, epochs=18, batch_size=64, validation_split=0.2, shuffle=False)
y_pred = model.predict(test_x)
mse = mean_squared_error(test_y, y_pred)
rmse = np.sqrt(mse)
mae = mean_absolute_error(test_y, y_pred)
r2 = r2_score(test_y, y_pred)
print("均方誤差 (MSE):", mse)
print("均方根誤差 (RMSE):", rmse)
print("平均絕對誤差 (MAE):", mae)
print("擬合優(yōu)度:", r2)

last_x = test_x[-1]
last_x = np.expand_dims(last_x, 0)

series_pre = predict_all(model, last_x, num=30)
series = series_pre * (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('IMF')
plt.grid(True)
plt.xlabel('時間')
plt.ylabel('總有功功率(kw)')
plt.legend()
plt.show()

# 循環(huán)處理每個 IMFs
for i, imf in enumerate(u):
imf_name = f'imf_{i+1}'
train_x, test_x, train_y, test_y, arr_max, arr_min = prepare_data(imf)
model = create_lstm_model((train_x.shape[1], train_x.shape[2]))
train_and_predict(model, train_x, train_y, test_x, test_y, arr_max, arr_min)

2.4?VMD—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()

2.5 VMD—LSTM與LSTM模型評價指標比較

# 計算均方誤差(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 # 擬合優(yōu)度
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("擬合優(yōu)度:", r2)

這里的均方誤差、均方根誤差、平均絕對誤差都是對歸一化還原數(shù)據(jù)進行計算得到,前文的LSTM模型評價指標是對歸一化的數(shù)據(jù)計算得到,為了比較兩個模型的差異對前文LSTM模型也進行還原數(shù)據(jù)計算評價指標。

# 更好對比對lstm數(shù)據(jù)進行歸一化還原輸出評價指標
# 計算均方誤差(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 # 擬合優(yōu)度
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("擬合優(yōu)度:", r2)
# 定義模型和評價指標
models = ['LSTM', 'VMD-LSTM']
metrics = ['MSE', 'RMSE', 'MAE', 'R2']
values = {
'LSTM': [433308080.1553673, 20816.053424109174, 14396.407640033123, 0.490216331578196],
'VMD-LSTM': [169117880.61997274, 13004.53307966006, 9261.236531374, 0.801034096693379]
}

# 繪制柱狀圖
fig, axs = plt.subplots(2, 2, figsize=(12, 10))

for i, metric in enumerate(metrics):
ax = axs[i//2, i%2]
ax.bar(models, [values[model][i] for model in models], color=['skyblue', 'lightgreen'])
ax.set_title(metric)
ax.set_xlabel('Model')
ax.set_ylabel(metric)

plt.tight_layout()
plt.show()

綜合來看,VMD-LSTM模型相對于普通的LSTM模型在各個評價指標上表現(xiàn)更好,具有更低的預測誤差、更高的預測精度和更好的數(shù)據(jù)擬合效果。

文章轉(zhuǎn)自微信公眾號@Python機器學習AI

上一篇:

特征選擇:Lasso和Ridge算法結(jié)合的彈性網(wǎng)絡回歸實現(xiàn)

下一篇:

可解釋性機器學習庫Shapash——鳶尾花XGBoost分類解釋實現(xiàn)

我們有何不同?

API服務商零注冊

多API并行試用

數(shù)據(jù)驅(qū)動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費