简介:这份资源面向数据分析初学者与需要补足时序建模实操的从业者,围绕时间序列分析的三条主线展开:季节分解、指数平滑与ARIMA模型,并分别用Excel、Matlab、SPSS三类统计软件落地演示,帮助读者理解不同工具在趋势提取、平滑预测与参数估计上的差异。压缩包共55个文件,以32个m脚本、17个xlsx与2个xls数据表为主,另附read-me、docx项目说明与md文档,整体约967KB,体积轻便却覆盖了从数据到代码的完整链路。内容涉及Holt、Holt-Winters、广义指数平滑、移动平均趋势计算,以及Gompertz、Logistic、指数模型等Matlab实现,并配有香槟销量、比利时与西德GDP等案例数据,便于对照复现。目前已有64人学习下载,适合希望用多软件交叉验证、快速搭建时序分析实验框架的读者参考。
1. 时间序列三件套:为什么Excel、Matlab、SPSS都得备着
很多人第一次接触时间序列,是从一份带日期列的销售表开始的。数据拉出来,画个折线图,看着有涨有跌,然后呢?老板要下季度预测,你总不能说“看着还会涨”。这时候真正能落地的路径其实就三条:把趋势和季节拆开看(分解)、用历史加权去推下一期(指数平滑)、把自相关结构建模成方程(ARIMA)。这份资源把这三类方法串成了一条线,并且明确用Excel、Matlab、SPSS三种工具分别落地——不是让你三选一,而是让你知道什么场景该掏哪个。
Excel负责快速验证和向非技术同事解释,Matlab负责批量实验和参数扫描,SPSS负责出规范统计报告。适合谁?做运营分析、市场预测、库存计划、设备状态监测的从业者,以及正在补时间序列这门课的学生。你不需要先精通矩阵运算,但得愿意动手把数据跑一遍。下面按“先立住概念、再动手复现、最后避坑”的顺序拆开讲。
2. 分解、指数平滑、ARIMA:三条路线的选型逻辑与手算验证
2.1 分解法:把一条曲线拆成三股力
时间序列分解的核心假设是:观测值 = 趋势 × 季节 × 随机,或者加法形式 观测值 = 趋势 + 季节 + 随机。乘法适合波动幅度随水平增大的序列(比如销售额逐年增长、旺季更旺),加法适合波动幅度基本稳定的序列。判断方法很简单:画图,看波峰波谷的绝对差距是否随整体水平上升而扩大。
Excel里做分解最直接。假设A列是日期,B列是数值,按12期季节周期:
# 步骤1:计算中心化移动平均(趋势项) C2 = AVERAGE(B1:B12) # 12期移动平均,放在第7行附近 # 步骤2:去趋势 D = B / C # 乘法模型,得到季节比率 # 步骤3:按月份求平均季节比率 =AVERAGEIF(月份列, 1, D列) # 对1月求平均,依次得到12个月 # 步骤4:归一化,使12个季节比率之和为12 季节因子 = 原始季节比率 * 12 / SUM(12个季节比率) # 步骤5:预测 预测值 = 趋势外推值 * 对应月份季节因子逻辑说明:移动平均把季节波动抹平,剩下的就是趋势;用原始值除以趋势得到季节比率;按月份平均是为了消除单年随机干扰;归一化保证长期来看季节不引入系统性偏差。参数上,移动平均窗口必须等于季节周期(月度用12,季度用4),否则趋势项里会残留季节成分。常见翻车点是窗口选错,比如月度数据用了6期移动平均,结果季节比率算出来全是1附近,等于没分解。
Matlab做分解更省事,一行decompose或者seasonal分解函数就能出图,但要注意它默认是加法模型,乘法模型需要先取对数再分解,最后指数还原。SPSS在“分析→预测→季节性分解”里可以勾选模型类型,输出四个新变量:误差、季节、趋势、合并。我一般先用SPSS跑一遍看四个成分的图,确认趋势和季节是否真的存在,再决定要不要上ARIMA。
2.2 指数平滑:给近期数据更大权重
指数平滑的直觉是:越近的数据越重要。一次平滑适合无趋势无季节的序列,二次平滑(Holt)加了趋势项,三次平滑(Holt-Winters)再加季节项。公式不复杂,但参数α、β、γ的取值直接决定预测是灵敏还是迟钝。
Excel里可以用“预测工作表”功能自动做三次指数平滑,但想手动控制参数,建议自己写公式:
# 一次指数平滑 S1 = B1 # 初始值取第一期 S_t = α * B_t + (1-α) * S_{t-1} # Holt趋势 L_t = α * B_t + (1-α) * (L_{t-1} + T_{t-1}) T_t = β * (L_t - L_{t-1}) + (1-β) * T_{t-1} # Holt-Winters乘法季节 L_t = α * (B_t / S_{t-m}) + (1-α) * (L_{t-1} + T_{t-1}) T_t = β * (L_t - L_{t-1}) + (1-β) * T_{t-1} S_t = γ * (B_t / L_t) + (1-γ) * S_{t-m}参数说明:α控制水平平滑,取值0.1~0.3时预测平稳,0.6~0.9时紧跟近期波动;β控制趋势平滑,一般取0.05~0.2,太大趋势会抖;γ控制季节平滑,月度数据常用0.1~0.3。初始值可以用前一个完整周期的平均值。Matlab的exponentialSmoothing函数支持自动优化参数,但自动优化容易过拟合,我一般会留出最后12期做验证,手动调参对比MAPE。
SPSS在“分析→预测→创建模型→指数平滑”里可以选模型类型,输出平滑参数和拟合优度。注意SPSS默认用最大似然估计参数,和Excel手动调参结果可能不同,这不是bug,是优化目标不同。选哪个?如果只是内部快速看趋势,Excel够用;如果要写报告,SPSS的参数表和拟合指标更规范。
2.3 ARIMA:把自相关结构写成方程
ARIMA(p,d,q)三个字母分别对应自回归阶数、差分次数、移动平均阶数。p看PACF截尾,q看ACF截尾,d看序列是否平稳。平稳性检验用ADF,p值小于0.05认为平稳;不平稳就差分,差一次不够就差两次,但d一般不超过2,否则序列信息被过度消耗。
Matlab做ARIMA建模的流程最完整:
% 假设y是列向量时间序列 % 1. 平稳性检验 [h,pValue] = adftest(y); % 2. 差分 dy = diff(y); % 3. 看ACF和PACF定阶 autocorr(dy); parcorr(dy); % 4. 拟合ARIMA(1,1,1) Mdl = arima(1,1,1); EstMdl = estimate(Mdl, y); % 5. 预测未来12期 [forecast, MSE] = forecast(EstMdl, 12, 'Y0', y);逻辑说明:adftest返回的h为1表示拒绝单位根假设,序列平稳;diff做一阶差分;autocorr和parcorr用来目测截尾位置;arima(1,1,1)定义模型结构;estimate用最大似然估计参数;forecast输出预测值和均方误差。参数上,p和q一般不超过3,阶数越高参数越多,过拟合风险越大。常见做法是先用AIC/BIC网格搜索p和q,选指标最小的组合,但也要看残差是否白噪声。
SPSS在“分析→预测→创建模型→ARIMA”里可以手动指定p、d、q,也可以让系统自动选。自动选的结果有时会给出高阶模型,我一般会手动限制p和q不超过2,再对比拟合优度。Excel做ARIMA比较吃力,需要装分析工具库或者用Real Statistics插件,不推荐作为主力工具,但可以用来验证简单模型的预测结果。
3. 三工具实操:从数据导入到预测输出的完整链路
3.1 Excel:快速分解与预测工作表
Excel的优势是门槛低、可视化快。拿到一份月度销售数据,先做三件事:画折线图看趋势和季节、加移动平均线看趋势、用预测工作表生成基线预测。
# 数据准备:A列日期,B列数值,从第2行开始 # 插入折线图:选中B列,插入→折线图 # 添加移动平均趋势线:右键数据系列→添加趋势线→移动平均,周期12 # 预测工作表:数据→预测→预测工作表 # 设置:预测结束日期、置信区间95%、季节周期12 # 输出:新工作表包含预测值、置信上下限、图表逻辑说明:移动平均趋势线帮你肉眼确认趋势方向;预测工作表底层用的是三次指数平滑(Holt-Winters),适合有趋势和季节的序列。参数上,季节周期必须填对,月度填12,季度填4,周度填52。置信区间默认95%,可以改成90%或99%,区间越宽预测越保守。注意预测工作表对异常值敏感,如果某个月有促销导致销量翻倍,预测会被拉高,建议先做异常值处理。
Excel做分解的另一个技巧是用“数据分析”工具库里的“移动平均”和“指数平滑”,但这两个工具功能有限,指数平滑只支持一次平滑。要做Holt-Winters,还是得自己写公式或者用预测工作表。
3.2 Matlab:批量实验与参数扫描
Matlab适合做参数扫描和批量预测。比如你要对比不同α、β、γ组合的预测效果,可以写循环:
% 假设y是月度数据,长度至少36期 y = data; % 导入你的数据 n = length(y); train = y(1:n-12); % 前n-12期训练 test = y(n-11:n); % 后12期验证 bestMAPE = inf; bestParams = []; for alpha = 0.1:0.1:0.9 for beta = 0.05:0.05:0.3 for gamma = 0.1:0.1:0.5 % 拟合Holt-Winters fit = exponentialSmoothing(train, 'seasonal', 12, ... 'alpha', alpha, 'beta', beta, 'gamma', gamma); % 预测12期 yp = forecast(fit, 12); % 计算MAPE mape = mean(abs((test - yp) ./ test)) * 100; if mape < bestMAPE bestMAPE = mape; bestParams = [alpha, beta, gamma]; end end end end disp(['最优参数:', num2str(bestParams), ',MAPE:', num2str(bestMAPE)]);逻辑说明:留出最后12期做验证是时间序列建模的基本纪律,不能用全部数据拟合再预测全部数据,那样MAPE会虚低。exponentialSmoothing的seasonal参数指定季节周期,alpha、beta、gamma分别对应水平、趋势、季节平滑系数。MAPE是平均绝对百分比误差,越小越好,但要注意当实际值接近0时MAPE会爆炸,这时候改用MAE或RMSE。
Matlab做ARIMA的批量实验也类似,用网格搜索p和q,选AIC最小的模型。但要注意,AIC最小不代表预测最好,还要看残差诊断。我一般会同时看AIC、残差ACF、Ljung-Box检验p值,三个都过关才认为模型可用。
3.3 SPSS:规范报告与自动建模
SPSS的强项是输出规范。在“分析→预测→创建模型”里,你可以选“专家建模器”让系统自动选模型,也可以手动指定指数平滑或ARIMA。专家建模器会自动处理异常值、缺失值、季节周期,输出拟合优度、残差ACF、预测值。
操作路径:分析 → 预测 → 创建模型 变量:将数值列拖入“因变量” 方法:专家建模器 或 手动指定 专家建模器设置:勾选“考虑季节”、“考虑异常值” 输出:模型摘要、拟合优度、残差诊断、预测图 保存:勾选“预测值”、“置信区间”逻辑说明:专家建模器底层会对比指数平滑和ARIMA,选拟合最好的。但自动选出的模型不一定符合业务直觉,比如它可能给出一个高阶ARIMA,参数解释性差。我一般会先让专家建模器跑一遍,看它选了什么,再手动指定一个更简单的模型对比。如果简单模型的拟合优度只差一点点,优先用简单模型,因为可解释性更好。
SPSS输出里重点看三个表:模型统计量(平稳R方、MAPE)、残差ACF(是否所有滞后都在置信区间内)、预测表(预测值和置信区间)。平稳R方剔除了趋势和季节的影响,比普通R方更可靠。MAPE小于10%算不错,小于5%算很好,但也要结合业务容忍度。
4. 避坑与排查:时间序列建模最常见的五个翻车点
4.1 现象:预测值是一条直线,完全没有季节波动
原因:指数平滑的γ参数被设成0,或者季节周期设错。Excel预测工作表如果季节周期填了1,等于没有季节项。Matlab的exponentialSmoothing如果没指定seasonal参数,默认不加季节。
解决:检查季节周期是否等于数据周期(月度12、季度4、周度52);检查γ是否大于0;用分解法先确认季节成分确实存在,再上Holt-Winters。
4.2 现象:ARIMA模型残差ACF还有明显尖峰
原因:p或q阶数不够,或者差分次数不对。残差里还有自相关,说明模型没把结构提取干净。
解决:看残差ACF和PACF,如果ACF在滞后k处截尾,增加q;如果PACF在滞后k处截尾,增加p。如果残差在季节滞后处有尖峰,说明需要季节ARIMA(SARIMA),在Matlab里用arima('Seasonality',12)。
4.3 现象:MAPE很低但预测图明显偏离
原因:MAPE在 actual 接近0时会被放大或缩小,导致指标失真。比如某个月实际值是1,预测值是2,MAPE是100%,但绝对误差只有1。
解决:同时看MAE、RMSE和预测图。如果实际值有0或接近0,MAPE不可靠,改用MAE。预测图要覆盖训练期和验证期,肉眼确认预测是否跟上了趋势和季节。
4.4 现象:Excel预测工作表报错“数据不足”
原因:预测工作表需要至少两个完整季节周期的数据。月度数据至少24期,季度数据至少8期,周度数据至少104期。
解决:如果数据不够,改用一次或二次指数平滑,不加季节项。或者用移动平均做粗略趋势外推,但不要声称这是“预测模型”。
4.5 现象:SPSS专家建模器选了一个高阶ARIMA,参数看不懂
原因:专家建模器以拟合优度为唯一目标,可能过拟合。高阶模型的参数解释性差,业务方无法理解。
解决:手动指定一个低阶模型(p和q不超过2),对比拟合优度。如果差距在可接受范围内(比如MAPE差1%以内),优先用低阶模型。在报告里写清楚模型结构和参数含义,比追求极致拟合更重要。
5. 进阶技巧:用滚动预测验证模型稳定性
模型建完不是终点,真正能说明问题的是滚动预测。做法很简单:每次用前n期训练,预测第n+1期,然后窗口向前滑动一期,重复直到数据末尾。这样你能得到每个时间点的“实时预测”,更接近真实使用场景。
% 滚动预测示例 y = data; n = length(y); window = 36; % 训练窗口长度 errors = []; for i = window:n-1 train = y(i-window+1:i); actual = y(i+1); % 拟合Holt-Winters fit = exponentialSmoothing(train, 'seasonal', 12); yp = forecast(fit, 1); errors = [errors; actual - yp]; end MAE = mean(abs(errors)); RMSE = sqrt(mean(errors.^2)); disp(['滚动预测MAE:', num2str(MAE), ',RMSE:', num2str(RMSE)]);逻辑说明:滚动预测模拟了“每次只用历史数据预测下一期”的真实场景,比一次性留出验证集更严格。窗口长度一般取2~3个季节周期,太短模型学不到季节,太长会包含过时信息。MAE和RMSE越小越好,但也要看误差是否随时间增大——如果误差越来越大,说明序列结构可能变了,模型需要重新拟合。
我一般会同时跑固定窗口和扩展窗口两种滚动预测。固定窗口假设序列结构稳定,扩展窗口假设历史信息都有用。如果两种结果差异大,说明序列存在结构性变化,需要分段建模或者加入外部变量。
从那以后我每次做时间序列预测,都强制走一遍滚动预测,不再只看一次性验证集的MAPE。这个习惯帮我提前发现了好几次模型失效的情况,也让我在给业务方解释时更有底气。希望帮到你。
本文还有配套的精品资源,点击获取