Py学习  »  机器学习算法

【深度学习】突破LSTM!结合ARIMA时间序列预测 !!

机器学习初学者 • 3 月前 • 112 次点击  

今儿再来和大家聊聊基于LSTM和ARIMA的混合模型在时间序列预测,这部分很常见也很重要,大家有空可以仔细看看~

另外,传统的统计方法如ARIMA模型能有效捕捉线性结构,但对复杂非线性模式的表现较弱。深度学习方法(如LSTM)在非线性时间序列上有良好表现。混合模型试图结合ARIMA与LSTM各自的优势,使模型既能处理时间序列中的线性趋势,又能捕捉复杂的非线性特征。

混合模型数学原理

ARIMA模型

ARIMA模型(Auto-Regressive Integrated Moving Average)是基于时间序列的自回归和滑动平均过程。它可以表示为 ARIMA(p, d, q),其中:

  •  是自回归(AR)项的阶数。
  •  是差分次数,用于消除非平稳性。
  •  是滑动平均(MA)项的阶数。

ARIMA模型公式:

对于给定的时间序列 ,假设经过  次差分后达到平稳性,则ARIMA模型的表达为:

其中:

  •  为自回归项的系数。
  •  为滑动平均项的系数。
  •  为白噪声项,满足独立同分布。

LSTM模型

LSTM(Long Short-Term Memory)是一种特殊的RNN,能够记忆较长的历史信息,适合处理非线性和长短期依赖的序列数据。LSTM的核心是通过门机制(输入门、遗忘门、输出门)控制信息流。

LSTM模型公式:

LSTM单元的计算包含以下步骤:

  1. 遗忘门 :决定保留多少历史信息。
  1. 输入门  和候选记忆 :决定如何更新单元状态。
  1. 单元状态 :通过组合遗忘门和输入门,更新单元状态。
  1. 输出门  和隐藏状态 :计算最终的输出。

混合模型的组成与公式

对于给定时间序列 ,我们可以将其表示为线性部分  和非线性部分  的组合:

首先,我们用ARIMA对时间序列拟合线性部分 ,然后将残差序列(原序列减去ARIMA预测)用LSTM模型拟合非线性部分 ,得到最终的预测:

数据生成与特征分析

数据生成

我们生成包含趋势、季节性和噪声的时间序列,模拟现实中可能遇到的复杂数据。假设时间范围为0到200,趋势线性增加、季节性为正弦波、噪声为正态分布。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 生成合成数据
np.random.seed(0)
time = np.arange(0400)
trend = time * 0.1  # 趋势项
seasonal = 10 * np.sin(time * 0.2)  # 周期性
noise = np.random.normal(01, len(time))  # 噪声项
series = trend + seasonal + noise

# 存储在DataFrame中
df = pd.DataFrame({'Time': time, 'Value': series})

数据可视化

# 绘制时间序列图
plt.figure(figsize=(126))
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=(512))
arima_result = model_arima.fit()

# 生成预测值并绘制图形
df['ARIMA_Prediction'] = arima_result.predict(start=1, end=len(df)-1, dynamic=False)
plt.figure(figsize=(126))
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=(01))
residual_scaled = scaler.fit_transform(df['Residual'].values.reshape(-11))

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=(126))
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参数优化的步骤:

  1. 差分次数:使用差分可以去除时间序列中的非平稳性。通常通过ADF检验(单位根检验)来判断是否需要差分。
  2. 自回归阶数 :通过观察ACF(自相关函数)图来确定。
  3. 移动平均阶数 :通过观察PACF(偏自相关函数)图来确定。
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf

# 画出ACF和PACF图,帮助选择p和q
plt.figure(figsize=(126))
plot_acf(df['Value'], lags=40, ax=plt.gca())
plt.title('ACF Plot')
plt.show()

plt.figure(figsize=(126))
plot_pacf(df['Value'], lags=40, ax=plt.gca())
plt.title('PACF Plot')
plt.show()

AIC和BIC优化:

  • 通过循环不同的  参数组合,使用AIC和BIC选择最佳模型。
  • 代码实现可以使用 auto_arimapmdarima库)来自动选择最优参数。
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模型的超参数优化

  1. 层数与神经元数:通过增加LSTM的层数或每层的神经元数量可以增加模型的学习能力,但也会增加计算复杂度。
  2. 训练批量大小和学习率:调整批量大小(batch_size)和学习率(learning_rate)来提高训练的收敛速度和预测精度。
  3. 训练轮次:增加训练轮次可以进一步提高模型的预测精度,直到达到收敛。
# 使用GridSearchCV或随机搜索来调优LSTM的超参数
from sklearn.model_selection import GridSearchCV

# 设定参数网格
param_grid = {
    'batch_size': [1632],
    'epochs': [50100],
    'optimizer' : ['adam''rmsprop'],
    'lstm_units': [50100]
}

# 使用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=(126))
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模型相比,混合模型能够更好地拟合复杂的时间序列数据,提供更加准确的预测。

最后

大家有问题可以直接在评论区留言即可~

喜欢本文的朋友可 收藏、点赞、转发起来!

往期精彩回顾




  • 交流群

请备注:”昵称-学校/公司-研究方向“,例如:”张小明-浙大-CV“加群。

也可以加入机器学习交流qq群772479961


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/177715
 
112 次点击