突破LSTM!结合ARIMA时间序列预测 !!
混合模型数学原理
ARIMA模型
ARIMA模型(Auto-Regressive Integrated Moving Average)是基于时间序列的自回归和滑动平均过程。它可以表示为 ARIMA(p, d, q),其中:
- p是自回归(AR)项的阶数。
- d是差分次数,用于消除非平稳性。
- q是滑动平均(MA)项的阶数。
ARIMA模型公式:
对于给定的时间序列y ,假设经过 d次差分后达到平稳性,则ARIMA模型的表达为:
LSTM模型
LSTM(Long Short-Term Memory)是一种特殊的RNN,能够记忆较长的历史信息,适合处理非线性和长短期依赖的序列数据。LSTM的核心是通过门机制(输入门、遗忘门、输出门)控制信息流。
LSTM模型公式:
LSTM单元的计算包含以下步骤:
混合模型的组成与公式
数据生成与特征分析
数据生成
我们生成包含趋势、季节性和噪声的时间序列,模拟现实中可能遇到的复杂数据。假设时间范围为0到200,趋势线性增加、季节性为正弦波、噪声为正态分布。
import numpy as np
import pandas as pd
import 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准则寻找最佳的 p, d, q 参数组合。此处手动设定为 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 Sequential
from 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参数优化的步骤:
- 差分次数d:使用差分可以去除时间序列中的非平稳性。通常通过ADF检验(单位根检验)来判断是否需要差分。
- 自回归阶数 p:通过观察ACF(自相关函数)图来确定。
- 移动平均阶数 q:通过观察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优化:
- 通过循环不同的 p、d、 q参数组合,使用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层数、每层的神经元数。
- 学习率:Adam优化器的学习率、批量大小。
- 训练轮次:过多的训练可能导致过拟合,过少的训练则可能导致欠拟合。
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模型相比,混合模型能够更好地拟合复杂的时间序列数据,提供更加准确的预测。