ARIMA(p,d,q) 模型实战:Python statsmodels 库 0.14.0 版本完整建模流程与 AIC/BIC 调优

发布时间:2026/7/8 23:03:25
ARIMA(p,d,q) 模型实战:Python statsmodels 库 0.14.0 版本完整建模流程与 AIC/BIC 调优 ARIMA(p,d,q) 模型实战Python statsmodels 库 0.14.0 版本完整建模流程与 AIC/BIC 调优1. 时间序列分析基础与ARIMA模型概览时间序列分析是数据科学领域中极具挑战性的方向之一。当我们面对具有时间依赖性的数据时传统回归方法往往难以捕捉其内在的动态规律。ARIMA模型作为一种经典的时间序列预测方法融合了自回归(AR)、差分(I)和移动平均(MA)三大组件能够有效处理各种复杂的时间序列模式。在金融领域ARIMA被广泛应用于股票价格预测在零售行业它帮助商家预测商品销量在气象学中ARIMA模型用于温度变化的预测。无论数据呈现出趋势性、季节性还是随机波动经过适当参数配置的ARIMA模型都能展现出强大的预测能力。ARIMA模型的核心参数p自回归阶数表示当前值与过去p个历史值的线性关系d差分阶数使非平稳序列转化为平稳序列的关键步骤q移动平均阶数反映当前值与过去q个预测误差的关系# 基础库导入 import numpy as np import pandas as pd import matplotlib.pyplot as plt from statsmodels.tsa.statespace.sarimax import SARIMAX from statsmodels.tsa.stattools import adfuller from statsmodels.graphics.tsaplots import plot_acf, plot_pacf2. 数据准备与平稳性检验2.1 数据加载与可视化高质量的时间序列分析始于对数据的深入理解。我们首先需要将数据加载到Pandas DataFrame中并进行初步的可视化检查。# 示例数据加载实际应用中替换为您的数据 date_rng pd.date_range(start2020-01-01, end2023-12-31, freqD) ts_data pd.Series(np.random.randn(len(date_rng)) * 10 50, indexdate_rng) # 添加趋势和季节性成分 trend np.linspace(0, 50, len(date_rng)) seasonality 15 * np.sin(2 * np.pi * np.arange(len(date_rng)) / 365) ts_data ts_data trend seasonality # 可视化原始数据 plt.figure(figsize(12,6)) plt.plot(ts_data) plt.title(原始时间序列数据) plt.xlabel(日期) plt.ylabel(观测值) plt.grid(True) plt.show()2.2 平稳性检验与差分处理平稳性是ARIMA建模的前提条件。我们使用Augmented Dickey-Fuller (ADF)检验来判断序列是否平稳。def test_stationarity(timeseries, window12): # 计算滚动统计量 rolmean timeseries.rolling(windowwindow).mean() rolstd timeseries.rolling(windowwindow).std() # 绘制滚动统计量 plt.figure(figsize(12,6)) orig plt.plot(timeseries, colorblue, label原始数据) mean plt.plot(rolmean, colorred, label滚动均值) std plt.plot(rolstd, colorblack, label滚动标准差) plt.legend(locbest) plt.title(滚动均值与标准差) plt.grid(True) plt.show() # 执行ADF检验 print(ADF检验结果:) dftest adfuller(timeseries, autolagAIC) dfoutput pd.Series(dftest[0:4], index[检验统计量,p值,滞后阶数,观测数]) for key,value in dftest[4].items(): dfoutput[f临界值({key})] value print(dfoutput) # 检验原始数据平稳性 test_stationarity(ts_data)当p值大于0.05时我们需要对数据进行差分处理。差分阶数d的确定通常通过观察ADF检验结果和自相关图。# 一阶差分 ts_data_diff1 ts_data.diff().dropna() # 检验一阶差分后数据 test_stationarity(ts_data_diff1) # 二阶差分如果需要 ts_data_diff2 ts_data_diff1.diff().dropna() test_stationarity(ts_data_diff2)3. 模型识别与参数选择3.1 ACF与PACF分析自相关(ACF)和偏自相关(PACF)图是确定ARIMA模型p和q参数的重要工具。# 绘制ACF和PACF图 plt.figure(figsize(12,8)) plt.subplot(211) plot_acf(ts_data_diff1, axplt.gca(), lags40) plt.subplot(212) plot_pacf(ts_data_diff1, axplt.gca(), lags40) plt.tight_layout() plt.show()解读指南AR(p)模型PACF在p阶后截尾ACF逐渐衰减MA(q)模型ACF在q阶后截尾PACF逐渐衰减ARMA(p,q)模型ACF和PACF都呈现衰减模式3.2 网格搜索与AIC/BIC准则当ACF和PACF图无法提供明确指导时我们可以采用网格搜索结合信息准则的方法寻找最优参数。import itertools # 定义参数搜索范围 p range(0, 3) d range(1, 3) q range(0, 3) pdq list(itertools.product(p, d, q)) # 网格搜索寻找最优参数 best_aic np.inf best_bic np.inf best_pdq None best_model None for param in pdq: try: model SARIMAX(ts_data, orderparam, seasonal_order(0,0,0,0), enforce_stationarityFalse, enforce_invertibilityFalse) results model.fit(disp0) # 比较AIC if results.aic best_aic: best_aic results.aic best_pdq_aic param best_model_aic results # 比较BIC if results.bic best_bic: best_bic results.bic best_pdq_bic param best_model_bic results except: continue print(f最优AIC参数组合: ARIMA{best_pdq_aic} AIC:{best_aic:.2f}) print(f最优BIC参数组合: ARIMA{best_pdq_bic} BIC:{best_bic:.2f})4. 模型拟合与诊断4.1 模型训练与参数估计确定最优参数后我们可以正式拟合ARIMA模型。# 使用最优参数拟合模型 model SARIMAX(ts_data, orderbest_pdq_aic, seasonal_order(0,0,0,0), enforce_stationarityFalse, enforce_invertibilityFalse) results model.fit(disp0) # 输出模型摘要 print(results.summary())关键输出解读系数显著性P|z|列小于0.05表示系数显著Ljung-Box检验检验残差是否自相关p值应大于0.05Jarque-Bera检验检验残差正态性4.2 残差诊断良好的ARIMA模型应产生类似白噪声的残差序列。# 残差诊断图 results.plot_diagnostics(figsize(12,8)) plt.tight_layout() plt.show() # 残差自相关检验 residuals results.resid plt.figure(figsize(12,4)) plot_acf(residuals, lags40) plt.show()5. 模型预测与评估5.1 样本内与样本外预测# 样本内预测 pred results.get_prediction(startpd.to_datetime(2023-01-01), endpd.to_datetime(2023-12-31), dynamicFalse) pred_ci pred.conf_int() # 可视化预测结果 plt.figure(figsize(12,6)) ax ts_data[2022:].plot(label观测值) pred.predicted_mean.plot(axax, label一步向前预测) ax.fill_between(pred_ci.index, pred_ci.iloc[:,0], pred_ci.iloc[:,1], colork, alpha0.1) plt.xlabel(日期) plt.ylabel(观测值) plt.title(ARIMA模型预测结果) plt.legend() plt.grid(True) plt.show()5.2 预测性能评估from sklearn.metrics import mean_squared_error, mean_absolute_error # 计算预测误差 y_actual ts_data[2023-01-01:2023-12-31] y_pred pred.predicted_mean mse mean_squared_error(y_actual, y_pred) rmse np.sqrt(mse) mae mean_absolute_error(y_actual, y_pred) print(f均方误差(MSE): {mse:.2f}) print(f均方根误差(RMSE): {rmse:.2f}) print(f平均绝对误差(MAE): {mae:.2f})6. 高级技巧与实战建议6.1 季节性ARIMA模型当数据存在明显季节性时可以考虑季节性ARIMA(SARIMA)模型。# SARIMA模型示例 model SARIMAX(ts_data, order(1,1,1), seasonal_order(1,1,1,12), enforce_stationarityFalse, enforce_invertibilityFalse) results model.fit(disp0) print(results.summary())6.2 自动化ARIMA建模对于大规模应用可以使用pmdarima库实现自动化ARIMA建模。from pmdarima import auto_arima # 自动化ARIMA建模 model auto_arima(ts_data, start_p0, start_q0, max_p3, max_q3, dNone, seasonalFalse, traceTrue, error_actionignore, suppress_warningsTrue, stepwiseTrue) print(model.summary())6.3 模型部署与更新策略模型部署流程定期重新训练模型以纳入最新数据建立监控机制跟踪预测误差变化设置预警阈值触发模型重新训练# 模型更新示例 def update_model(new_data, old_model): # 合并新旧数据 full_data pd.concat([old_model.data.orig_endog, new_data]) # 使用先前参数重新拟合 updated_model SARIMAX(full_data, orderold_model.order, seasonal_orderold_model.seasonal_order) return updated_model.fit(disp0)7. 常见问题与解决方案7.1 模型收敛问题问题表现拟合过程报错或无法收敛参数估计值异常大/小解决方案尝试不同的优化算法调整maxiter参数增加迭代次数检查数据平稳性和异常值# 使用不同优化器 model SARIMAX(ts_data, order(1,1,1), seasonal_order(1,1,1,12)) results model.fit(methodbfgs, maxiter500)7.2 预测性能不稳定可能原因数据生成过程随时间变化存在未建模的外部冲击改进措施引入外生变量采用滚动时间窗口训练结合其他模型如Prophet或LSTM# 引入外生变量示例 exog_data pd.DataFrame({external_factor: np.random.randn(len(ts_data))}, indexts_data.index) model SARIMAX(ts_data, exogexog_data, order(1,1,1)) results model.fit()8. 实际案例分析8.1 零售销售预测数据特点明显的周季节性节假日效应显著长期增长趋势建模策略使用SARIMA(1,1,1)(1,1,1,7)捕捉周季节性添加节假日虚拟变量作为外生变量对数变换处理异方差性# 零售销售案例代码框架 sales_data pd.read_csv(retail_sales.csv, parse_dates[date], index_coldate) # 创建节假日虚拟变量 holidays [2020-12-25, 2021-01-01] # 示例日期 sales_data[is_holiday] sales_data.index.isin(pd.to_datetime(holidays)).astype(int) # 对数变换 sales_data[log_sales] np.log(sales_data[sales]) # 拟合SARIMAX模型 model SARIMAX(sales_data[log_sales], exogsales_data[[is_holiday]], order(1,1,1), seasonal_order(1,1,1,7)) results model.fit()8.2 股票价格预测挑战高波动性市场效率导致预测困难非平稳性明显实用建议预测收益率而非绝对价格结合GARCH模型处理波动聚集谨慎评估预测效果避免过拟合# 股票收益率预测示例 stock_prices pd.read_csv(stock_prices.csv, parse_dates[date], index_coldate) returns stock_prices[close].pct_change().dropna() # 拟合ARIMA-GARCH组合模型 from arch import arch_model # 先拟合ARIMA模型 arima_model SARIMAX(returns, order(1,0,1)) arima_results arima_model.fit() # 使用ARIMA残差拟合GARCH模型 garch_model arch_model(arima_results.resid, p1, q1) garch_results garch_model.fit()