当前位置: 首页 > news >正文

SARIMA模型实战:从数据预处理到预测评估的完整Python实现

1. 时间序列分析与SARIMA模型基础

时间序列分析是数据科学领域的重要分支,它专门研究按时间顺序排列的数据点。想象你每天记录体重变化,这些数据点按日期排列就构成了一个典型的时间序列。在实际应用中,时间序列分析可以帮助我们预测股票价格、销售额变化、气象数据等具有时间依赖性的数据。

SARIMA(季节性自回归综合移动平均)模型是ARIMA模型的升级版,专门处理具有季节性特征的数据。比如空调销量每年夏天都会上升,这种周期性变化就是典型的季节性特征。SARIMA模型通过(p,d,q)×(P,D,Q,s)这组参数来描述数据的特征:

  • p:自回归项阶数
  • d:差分次数
  • q:移动平均项阶数
  • P:季节性自回归阶数
  • D:季节性差分次数
  • Q:季节性移动平均阶数
  • s:季节周期长度

与传统ARIMA相比,SARIMA增加了处理季节性变化的能力。举个例子,如果分析月度销售数据,s通常设为12(一年12个月);如果是季度数据,s则设为4。

2. 数据准备与预处理实战

2.1 数据获取与探索

我们从NASA戈达德空间研究所获取了北美陆地表面温度数据,时间跨度为1990年1月至2020年11月。原始数据格式如下:

import pandas as pd data = pd.read_excel('temperature.xlsx', sheet_name='NH.Ts+dSST', header=1, index_col=0) print(data.head())

数据探索是建模的第一步。我们先绘制原始数据的时序图:

import matplotlib.pyplot as plt plt.figure(figsize=(12,6)) plt.plot(data.values.ravel()[:-1]) # 排除最后一个空值 plt.title('北美陆地温度变化(1990-2020)') plt.xlabel('月份') plt.ylabel('温度(℃)') plt.show()

2.2 平稳化处理技巧

原始数据通常包含趋势和季节性成分。我们采用一阶12步差分来消除这些影响:

# 一阶差分消除趋势 diff_1 = data.diff(1).dropna() # 12步差分消除季节性 diff_12 = diff_1.diff(12).dropna()

平稳性检验使用ADF单位根检验:

from statsmodels.tsa.stattools import adfuller result = adfuller(diff_12) print('ADF统计量:', result[0]) print('p值:', result[1]) print('临界值:', result[4])

如果p值小于0.05,可以认为数据已平稳。对于不平稳的数据,可以尝试Box-Cox变换:

from scipy.stats import boxcox transformed, _ = boxcox(data.values.flatten()[1:]) # 排除第一个NaN

3. 模型定阶与参数选择

3.1 自相关与偏自相关分析

ACF和PACF图是定阶的重要工具:

from statsmodels.graphics.tsaplots import plot_acf, plot_pacf fig, (ax1, ax2) = plt.subplots(2,1, figsize=(12,8)) plot_acf(diff_12, lags=36, ax=ax1) plot_pacf(diff_12, lags=36, ax=ax2) plt.show()

通过观察截尾和拖尾特征,可以初步判断p、q值。但这种方法比较主观,我们需要更客观的准则。

3.2 自动化参数搜索

使用AIC/BIC准则进行参数网格搜索:

from itertools import product from statsmodels.tsa.statespace.sarimax import SARIMAX import warnings warnings.filterwarnings("ignore") # 参数范围设置 ps = range(0, 3) # AR阶数 ds = range(0, 2) # 差分次数 qs = range(0, 3) # MA阶数 Ps = range(0, 2) # 季节性AR阶数 Ds = range(0, 2) # 季节性差分 Qs = range(0, 2) # 季节性MA阶数 s = 12 # 季节周期 # 生成所有参数组合 params_list = list(product(ps, ds, qs, Ps, Ds, Qs)) def find_best_params(data, params_list): best_bic = float('inf') best_params = None for param in params_list: try: model = SARIMAX(data, order=(param[0], param[1], param[2]), seasonal_order=(param[3], param[4], param[5], s)) results = model.fit(disp=-1) if results.bic < best_bic: best_bic = results.bic best_params = param except: continue return best_params, best_bic best_params, best_bic = find_best_params(data, params_list) print(f'最优参数: SARIMA{best_params[:3]}×{best_params[3:]}{s}') print(f'最小BIC值: {best_bic}')

4. 模型训练与诊断

4.1 模型拟合与残差分析

使用最优参数训练模型:

model = SARIMAX(data, order=(best_params[0], best_params[1], best_params[2]), seasonal_order=(best_params[3], best_params[4], best_params[5], s)) results = model.fit(disp=-1) # 残差诊断 results.plot_diagnostics(figsize=(15,12)) plt.show()

诊断图包括:

  1. 标准化残差时序图 - 应无明显趋势
  2. 残差直方图 - 应接近正态分布
  3. 正态Q-Q图 - 点应大致在直线上
  4. 残差自相关图 - 应无显著自相关

4.2 白噪声检验

使用Ljung-Box检验验证残差是否为白噪声:

from statsmodels.stats.diagnostic import acorr_ljungbox lb_test = acorr_ljungbox(results.resid, lags=12) print('p值:', lb_test[1])

如果所有p值都大于0.05,说明残差是白噪声,模型拟合良好。

5. 预测与评估

5.1 时间序列预测

使用训练好的模型进行预测:

# 预测未来12个月 forecast = results.get_forecast(steps=12) forecast_mean = forecast.predicted_mean conf_int = forecast.conf_int() # 绘制预测结果 plt.figure(figsize=(12,6)) plt.plot(data.values.ravel()[:-1], label='观测值') plt.plot(range(len(data), len(data)+12), forecast_mean, label='预测值', color='red') plt.fill_between(range(len(data), len(data)+12), conf_int.iloc[:,0], conf_int.iloc[:,1], color='pink', alpha=0.3) plt.legend() plt.show()

5.2 模型评估指标

使用MSE、MAE和R²评估预测效果:

from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score # 假设test_data是真实值 mse = mean_squared_error(test_data, forecast_mean) mae = mean_absolute_error(test_data, forecast_mean) r2 = r2_score(test_data, forecast_mean) print(f'MSE: {mse:.4f}') print(f'MAE: {mae:.4f}') print(f'R²: {r2:.4f}')

在实际项目中,我遇到过MSE很低但预测曲线明显偏离的情况。这时候需要结合业务知识判断,不能完全依赖指标。比如温度预测中,0.5℃的误差对日常穿衣影响不大,但对农作物生长可能很关键。

6. 完整代码实现

以下是整合后的完整代码示例:

# 导入所需库 import pandas as pd import numpy as np 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_pacf from sklearn.metrics import mean_squared_error from itertools import product # 1. 数据加载与预处理 data = pd.read_excel('temperature.xlsx', index_col=0) ts_data = data.values.ravel()[:-1] # 2. 平稳性检验与处理 diff_1 = pd.Series(ts_data).diff(1).dropna() diff_12 = diff_1.diff(12).dropna() # 3. 参数搜索 def find_best_params(data): ps = range(0, 3) ds = range(0, 2) qs = range(0, 3) Ps = range(0, 2) Ds = range(0, 2) Qs = range(0, 2) s = 12 params_list = list(product(ps, ds, qs, Ps, Ds, Qs)) best_bic = np.inf best_params = None for param in params_list: try: model = SARIMAX(data, order=(param[0], param[1], param[2]), seasonal_order=(param[3], param[4], param[5], s)) results = model.fit(disp=-1) if results.bic < best_bic: best_bic = results.bic best_params = param except: continue return best_params, best_bic best_params, best_bic = find_best_params(ts_data) # 4. 模型训练 final_model = SARIMAX(ts_data, order=(best_params[0], best_params[1], best_params[2]), seasonal_order=(best_params[3], best_params[4], best_params[5], 12)) final_results = final_model.fit(disp=-1) # 5. 预测与评估 forecast = final_results.get_forecast(steps=12) forecast_mean = forecast.predicted_mean conf_int = forecast.conf_int() # 可视化 plt.figure(figsize=(12,6)) plt.plot(ts_data, label='观测值') plt.plot(range(len(ts_data), len(ts_data)+12), forecast_mean, label='预测值', color='red') plt.fill_between(range(len(ts_data), len(ts_data)+12), conf_int.iloc[:,0], conf_int.iloc[:,1], color='pink', alpha=0.3) plt.legend() plt.show()

在实现过程中,有几个常见坑需要注意:

  1. 数据量不足会导致模型波动大,建议至少使用3-4个完整周期的数据
  2. 差分过度会使数据失去原有特征,ADF检验可以帮助判断
  3. 参数搜索范围不宜过大,否则计算成本会急剧上升
  4. 残差检验不通过时,需要回到数据预处理阶段重新检查
http://www.jsqmd.com/news/637220/

相关文章:

  • 即插即用系列 | TGRS 2026 | LaSEA:隐式语义感知提取与聚合!跨尺度特征增强+随机池化抗噪,深层语义不退化!| 代码分享
  • Android AVB 实战:从镜像构建到安全启动的完整流程解析
  • ANSYS特征值屈曲分析在桁架结构设计中的关键应用
  • 轻量级购物清单管理应用Koffan
  • 第8篇:梯度下降算法实战——优化模型的“寻路”指南(项目实战)
  • 【工业级AIAgent状态机白皮书】:基于127个真实Agent项目验证的6层状态抽象模型
  • 密胺餐具生产厂家哪个好
  • 智能技术革新学术研究:8款工具提升毕业论文质量
  • 为什么顶级期刊偏爱isoTOP-ABPP?揭秘这项技术背后的5大创新设计
  • 斯坦福CS146S作业全解析:从Prompt到Agent实战
  • Dell EMC PowerEdge 14G 服务器BIOS中RAID配置实战:从零构建虚拟磁盘
  • LeetCode(两两交换链表中的节点)
  • HuggingFace Accelerate多卡训练卡在prepare()?手把手教你排查NCCL P2P通信问题(附4090实测)
  • 跟我一起学 OpenClaw(10):工具系统完全指南——从「安全沙箱」到「企业级自动化」的权限设计
  • 从博弈论到艺术创作:深入浅出解析生成对抗网络(GAN)
  • 基于ESP32的无线遥控小车开发指南
  • 仿真环境滞后=Agent上线延迟3个月?紧急发布AIAgent仿真基建加速包:含5个预训练世界模型接口+2套轻量级物理引擎适配器
  • 深入解析TTL与CMOS电平标准:从原理到应用实践
  • 爱毕业aibiye采用前沿的深度学习模型,对重复率超过30%的论文内容进行智能重组,确保改写后的文本符合原创性要求。
  • STM32F407+RT-Thread实战:3.2寸LCD驱动ILI9341全流程(附FSMC避坑指南)
  • AI开发-python-langchain框架(--AI 直接生成并执行 Python 代码 )托
  • 打破空间壁垒:视频会议重构数字化协作新范式
  • 别再手动做表格了!用WPS这个隐藏功能自动分析数据(含真实案例演示)
  • 33.赛灵思(AMD)bram_axi(AXI BRAM Controller)核心官方文档清单
  • C语言函数是什么?新手必懂的核心概念
  • 线性投影在机器学习中的5个实战应用:从PCA到特征提取
  • Agent落地为什么这么难?:从概念到生产的工程鸿沟
  • Go语言的go-ast抽象语法树包与代码生成工具的构建框架
  • 2026年4月13日 AI前沿资讯速览
  • 基于STM32的智能厨房安全检测系统(完整项目)