
如何高效爬取全球新闻网站 – 整合Scrapy、Selenium与Mediastack API实现自动化新闻采集
ARIMA模型(Auto-Regressive Integrated Moving Average)是基于时间序列的自回归和滑动平均过程。它可以表示为 ARIMA(p, d, q),其中:
ARIMA模型公式:
对于给定的时间序列y ,假设经过 d次差分后达到平稳性,则ARIMA模型的表达为:
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()
我们使用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模型能够有效捕捉数据中的趋势和部分周期性,但在高频噪声部分表现不佳,这为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模型需要将数据转换为适合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模型的核心优化在于选择合适的参数 、、。通常可以通过AIC(Akaike信息准则)或者BIC(贝叶斯信息准则)来进行模型选择,优化这三个参数。
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优化:
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模型的优化主要涉及以下几个方面:
# 使用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模型相比,混合模型能够更好地拟合复杂的时间序列数据,提供更加准确的预测。