今儿再来和大家聊聊基于LSTM和ARIMA的混合模型在时间序列预测,这部分很常见也很重要,大家有空可以仔细看看~
另外,传统的统计方法如ARIMA模型能有效捕捉线性结构,但对复杂非线性模式的表现较弱。深度学习方法(如LSTM)在非线性时间序列上有良好表现。混合模型试图结合ARIMA与LSTM各自的优势,使模型既能处理时间序列中的线性趋势,又能捕捉复杂的非线性特征。
混合模型数学原理 ARIMA模型 ARIMA模型(Auto-Regressive Integrated Moving Average)是基于时间序列的自回归和滑动平均过程。它可以表示为 ARIMA(p, d, q),其中:
ARIMA模型公式:
对于给定的时间序列
,假设经过 次差分后达到平稳性,则ARIMA模型的表达为:
其中:
LSTM模型 LSTM(Long Short-Term Memory)是一种特殊的RNN,能够记忆较长的历史信息,适合处理非线性和长短期依赖的序列数据。LSTM的核心是通过门机制(输入门、遗忘门、输出门)控制信息流。
LSTM模型公式:
LSTM单元的计算包含以下步骤:
单元状态 :通过组合遗忘门和输入门,更新单元状态。
混合模型的组成与公式 对于给定时间序列 ,我们可以将其表示为线性部分 和非线性部分 的组合:
首先,我们用ARIMA对时间序列拟合线性部分 ,然后将残差序列(原序列减去ARIMA预测)用LSTM模型拟合非线性部分 ,得到最终的预测:
数据生成与特征分析 数据生成 我们生成包含趋势、季节性和噪声的时间序列,模拟现实中可能遇到的复杂数据。假设时间范围为0到200,趋势线性增加、季节性为正弦波、噪声为正态分布。
import numpy as npimport pandas as pdimport matplotlib.pyplot as plt# 生成合成数据 np.random.seed(0 ) time = np.arange(0 , 400 ) trend = time * 0.1 # 趋势项 seasonal = 10 * np.sin(time * 0.2 ) # 周期性 noise = np.random.normal(0 , 1 , len(time)) # 噪声项 series = trend + seasonal + noise# 存储在DataFrame中 df = pd.DataFrame({'Time' : time, 'Value' : series})
数据可视化 # 绘制时间序列图 plt.figure(figsize=(12 , 6 )) plt.plot(df['Time' ], df['Value' ], label='Synthetic Time Series' ) plt.title('Synthetic Time Series with Trend, Seasonality, and Noise' ) plt.xlabel('Time' ) plt.ylabel('Value' ) plt.legend() plt.show()
使用ARIMA拟合时间序列的线性部分
参数选择与模型拟合 我们使用AIC准则寻找最佳的 , , 参数组合。此处手动设定为 ARIMA(5, 1, 2),并使用模型拟合。
from statsmodels.tsa.arima.model import ARIMA# 使用ARIMA模型拟合时间序列的线性部分 model_arima = ARIMA(df['Value' ], order=(5 , 1 , 2 )) arima_result = model_arima.fit()# 生成预测值并绘制图形 df['ARIMA_Prediction' ] = arima_result.predict(start=1 , end=len(df)-1 , dynamic=False ) plt.figure(figsize=(12 , 6 )) plt.plot(df['Time' ], df['Value' ], label='Original Time Series' ) plt.plot(df['Time' ], df['ARIMA_Prediction' ], color='red' , label='ARIMA Prediction' ) plt.title('ARIMA Model Fitting' ) plt.xlabel('Time' ) plt.ylabel('Value' ) plt.legend() plt.show()
ARIMA模型输出分析 从拟合图中可以看到,ARIMA模型能够有效捕捉数据中的趋势和部分周期性,但在高频噪声部分表现不佳,这为LSTM捕捉非线性模式留出了空间。
使用LSTM拟合残差序列的非线性部分 残差计算与数据归一化 # 计算残差序列 df['Residual' ] = df['Value' ] - df['ARIMA_Prediction' ]# 数据归一化处理 from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler(feature_range=(0 , 1 )) residual_scaled = scaler.fit_transform(df['Residual' ].values.reshape(-1 , 1 ))
LSTM模型的数据准备 LSTM模型需要将数据转换为适合RNN输入格式的三维张量,定义一个函数来创建序列化的数据集。
# 创建LSTM数据集 def create_dataset (data, time_step=1 ) : X, Y = [], [] for i in range(len(data) - time_step - 1 ): X.append(data[i:(i + time_step), 0 ]) Y.append(data[i + time_step, 0 ]) return np.array(X), np.array(Y) time_step = 5 X_train, y_train = create_dataset(residual_scaled, time_step) X_train = X_train.reshape(X_train.shape[0 ], X_train.shape[1 ], 1 )
LSTM模型构建与训练 from keras.models import Sequentialfrom keras.layers import LSTM, Dense# 构建LSTM模型 model_lstm = Sequential([ LSTM(50 , return_sequences=True , input_shape=(time_step, 1 )), LSTM(50 , return_sequences=False ), Dense(25 ), Dense(1 ) ]) model_lstm.compile(optimizer='adam' , loss='mean_squared_error' ) model_lstm.fit(X_train, y_train, epochs=50 , batch_size=1
, verbose=2 )# 使用LSTM模型预测残差 lstm_predictions = model_lstm.predict(X_train) lstm_predictions = scaler.inverse_transform(lstm_predictions)
混合模型预测与最终可视化 混合模型预测 将ARIMA模型预测的线性部分与LSTM模型预测的非线性部分相加,得到最终的预测结果。这里假设ARIMA和LSTM的预测在时间上是对齐的,因此可以直接相加。
# 混合模型预测 df['Hybrid_Prediction' ] = df['ARIMA_Prediction' ][:len(lstm_predictions)] + lstm_predictions.flatten()# 绘制最终的混合模型预测结果 plt.figure(figsize=(12 , 6 )) plt.plot(df['Time' ], df['Value' ], label='Original Time Series' ) plt.plot(df['Time' ][:len(df['Hybrid_Prediction' ])], df['Hybrid_Prediction' ], color='purple' , label='Hybrid Model Prediction' ) plt.title('Hybrid Model Prediction (ARIMA + LSTM)' ) plt.xlabel('Time' ) plt.ylabel('Value' ) plt.legend() plt.show()
混合模型的最终预测效果。混合模型通过结合ARIMA模型的线性部分和LSTM模型捕捉的非线性残差,提供了比单独使用ARIMA或LSTM更精确的预测。
模型优化与调参流程 ARIMA模型的优化 ARIMA模型的核心优化在于选择合适的参数 、
、 。通常可以通过AIC(Akaike信息准则)或者BIC(贝叶斯信息准则)来进行模型选择,优化这三个参数。
ARIMA参数优化的步骤: 差分次数 :使用差分可以去除时间序列中的非平稳性。通常通过ADF检验(单位根检验)来判断是否需要差分。 自回归阶数 :通过观察ACF(自相关函数)图来确定。 移动平均阶数 :通过观察PACF(偏自相关函数)图来确定。 from statsmodels.graphics.tsaplots import plot_acf, plot_pacf# 画出ACF和PACF图,帮助选择p和q plt.figure(figsize=(12 , 6 )) plot_acf(df['Value' ], lags=40 , ax=plt.gca()) plt.title('ACF Plot' ) plt.show() plt.figure(figsize=(12 , 6 )) plot_pacf(df['Value' ], lags=40 , ax=plt.gca()) plt.title('PACF Plot' ) plt.show()
AIC和BIC优化:
通过循环不同的 、
、 参数组合,使用AIC和BIC选择最佳模型。 代码实现可以使用 auto_arima
(pmdarima
库)来自动选择最优参数。 from pmdarima import auto_arima# 自动选择最优ARIMA模型 auto_model = auto_arima(df['Value' ], seasonal=False , trace=True , error_action='ignore' , suppress_warnings=True ) auto_model.summary()
LSTM模型的优化 LSTM模型的优化主要涉及以下几个方面:
训练轮次 :过多的训练可能导致过拟合,过少的训练则可能导致欠拟合。LSTM模型的超参数优化 层数与神经元数 :通过增加LSTM的层数或每层的神经元数量可以增加模型的学习能力,但也会增加计算复杂度。训练批量大小和学习率 :调整批量大小(batch_size)和学习率(learning_rate)来提高训练的收敛速度和预测精度。训练轮次 :增加训练轮次可以进一步提高模型的预测精度,直到达到收敛。# 使用GridSearchCV或随机搜索来调优LSTM的超参数 from sklearn.model_selection import GridSearchCV# 设定参数网格 param_grid = { 'batch_size' : [16 , 32 ], 'epochs' : [50 , 100 ], 'optimizer'
: ['adam' , 'rmsprop' ], 'lstm_units' : [50 , 100 ] }# 使用GridSearch进行调参 # 实际操作时需要定义一个合适的LSTM模型训练函数
交叉验证 LSTM训练过程中可以使用交叉验证来检测是否发生过拟合。交叉验证可以帮助选择最佳超参数,避免因数据划分不当导致结果偏差。
# 可以使用KFold交叉验证来评估模型 from sklearn.model_selection import KFold kf = KFold(n_splits=5 )for train_index, val_index in kf.split(X_train): X_train_fold, X_val_fold = X_train[train_index], X_train[val_index] y_train_fold, y_val_fold = y_train[train_index], y_train[val_index] model_lstm.fit(X_train_fold, y_train_fold, epochs=50 , batch_size=32 , validation_data=(X_val_fold, y_val_fold))
综合优化 综合优化时,我们不仅要考虑ARIMA和LSTM的单独优化,还需要关注两者结合的效果。混合模型优化的关键在于如何选择ARIMA的线性部分与LSTM的非线性部分的加权比例,以及如何处理预测误差。
一种常用方法是加权平均法 ,根据ARIMA和LSTM的预测误差来动态调整两者的权重。
# 根据误差调整权重 arima_error = np.abs(df['Value' ] - df['ARIMA_Prediction' ]) lstm_error = np.abs(df['Residual' ] - lstm_predictions.flatten())# 计算加权系数 arima_weight = arima_error / (arima_error + lstm_error) lstm_weight = lstm_error / (arima_error + lstm_error)# 生成加权混合预测 df['Weighted_Hybrid_Prediction' ] = arima_weight * df['ARIMA_Prediction' ] + lstm_weight * lstm_predictions.flatten()# 绘制加权混合预测 plt.figure(figsize=(12 , 6 )) plt.plot(df['Time' ], df['Value' ], label='Original Time Series' ) plt.plot(df['Time' ][:len(df['Weighted_Hybrid_Prediction' ])], df['Weighted_Hybrid_Prediction' ], color='orange' , label='Weighted Hybrid Prediction' ) plt.title('Weighted Hybrid Model Prediction' ) plt.xlabel('Time' ) plt.ylabel('Value' ) plt.legend() plt.show()
通过使用ARIMA模型捕捉时间序列中的线性趋势部分,并通过LSTM模型捕捉非线性部分,我们构建了一个混合时间序列预测模型。与单独使用ARIMA或LSTM模型相比,混合模型能够更好地拟合复杂的时间序列数据,提供更加准确的预测。