news 2026/9/30 3:43:37

M4竞赛启示:时间序列预测中统计方法为何胜过深度学习?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
M4竞赛启示:时间序列预测中统计方法为何胜过深度学习?

如果你第一次听说M4,先记住一个反直觉的事实:这场时间序列预测圈里规模空前的竞赛,最后称王的不是深度学习。很多做预测的工程师至今还会拿这件事自嘲——当你在调LSTM的hidden units时,隔壁老统计学家用一行指数平滑把榜单刷到了顶部。

M4全称Makridakis Competition 4,是连续四届预测竞赛中规模最大、影响也最深远的一届:10万条真实商业与经济序列、6种采样频率、全球上千支队伍参与。它回答的问题直白到令人不适:在“真实世界”的预测场景里,到底哪种方法最能打?

这篇文章不打算复述竞赛官网的介绍页。我想从一个从业者的视角,把M4里最反直觉的结论、它背后的逻辑、以及我们今天做销量预测、流量预测或任何时序项目时该怎么抄这些经验,完整拆一遍。适合正在选型预测算法的工程师,也给那些需要向业务方解释“为什么不能直接上最复杂的模型”的朋友。

1. M4竞赛到底考了什么:10万条序列、六大频率、一个核心目标

1.1 数据集构成与测试方式,比你想象中更“真实”

M4由预测学家Spyros Makridakis组织,数据来源覆盖金融、商业、经济、人口等多个领域,全部都是真实观测序列,不是合成数据。整个训练池约有10万条序列,按采样频率分成六组:年度(Yearly)约2.3万条、季度(Quarterly)约2.4万条、月度(Monthly)约4.8万条、周度(Weekly)359条、日度(Daily)4227条、小时级(Hourly)414条。你没看错,比赛的海量数据主要集中在低频率序列上,真正的高频数据反而少得很——这一点对后文理解深度学习的失利非常关键。

测试集划分方式也值得一提。竞赛没有把10万条序列打乱后随机分割,而是按“每个序列的最后一整段”作为预测目标。比如月度序列通常留下最后18个点作为测试集,年度序列留最后6个,季度序列留最后8个,周度、日度、小时序列则各自留下一段完整周期。这种切法完全模拟实际业务中“我要预测未来N个时间点”的场景——过去已知,未来未知,没有任何后视镜可用。

我当时看到这个设置的时候,第一反应是“这也太接地气了”。很多比赛为了拼精度会把数据切得尽量均匀,M4偏偏用最接近业务的方式切:你只有历史,必须预测未来。这种朴实的评估方式,反而让比赛结果对真实项目有极强的参考价值。

1.2 核心指标:为什么M4要看MASE和OWA,而不是RMSE

M4的评估没有只看单一误差指标,而是用了三个指标的组合:sMAPE、MASE和OWA。很多新手第一次看到这堆缩写容易懵,但你只要理解一件事:主指标设计的核心诉求是“跨序列可比、不被尺度绑架”。

先看sMAPE(对称平均绝对百分比误差),公式是:

sMAPE = mean( 2 * |F_t - A_t| / (|F_t| + |A_t| ) )

直观理解就是把预测值和真实值之间的差距,除以两者绝对值的平均,得到一个“百分比化”的误差。问题在于,当真实值接近0时,分母也趋近0,一个微小的偏差就会被放大成天文数字。M4官方后来甚至专门讨论过这一点,在周度、日度序列里,某些序列的值天然很小,sMAPE就会出现异常低的“假分数”。

再来看MASE(平均绝对尺度误差),它避开了这个问题。MASE先把预测误差MAE算出来,再除以训练集内部的“季节朴素预测”误差——也就是“拿去年同期当预测”这种最简单基准的误差。因为分母是从训练集内部算出来的,它天然适应了每条序列的尺度,跨序列平均时不会让大数值序列主导结果。

OWA则是前两者的合成,中文名叫“相对加权平均”,公式是:

OWA = 0.5 * (MASE / MASE_naive + sMAPE / sMAPE_naive)

其中分母是朴素基准对应的误差。换句话说,OWA本质回答的是“你的方法比‘无脑拿前值/去年同期’好多少”,低于1说明赢过朴素基准,高于1说明连基准都没跑赢。

这对实际项目的启发非常直接:如果你在一个多序列、多业务线的预测项目里,只盯着RMSE或MAPE做模型排名,大概率会被少数几条数值极大、或接近零的序列绑架。更稳的做法是像M4一样,为每条序列单独算一个“相对基准的误差”,再取平均或看分布。

指标计算思路优势适合场景
sMAPE对称百分比误差直观,业务好解释业务本身就是百分比口径,且序列无近零值
MASE误差除以季节Naive误差跨序列可比,尺度无关多序列、混合量纲的首选
OWAMASE与sMAPE相对Naive的加权平均综合排名,抗极端值团队内部模型选型/周报

2. 榜单真相:称王的不是深度学习,而是朴素统计的组合

2.1 成绩单现象:统计组合霸榜,纯机器学习大面积垫底

M4最终公布成绩时,舆论是被震了一下的。站上领奖台最高处的,不是某个惊艳的“大模型”,而是一个你几乎不会在头条上见到的方案——统计模型组合。其核心是几个经典方法的加权平均,例如指数平滑、Theta方法、ARIMA家族的组合。紧咬其后的是一种混合思路:把指数平滑嵌入LSTM结构中,也就是后来被很多人讨论的ES-RNN类模型。

最尴尬的是纯深度学习阵营。大量参赛队伍使用的是标准LSTM、RNN、DNN架构,它们的排名却普遍靠后,甚至有一批纯深度模型的OWA超过了1.0——意思是简单到极致的Naive基准都没跑赢。Makridakis本人在赛后报告中反复强调过这个结论:大多数机器学习方法,尤其是深度学习方法,在10万条序列上的表现显著逊于统计方法。

这条结论之所以让很多人不舒服,是因为它违背了2018年前后的技术直觉。当时LSTM几乎成了“时序预测”的代名词,大家默认只要数据量足够大,深度学习总能碾压经典方法。M4给了这波狂热一记精准的耳光。

2.2 为什么统计组合反而赢了:三个绕不开的底层原因

我在复盘M4时,逐渐意识到统计组合的胜利并不是偶然,而是由时序预测这个问题的本质决定的。至少可以从三个层面理解这件事。

第一个层面是信噪比。时序预测和图像识别最大的区别在于:单条时间序列里包含的有效信息量其实非常有限。哪怕你有10万条序列,每条序列的长度也不过几十到几百个点,其中还混合着趋势、季节、噪声和随机冲击。深度学习本质上是需要海量样本才能拟合复杂映射的模型,但在“每条序列样本都很短、且序列之间分布差异巨大”的情况下,它很难从不同序列里学到通用的“模式”,只能硬背各自序列的形态,结果就是严重的过拟合。

第二个层面是归纳偏置。统计方法并不是什么都没有学,而是带着几十年沉淀下来的强先验去建模。指数平滑认为历史影响会随时间衰减,Theta方法擅长捕捉趋势和季节,ARIMA对随机过程的描述是显式建模。这些先验对短序列、强季节、低信噪比的数据几乎天然适配;而深度学习默认“一切从头学”,在有限样本下很容易把噪声当信号。

第三个层面是组合本身的魅力。组合方法的逻辑特别像炒股里的资产配置——你不知道哪个模型在哪种情况下会失效,那就让多个模型同时上场,谁在局部表现好谁就拉高整体精度,互相抵消失误。M4前几十名里有大量队伍用到了模型组合,这一点在赛后统计里非常突出:几乎所有高排名方案,都包含至少一种“平均化”操作。

用生活类比来说:统计模型像一位经验丰富的老中医,每次只给一小方,但对常见病症很有把握;深度学习像大规模体检出来的“通用处方”,在样本足够多的人身上会有平均效果,可一旦遇到一个长得不太一样的个体,就容易翻车。M4恰恰是由无数个“长得不太一样”的个体组成的。

2.3 ES-RNN的启示:深度学习不是没用,而是别单打独斗

把M4理解成“深度学习不行”就太片面了。排名靠前的ES-RNN就是一个典型反例:它把指数平滑的季节分量作为LSTM的输入特征或初始化结构,让LSTM不用从头学季节模式,只负责捕捉更复杂的残差依赖。

我后来的理解是:统计方法负责“稳定输出”,深度学习负责“处理异常和局部关联”。这种分工非常符合两者的特性。纯LSTM在M4上失利,不一定是结构有问题,更多是用错了地方——让它去完成自己最不擅长的任务:在短序列上既要学趋势、又要学季节、还要学随机噪声。这相当于让一个新人同时干三个资深专员的活,最后哪个都干不精。

所以从M4里真正应该带走的结论不是“LSTM已死”,而是“在真实业务预测里,先让可靠的老方法做底,再让深度学习补那些老方法罩不住的角落”。这个思路贯穿了后续大量工业级预测系统。

3. 从M4到实际项目:预测工程最该抄的三条作业

3.1 先上一堆基线,再谈“高级模型”

M4给我最大的工程启发其实特别朴素:在决定上LSTM、Transformer之前,先老老实实把基线模型跑完。我见过太多团队,项目启动第一天就架LSTM训练框架,折腾两周后交付的精度还没跑赢“去年同期”口径。

正确的打开方式是倒过来的。拿到一份预测需求时,第一周只干一件事:把几条基线全部跑一遍。

  • Naive预测:直接用最后一个观测值外推。
  • 季节Naive:直接用去年同期/同周期值外推。
  • 简单指数平滑(SES):适合无趋势、无季节的平稳序列。
  • Holt-Winters(三参数指数平滑):适合有趋势和季节的常见业务序列。
  • Theta方法:M4里表现优异的经典方法,statsmodels直接有实现。
  • ARIMA/AutoARIMA:适合有一定统计基础、想做白噪声检验的团队。

直觉上最容易被低估的是季节Naive。很多项目的业务序列具有强季节性——月销、周客流、日订单量——此时“拿去年同期”的效果常常能排进前三。别瞧不起这条基线,它背后是“相似日”的朴素逻辑,真实业务里往往比一堆复杂的特征工程更稳。

然后有个硬性要求:除非某个高级模型能在验证集上稳定赢过所有基线,否则不要进入下一阶段。这个门槛听起来低,实际能过滤掉七八成没必要做的“大模型工程”。

3.2 组合是免费的降方差,权重别太复杂

M4的另一个实用结论是:把多个统计模型的结果做平均,效果通常好于其中任何一个单独模型。这里有一个非常重要的工程化技巧:组合权重不必花哨。

我在实际项目里试过几种组合方式——简单平均、基于内置交叉验证的加权平均、用优化器搜索权重,最后发现收益最高的其实是“简单平均+按频率分组后加权”的组合。优化出来的权重经常过拟合验证集,上线后反而跑崩。原因很简单:时序数据本身不稳定,为了在验证集上多挤一丝精度而拟合权重,本质是在“解释噪声”。

一个可以照抄的简单组合逻辑是:模型池固定包含ETS、Theta、季节Naive、AutoARIMA;预测值直接取四者的平均值;如果某条序列明显以季节模式为主,可以把季节Naive的权重调高一点。下面是这个逻辑的极简实现代码:

import numpy as np from statsmodels.tsa.holtwinters import ExponentialSmoothing from statsmodels.tsa.theta import ThetaModel def run_combined_forecast(series, horizon, seasonal_period=12): """极简组合预测:ETS + Theta + 季节Naive 做简单平均""" # ETS ets_model = ExponentialSmoothing( series, trend="add", seasonal="add", seasonal_periods=seasonal_period, ).fit() ets_pred = ets_model.forecast(horizon) # Theta theta_model = ThetaModel(series, period=seasonal_period).fit() theta_pred = theta_model.forecast(horizon) # 季节Naive:去年同期值 naive_pred = np.tile(series[-seasonal_period:], int(np.ceil(horizon / seasonal_period)))[:horizon] # 简单平均 return 0.4 * ets_pred + 0.4 * theta_pred + 0.2 * naive_pred

注意seasonal_period根据频率变化:月度序列选12,周度序列选52,日度序列选7,小时级选24,季度选4,年度没有季节则选1。这个组合虽然简单,在大多数业务数据上已经能稳定跑进“够用”的区域,而且推理速度极快、可解释性强。

3.3 多序列预测的工程级建议:频率、标准化与验证方式

M4一共涉及6种频率。如果你用同一套参数跑所有频率,大概率会在某些频率上崩。建议对所有序列按频率分组,每个分组独立做标准化、独立调参、独立验证。

标准化这一步特别关键。多序列混合建模时,如果不把量纲统一,大数值序列会天然主导损失函数。我的习惯是对每条序列单独做z-score归一化,均值和标准差只用训练集部分计算,然后对整个序列应用。这里埋着一个很深的坑,后面第5章会专门展开。

验证方式则建议使用滚动时间窗口,而不是随机划分。每次只允许用“当前时间点之前”的数据做训练,预测“当前时间点之后”的数据。这个过程类似你在业务里每个月做一次“用历史预测下月”的复盘,效果最接近真实上线。

4. 深度学习什么时候才该上场:LSTM/Transformer的适用边界

4.1 判断深度模型该不该上的四条标准

M4之后我给自己定了一套判断标准,避免每次见到“调参狂魔”就头脑发热。以下四个条件,至少满足三条,我才会认真考虑深度模型:

  1. 单序列长度足够长,至少几千个观测点。LSTM这类模型最擅长的是从长历史里学习局部的重复模式,几十个点甚至几百个点很难支撑它的容量。
  2. 有大量同构序列,且存在共享模式。比如几百家门店的日销量,虽然每家绝对值不同,但促销响应和节假日效应相似,这给了全局模型学习的空间。
  3. 外部特征信号很强。促销、节假日、天气、流量活动这类信息对预测值有显著影响,而统计模型处理外部变量比较吃力,树模型和深度模型反而擅长。
  4. 计算与维护预算充足。深度学习意味着训练链路、GPU、特征管线、监控系统,一套下来是统计模型的好几倍成本。
判断条件满足时的选择不满足时的替代方案
单序列≥数千点深度模型或大窗口树模型ETS/Theta/ARIMA
有大量同构序列多序列全局模型单序列统计建模
外部特征显著树模型或深度模型统计模型仅靠历史值
计算维护预算充足可以试LSTM/Transformer先用基线撑住,逐步升级

反观M4,多数序列只有几百个点,外部特征完全缺失,这两条对深度模型极其不利。这也解释了为什么它在M4上整体疲软。

4.2 如果你还是要用LSTM:M4余波里的“残差混合”思路

有些场景确实需要深度学习,比如序列里有复杂的联动关系、或需要融合大量外部特征。这时候,最好别让LSTM从零开始学趋势和季节,而是先拆掉统计模型能处理的部分,只让它学剩下的残差。

具体思路受ES-RNN启发,分三步:

第一步,用STL或ETS把序列分解成趋势、季节、残差三部分。趋势和季节是比较“稳定可预期”的成分,统计方法能做得很好。 第二步,把“残差”作为LSTM的训练目标。残差里主要是随机波动与局部异常模式,这正是深度模型比较擅长捕捉的“非线性局部关联”。 第三步,预测值等于统计模型的趋势季节预测,加上LSTM对残差的预测。这样可以最大程度避免LSTM在强季节序列上浪费参数。

核心代码骨架大致长这样:

# 伪代码:统计拆解 + LSTM残差学习 from statsmodels.tsa.seasonal import STL from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense # 1. 拆解 stl = STL(series, period=12, robust=True).fit() trend_seasonal = stl.trend + stl.seasonal resid = series - trend_seasonal # 2. 对残差做序列窗口化,训练LSTM model = Sequential([ LSTM(32, input_shape=(input_steps, num_features)), Dense(horizon) ]) model.compile(optimizer="adam", loss="mse") # 训练时 x = 历史残差窗口, y = 未来残差值 # 训练完成后,输出未来残差 # 3. 最终预测 = 趋势季节外推 + 残差预测 final_pred = forecast_trend_seasonal + resid_pred

这套思路在M4的混合模型里表现亮眼,后来在很多工业项目里也被反复验证。时刻记住:统计模型是底座,深度学习是补丁,不要让补丁承担整个屋顶的重量。

另外提醒一句,M4之后的下一个赛事M5里,树模型(如LightGBM)在大量外部特征和分层预测任务中表现极强。所以别把“深度学习”当唯一解,更别把“统计方法”当成过时货,工具真要按场景挑。

5. 复现M4经验时最容易踩的四个坑

5.1 坑一:把时间序列当独立样本做随机交叉验证

这是我们最容易犯的错误,几乎每周都有团队踩中。标准机器学习里大家习惯用KFold随机打乱样本,可时序数据一旦打乱,浅层的信息会泄漏到深层,模型在验证集上的表现会被严重“高估”。

正确姿势是用TimeSeriesSplit或滚动窗口验证。sklearn里直接有现成实现:

from sklearn.model_selection import TimeSeriesSplit tscv = TimeSeriesSplit(n_splits=5) for train_idx, val_idx in tscv.split(X): # train_idx 永远在 val_idx 之前 model.fit(X[train_idx], y[train_idx]) score = evaluate(model, X[val_idx], y[val_idx])

判断自己是否踩坑,只需要问一个问题:验证集里任何一个时间点的数据,是否用到了“它未来”的信息?如果有,指标就会失真。现实中这个坑极其隐蔽,比如用了全局归一化、全局滚动统计量做特征、或者误把未来促销编码放进训练集,都会造成程度不一的泄漏。

5.2 坑二:只看RMSE,被少数异常序列绑架

RMSE是一个很容易被极端值主导的指标。假设100条序列里有一条序列的数值比其余序列大两个量级,这条序列贡献的平方误差就会占到总误差的绝大部分。模型只要“讨好”这一条序列,总体RMSE就会好看,但其余99条序列的预测质量可能一塌糊涂。

M4选择MASE和OWA的原因恰恰在这里:它对每条序列单独用“基线误差”做归一化,再等权平均,防止大数值序列“绑架”总分。落地到项目里,我的建议是错误报告别只给一个均值,要给出误差的全部分布——中位数、P75、P90,再配合分组的相对基准误差。这样模型在哪些业务线拉胯才藏不住。

5.3 坑三:标准化参数用全序列计算,造成特征泄漏

这个坑我在多序列项目里亲眼见过不止一次。有人喜欢把整个序列的均值、标准差算出来做StandardScaler,再切训练集和测试集。问题在于:测试集的均值和标准差已经被模型“看见”了,预测时信息相当于提前泄漏。

正确做法是只用训练集部分计算标准化参数:

from sklearn.preprocessing import StandardScaler scaler = StandardScaler() # 训练集部分拟合 train_scaled = scaler.fit_transform(train_series.reshape(-1, 1)) # 用训练集的参数转换测试集 test_scaled = scaler.transform(test_series.reshape(-1, 1))

如果你的模型还要用节假日、促销等外部特征,也同样要区分“已知的未来”和“预测的未来”。未来某个节假日是否举行是排期确定的,可以直接编码;但未来的促销销量是多少则是未知的,不能当真实特征塞进模型。

M4的官方设置其实天然规避了这个坑:所有测试集都是在训练集之后才暴露的。但落地到我们自己的项目时,没有官方裁判替你把关,只有自己养出“泄漏雷达”才算真正学会时间序列预测。

5.4 坑四:一套参数模板跑所有频率的序列

M4的6种频率序列,最优方法差异很大。月度序列季节周期明显是12个月,日度序列则有年度周期和星期周期叠加,小时序列又有“早晚高峰”这样的日内节律。如果复用同一组模型参数,就像用一套尺码做所有人的衣服,必然顾此失彼。

我建议按频率拆分模型池,每个频率单独评估哪个模型、哪个季节周期设置最合适。不用搞得太复杂,先按频率分组跑基线,观察误差分布,再决定是否在同一频率内部按业务类型细分(例如零售和高频交易就是完全不同的规律)。

坑典型现象正确做法
随机交叉验证验证集指标虚高,上线翻车用TimeSeriesSplit,严禁未来信息泄漏
只看RMSE少数大序列主导模型选择报告误差分布,用相对基准指标
全序列标准化测试集信息进入训练只拟合训练集参数
一套参数跑所有频率某频率表现差但找不到原因按频率分组建模和调优

6. 最后说点我的个人体会

M4这场竞赛对预测领域的影响,像一面镜子,照出了过去几年很多团队走过的弯路。我自己最大的改变是:从“模型越复杂越好”的思路,转向“先建立可靠基线,再谨慎引入复杂模型”。遇到新项目时,先跑一遍M4式的组合基线和错误分布分析,用数据说话,而不是用“这个模型比较新潮”来说话。

如果你正打算用LSTM做销量或流量预测,建议先把历史数据拆一拆,表面上看起来越规整的趋势和季节,越应该交给统计方法;真正值得深度学习出力的是那些统计方法怎么也解释不清的局部异常和共变关系。这个思路,是M4留给我最实用的一课。

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

企业微信集成GitPuk:OAuth2统一登录部署指南

你有没有遇到过这种情况:团队内部已经全员使用企业微信,却还要每个人单独注册一套代码托管平台的账号。管理员每天审批新成员、找回密码、处理重名账户,累得够呛。GitPuk是一款面向中小团队的轻量级Git托管服务,部署成本低&#x…

作者头像 李华
网站建设 2026/9/30 3:43:30

基于Python与Django的电影推荐系统:协同过滤算法与数据库设计实战

1. 为什么选“电影推荐系统”当完整项目:需求拆解与技术选型思路先说一个很多人容易忽略的点:电影推荐系统这个题目,真正考察的不是你会不会写一个算法,而是你能不能把“协同过滤算法”“Python Django”“数据库”这三样东西在同…

作者头像 李华
网站建设 2026/9/30 3:43:09

消费级GPU微调DeepSeek-R1:LoRA与Unsloth实战指南

简介:这份PDF面向希望在消费级GPU上微调大模型的AI开发者与算法工程师,聚焦DeepSeek-R1这一开源推理模型的低成本适配方案。内容围绕LoRA低秩自适应与Unsloth框架展开,讲解如何以4位量化加载预训练模型与Tokenizer,降低显存占用&a…

作者头像 李华
网站建设 2026/9/30 3:43:08

DETR完全解读:从Transformer原理到端到端目标检测实战

1. 内容整体设计与思路拆解1.1 传统目标检测的痛点:Anchor、NMS与手工设计我第一次认真读DETR论文,是2019年左右。当时目标检测这个领域其实已经有非常成熟的方案了,Faster R-CNN系列、YOLO系列、SSD系列,跑起来都能看到不错的指标…

作者头像 李华
网站建设 2026/9/30 3:42:38

Windows命令行实用指南:从基础CMD命令到自动化脚本

1. 为什么二十年过去,命令行依然是值得重学的"老古董"前两天在群里看到有人问"DOS是不是早就淘汰了,还有必要学吗",底下回答五花八门。说实话,这个问题我太熟悉了——每次带新人,总有人觉得开个命…

作者头像 李华