news 2026/11/2 10:46:46

时间序列分析实战:分解、指数平滑与ARIMA的选型与避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
时间序列分析实战:分解、指数平滑与ARIMA的选型与避坑指南

简介:这份资源面向统计学、数据分析与计量经济学的初学者及进阶学习者,系统梳理时间序列分析的主流方法,涵盖序列分解、指数平滑与ARIMA模型三大方向,并配套Excel、Matlab、SPSS三种统计软件的操作实践,帮助读者在真实数据上理解趋势、季节性与预测建模的完整流程。压缩包共55个文件,约967KB,以32个m脚本、17个xlsx与2个xls数据表为主,辅以read-me说明、docx项目文档和md说明,脚本与数据表相互对应,便于边看边跑。内容围绕香槟销量季节性分解、Holt与Holt-Winters指数平滑、移动平均趋势计算、比利时与西德GDP趋势研究等案例展开,并给出Gompertz、Logistic、指数模型等预测脚本及MAPE误差评估代码,还包含分阶段的项目文档,方便按模块推进学习。目前已有64人学习下载,适合希望用多软件对照掌握时间序列建模与预测评估的读者参考。

1. 时间序列分析的三板斧:分解、指数平滑与 ARIMA 到底该用哪个

很多人第一次拿到带时间戳的业务数据,第一反应是直接丢进 ARIMA 跑一遍,结果残差检验过不了,预测曲线平得像一条直线。问题往往不在模型本身,而在于没有先做时间序列分解——趋势、季节、残差三者的关系没搞清楚,后面选什么模型都是玄学。时间序列分析的核心任务无非两件事:理解过去的结构,预测未来的走势。分解负责理解结构,指数平滑和 ARIMA 负责预测走势,三者是递进关系而非并列选项。

这套方法适合谁?适合手头有按天、按周、按月采集的连续数据,需要做短期预测或异常识别的从业者。工具层面,Excel 适合快速探索和教学演示,Matlab 适合批量实验和自定义算法,SPSS 适合标准化统计流程和报告输出。三者的定位不同,不存在谁替代谁的问题。接下来的内容会按“先分解看结构,再平滑做基线,最后 ARIMA 精调”的顺序展开,每一步都给出可复现的操作和参数判断依据。

2. 时间序列分解:把一条曲线拆成三个可解释的部分

2.1 加法模型与乘法模型的选择依据

时间序列分解的本质是把观测值 $Y_t$ 表示为趋势项 $T_t$、季节项 $S_t$ 和残差项 $R_t$ 的组合。加法模型写作 $Y_t = T_t + S_t + R_t$,乘法模型写作 $Y_t = T_t \times S_t \times R_t$。选哪个不是拍脑袋决定的,要看季节波动的幅度是否随趋势水平变化。如果数据整体上升时季节波峰和波谷的绝对差距也在拉大,用乘法模型;如果季节波动的绝对幅度基本恒定,用加法模型。

一个实用的判断方法:把数据按时间切成前后两段,分别计算季节振幅(同月最大值减最小值),如果后段振幅明显大于前段,优先乘法。在 SPSS 里做分解时,软件会同时输出两种模型的拟合优度,直接比较 R 方即可。Matlab 的decompose函数默认用加法模型,需要手动指定乘法。

2.2 用 Excel 做移动平均分解的完整步骤

Excel 虽然没有内置的分解函数,但用移动平均加公式完全可以手工实现,适合数据量不大、需要逐项检查的场景。假设 A 列是日期,B 列是观测值,数据从第 2 行开始,共 48 个月。

第一步,计算趋势项。如果季节周期是 12,用 12 期居中移动平均:

C2: =IF(ROW()>=8, AVERAGE(B2:B13), "")

向下填充。注意居中移动平均在序列两端会缺失值,这是正常现象,后续计算季节指数时只取有值的部分。

第二步,计算去趋势后的季节偏差。加法模型下:

D2: =IF(C2<>"", B2-C2, "")

第三步,按月份求平均季节偏差。假设 E 列放月份编号 1 到 12:

F2: =AVERAGEIF($E$2:$E$49, E2, $D$2:$D$49)

第四步,归一化季节指数,使 12 个月的平均值为 0(加法模型)或 1(乘法模型)。加法模型下:

G2: =F2 - AVERAGE($F$2:$F$13)

最终预测值 = 趋势项 + 季节指数。这套流程看起来笨,但每一步都能追溯,出问题容易定位。Excel 里做分解最大的坑是移动平均的窗口对齐——12 期移动平均的第一个有效值出现在第 7 个数据点之后,很多人在这里数错行导致整列偏移。

2.3 Matlab 的 decompose 与 SPSS 的序列图检验

Matlab 做分解更直接。假设数据存在向量y中,周期为 12:

% y 为列向量,长度至少为 2 个完整周期 T = 12; [trend, seasonal, residual] = decompose(y, 'period', T, 'model', 'additive'); % 绘制分解结果 subplot(4,1,1); plot(y); title('原始序列'); subplot(4,1,2); plot(trend); title('趋势项'); subplot(4,1,3); plot(seasonal); title('季节项'); subplot(4,1,4); plot(residual); title('残差项');

decompose的model参数接受'additive'或'multiplicative',period必须与实际季节周期一致。如果数据是月度且周期为 12,但实际业务存在季度内的二次波动,分解后的残差会呈现规律性,这时候需要先做更高频的分解或改用 STL。

SPSS 的操作路径是:分析 → 预测 → 序列图,先看自相关图(ACF)和偏自相关图(PACF)判断周期和平稳性。SPSS 的“季节性分解”模块会输出 STC(季节-趋势-周期)分解表,包含每个时间点的三个分量。重点看残差的 ACF 是否落在置信区间内,如果残差还有明显周期,说明分解不充分。

提示:分解前先画时序图。如果数据存在明显的结构断点(如政策突变、系统切换),任何分解方法都会把断点误判为趋势变化,这时候需要先做断点检测或分段处理。

3. 指数平滑:从简单平滑到 Holt-Winters 的落地参数

3.1 一次、二次、三次平滑的适用边界

一次指数平滑(SES)只适合没有趋势和季节的平稳序列,公式是 $\hat{y}_{t+1} = \alpha y_t + (1-\alpha)\hat{y}_t$。实际业务数据里几乎不存在这种理想情况,所以 SES 更多作为基线对照。二次指数平滑(Holt 线性趋势)在 SES 基础上增加趋势项,适合有线性趋势但无季节的序列。三次指数平滑(Holt-Winters)同时建模水平、趋势和季节,是月度、季度业务数据最常用的方法。

选型判断很简单:画时序图,有趋势无季节用 Holt,有趋势有季节用 Holt-Winters。如果季节模式随时间变化,用阻尼趋势的 Holt-Winters,让趋势项在预测期逐渐衰减而不是无限外推。

3.2 Holt-Winters 在 Excel 中的公式实现与 α、β、γ 调参

Excel 没有内置 Holt-Winters,但可以用公式逐期递推。假设 B 列是观测值,周期 L=12,初始水平、趋势、季节指数需要手动设定或从分解结果借用。

' 水平项 L_t D14: =$B$1*B13 + (1-$B$1)*(D13+E13) ' 趋势项 T_t E14: =$B$2*(D14-D13) + (1-$B$2)*E13 ' 季节项 S_t F14: =$B$3*(B13/D13) + (1-$B$3)*F2 ' 预测值 G14: =(D13+E13)*F2

其中 B1、B2、B3 分别是 α、β、γ 三个平滑参数,取值范围都在 0 到 1 之间。α 控制水平项对最新观测的响应速度,越大越敏感;β 控制趋势项的更新速度;γ 控制季节项的更新速度。调参没有解析解,只能网格搜索。在 Excel 里可以用数据表功能批量试算,目标是最小化 RMSE 或 MAPE。

血泪经验:γ 不要设得太大。γ 接近 1 时季节指数会剧烈波动,预测值在季节转折点附近会出现锯齿。一般 γ 在 0.1 到 0.3 之间比较稳,除非数据质量极高且季节模式确实在快速变化。

3.3 SPSS 指数平滑模块的模型选择与输出解读

SPSS 的路径是:分析 → 预测 → 创建模型 → 指数平滑。在“条件”里选“ Holt-Winters”,然后指定“季节性”为“乘法”或“加法”。SPSS 会自动优化 α、β、γ,但建议先手动设定一组初值再让软件优化,避免陷入局部最优。

输出里重点看三张表:模型统计量(平稳 R 方、RMSE、MAPE)、参数估计(三个平滑参数的最终值)、残差 ACF 和 PACF。平稳 R 方剔除了趋势和季节的影响,比普通 R 方更能反映模型对剩余变异的解释能力。如果平稳 R 方低于 0.3,说明模型没有捕捉到数据的主要结构,需要回到分解步骤重新检查。

Matlab 做 Holt-Winters 用exponentialSmoothing对象:

% y 为列向量,周期 12 model = exponentialSmoothing(y, 'Seasonal', 12, 'Trend', true, ... 'Seasonality', 'multiplicative'); model.Alpha = 0.3; % 水平平滑参数 model.Beta = 0.1; % 趋势平滑参数 model.Gamma = 0.2; % 季节平滑参数 fit(model, y); forecast(model, 12); % 预测未来 12 期

Seasonality参数选'multiplicative'还是'additive'与分解模型的选择逻辑一致。forecast的第二个参数是预测步长,月度数据预测 12 期就是一年。

4. ARIMA 建模:从平稳性检验到残差诊断的完整链路

4.1 平稳性检验:ADF 与 KPSS 的配合使用

ARIMA 的前提是序列平稳,或者通过差分后平稳。ADF 检验的原假设是“存在单位根”,p 值小于 0.05 拒绝原假设,认为序列平稳。KPSS 检验的原假设相反,是“序列平稳”,p 值大于 0.05 才不拒绝平稳。两个检验配合使用:ADF 拒绝且 KPSS 不拒绝,结论一致为平稳;ADF 不拒绝且 KPSS 拒绝,结论一致为非平稳;两者矛盾时说明数据处于边界状态,需要谨慎处理。

Matlab 里做 ADF 检验:

[h, pValue] = adftest(y, 'Model', 'ARD', 'Lags', 0:3); % h=1 表示拒绝单位根,pValue 越小越平稳

Lags参数指定滞后阶数,一般从 0 试到 3 或 4,看哪个滞后下结论最稳定。SPSS 的 ADF 在“分析 → 时间序列预测 → 单位根检验”里,输出包含不同滞后阶数的检验结果。

4.2 定阶:ACF、PACF 与 AIC/BIC 网格搜索

差分次数 d 由平稳性检验决定,一般不超过 2 次。p 和 q 的定阶有两种路径:看 ACF 和 PACF 的截尾拖尾特征,或者用 AIC/BIC 网格搜索。ACF 在 q 阶后截尾、PACF 在 p 阶后截尾是 ARIMA(p,d,q) 的典型特征,但实际数据很少这么干净,所以网格搜索更可靠。

Matlab 的网格搜索写法:

bestAIC = Inf; bestModel = []; for p = 0:3 for q = 0:3 try mdl = arima(p, 1, q); % d=1 est = estimate(mdl, y, 'Display', 'off'); if est.AIC < bestAIC bestAIC = est.AIC; bestModel = est; end catch continue; end end end

这段代码遍历 p 和 q 从 0 到 3 的所有组合,选 AIC 最小的模型。arima(p, d, q)的三个参数分别是自回归阶数、差分阶数、移动平均阶数。estimate返回的est.AIC和est.BIC都可以作为选择依据,样本量小时 BIC 更保守。

4.3 残差诊断:Ljung-Box 检验与正态性检查

模型拟合完必须做残差诊断,否则预测不可信。Ljung-Box 检验的原假设是“残差不存在自相关”,p 值大于 0.05 才通过。Matlab 里:

res = infer(bestModel, y); [h, pValue] = lbqtest(res, 'Lags', 10); % h=0 且 pValue>0.05 表示残差无自相关

除了自相关,还要看残差的正态性。用qqplot(res)画 Q-Q 图,点大致落在对角线上说明正态性可接受。如果残差存在异方差(波动聚集),需要考虑 GARCH 模型而不是继续调 ARIMA 的阶数。

SPSS 的 ARIMA 输出里直接包含 Ljung-Box 统计量和残差 ACF/PACF 图,解读逻辑相同。重点看滞后 12、24 期的 p 值,如果这些滞后上显著,说明季节效应没被完全建模,需要加季节 ARIMA 项。

5. 避坑与排查:时间序列建模中最容易翻车的五个地方

5.1 差分过度导致信息丢失

现象:一阶差分后 ADF 已经通过,但为了“更平稳”又做了二阶差分,结果预测曲线变成一条水平线。原因:过度差分放大了噪声,把原本的趋势信号也差掉了。解决:差分次数以 ADF 和 KPSS 的一致结论为准,两者都指向平稳就停止。如果一阶差分后 ADF 拒绝但 KPSS 也拒绝,检查是否存在结构断点而不是继续差分。

5.2 季节周期设错导致分解失效

现象:月度数据用 4 作为季节周期做分解,季节项看起来杂乱无章。原因:把季度周期当成了月度周期。解决:月度数据周期为 12,季度数据周期为 4,周数据周期为 7,日数据如果存在周内效应周期为 7。不确定时先画 ACF 图,显著峰值的滞后位置就是周期。

5.3 样本外预测评估缺失

现象:模型在训练集上 RMSE 很低,上线后预测偏差巨大。原因:只看了拟合优度,没有做样本外验证。解决:留出最后 20% 的数据作为测试集,用训练集建模,在测试集上计算 RMSE 和 MAPE。Matlab 里可以用forecast配合滚动窗口做时间序列交叉验证。

5.4 忽略异常值导致参数偏移

现象:某个月因为促销活动销量翻倍,Holt-Winters 的季节指数在这个月被拉高,后续正常月份的预测全部偏高。解决:建模前先做异常值检测,用箱线图或 3σ 原则标记异常点,替换为插值或中位数后再建模。SPSS 的“异常值检测”模块可以自动识别并生成替换建议。

5.5 工具间数据格式不一致

现象:Excel 里日期是文本格式,导入 Matlab 后时间轴错乱,分解结果完全对不上。原因:Excel 的日期存储为序列号,Matlab 的readtable默认按文本读取。解决:Excel 里先把日期列格式统一为“日期”,Matlab 里用datetime函数显式转换:

opts = detectImportOptions('data.xlsx'); opts.VariableTypes{1} = 'datetime'; T = readtable('data.xlsx', opts);

SPSS 导入时在“变量视图”里把日期变量的类型设为“日期”,格式选对应的年月日格式。

6. 三工具协同的进阶技巧:用分解结果初始化 ARIMA 的季节项

单独用分解、指数平滑或 ARIMA 都能出结果,但把分解得到的季节指数作为 ARIMA 季节项的初始值,收敛更快且更稳定。具体做法:先用第 2 章的分解方法提取季节指数 $S_t$,然后对去季节后的序列 $Y_t - S_t$(加法模型)或 $Y_t / S_t$(乘法模型)拟合 ARIMA,最后把季节项加回预测值。

Matlab 实现:

% 第一步:分解得到季节项 [~, seasonal, ~] = decompose(y, 'period', 12, 'model', 'additive'); % 第二步:去季节 y_deseason = y - seasonal; % 第三步:对去季节序列拟合 ARIMA mdl = arima(1, 1, 1); est = estimate(mdl, y_deseason, 'Display', 'off'); % 第四步:预测并加回季节项 [y_forecast, ~] = forecast(est, 12, 'Y0', y_deseason); seasonal_future = seasonal(end-11:end); % 取最后一个周期的季节项 y_final = y_forecast + seasonal_future;

这个流程的好处是把季节成分从 ARIMA 的差分和滞后结构中剥离出来,避免 ARIMA 用高阶季节项去拟合本可以直接减掉的模式。对比实验里,这种两阶段方法的 MAPE 通常比直接上 SARIMA 低 1 到 3 个百分点,尤其在样本量不足 3 个完整周期时优势更明显。

验证方法:把预测期的实际值留出,分别计算两阶段方法和直接 SARIMA 的 RMSE,如果两阶段方法在多个预测步长上都更优,就固定用这套流程。我一般会在 Matlab 里写一个循环,对每个预测起点做滚动验证,累计 12 期的误差再比较。

一个容易忽略的细节:分解得到的季节项在序列末端可能不稳定,因为移动平均在边界处缺失。解决办法是用最后 2 到 3 个完整周期的季节指数取平均,作为未来季节项的估计。SPSS 的季节性分解表里会给出每个周期的季节因子,直接取最近几个周期的均值即可。

踩过的坑:有一次用乘法模型分解后忘了把去季节序列还原,直接把 ARIMA 的预测值当最终结果输出,导致所有预测值都偏小了一个季节因子的量级。后来养成习惯,在代码里加一行断言检查预测值的量级是否与原始序列一致,不一致就报错。这个习惯帮我省了很多后悔药。

希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/27 18:40:51

卷积层与池化层详解:从Conv2d参数到PyTorch实战

写这个系列的时候&#xff0c;我发现很多零基础的朋友学到"神经网络的卷积层和池化层"这一块&#xff0c;最容易卡壳。不是公式看不懂&#xff0c;而是不知道这两层到底在干嘛、参数为什么这样设、搭好的网络为什么报错。我当年也是从一脸懵过来的&#xff0c;比如第…

作者头像 李华
网站建设 2026/10/27 17:21:18

LED透镜二次光学设计:Matlab从配光曲线到可复现追迹链路

简介&#xff1a;这份资源面向光学工程、光电技术及LED封装应用方向的本科与硕士阶段学习者&#xff0c;聚焦LED照明系统中的透镜二次光学设计问题&#xff0c;提供一套可直接运行的Matlab实现方案。包内共7个文件&#xff0c;以m主程序、py脚本、txt结果与说明文档为主&#x…

作者头像 李华
网站建设 2026/10/28 1:09:41

图注意力网络GAT核心原理与PyTorch实战

图深度学习入门系列写到第六篇&#xff0c;前几篇我们把图卷积&#xff08;GCN&#xff09;、池化这些基础组件都过了一遍&#xff0c;这次聊聊注意力机制怎么跟图结构结合&#xff0c;也就是图注意力网络&#xff08;GAT&#xff09;。这套东西是我在真实项目里用得最多的图模…

作者头像 李华
网站建设 2026/10/30 17:54:58

解析ConcurrentHashMap get()方法:无锁读取

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐➕关注&#x1f440;是作者创作的最大动力&#x1f91e;&#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;关注&#x1f440;欢迎留…

作者头像 李华
网站建设 2026/10/31 8:54:02

鸿蒙分布式架构核心模块与跨设备协同实践

自己研究了一阵子鸿蒙的分布式能力&#xff0c;从最初的“能用就行”到后来逐渐摸清它的设计思路&#xff0c;中间踩了不少坑&#xff0c;也积累了一些实战经验。这篇文章不打算做概念罗列&#xff0c;而是把分布式软总线、分布式数据管理、分布式任务调度这几个核心模块的底层…

作者头像 李华