尧图精选

加权马尔可夫链修正ARIMA:让预测残差不再被当白噪声扔掉

🕒 发布时间:2026/10/1 15:43:55 📁 来源:尧图网络
简介这是一份《基于加权马尔可夫链修正的ARIMA预测模型的研究》期刊论文PDF面向时间序列预测、设备状态监测与组合模型建模方向的算法研究人员和工程师。论文针对ARIMA模型在非线性、非平稳序列上偏差较大且不稳定的问题引入加权马尔可夫链对残差序列进行分析并采用状态特征值结合线性插值法将残差状态转化为具体修正值最终得到更准确的预测结果。实验部分以船舶海水出口温度预测为例与单一ARIMA模型的对比显示修正后模型精度显著提高具备可行性与工程应用价值。资源包仅含1个PDF文件整体约767KB内容完整覆盖摘要、引言、模型原理、实验设计与对比分析、结论及参考文献。目前已有513人学习使用适合需要复现该组合预测方法或从事设备视情维修、轮机自动化、时间序列分析等工作的技术人员直接研读。1. 加权马尔可夫链修正 ARIMA当预测残差不再服从白噪声做时间序列预测模型落地的人大概率遇到过同一个尴尬ARIMA 的拟合优度很好看误差图却像心电图一样有规律地起伏——正误差连成片负误差也连成片。这说明模型把该学的东西学完了但残差里还残留着一种状态惯性这个月的误差偏正下个月大概率还是偏正。这时候把残差当成白噪声处理等于丢掉了最后一块可用的信息。加权马尔可夫链修正 ARIMA 的思路很直接先用 ARIMA 把线性主趋势吃干榨净再用加权马尔可夫链去刻画残差在不同状态之间的转移规律最后把预测值补回来。这篇笔记就把这套方案从原理、参数到复现代码完整拆开适合正在做短期预测、发现自己模型误差有规律而不是随机噪声的工程师。2. ARIMA 的残差为什么值得修先弄清楚哪里没学干净2.1 ARIMA 能捕获什么趋势、周期性和平稳性的边界ARIMA 在处理单变量时间序列预测时本质假设是序列当前值可以由过去的自回归项、差分项和移动平均项线性组合解释。p 阶自回归捕捉序列自身的历史依赖d 阶差分把非平稳趋势转化为平稳序列q 阶移动平均吸收历史噪声的冲击。这套线性框架在趋势稳定、周期规整、波动同方差的序列上表现相当可靠也是很多业务预测基线模型的首选。但它的边界也很清楚一旦序列存在明显的状态切换——比如设备运行模式切换、节假日前后行为突变、外部环境阶段性变化——ARIMA 只能在均值层面做一个折中拟合无法表达当前处于哪个状态、下一步更可能往哪个状态走这类信息。换成更直白的话ARIMA 是平均主义马尔可夫链是状态主义。用 AIC 或 BIC 网格搜索选出来的 ARIMA 参数描述的是整套训练数据上的最优线性依赖。拟合之后残差如果呈现系统性特征就说明有一部分结构没有被线性模型消化掉。最典型的表现是残差序列的 Ljung-Box 检验 p 值远小于 0.05拒绝了白噪声假设。很多团队在这个节点就急着换模型其实换一个复杂度更高的模型未必划算先把残差里的状态转移规律建模出来往往更轻量。2.2 残差里的惯性长什么样三个典型形态我在实际项目里见过的残差惯性大致可以归成三类。第一种是连续同号比如连续 7 天的预测误差都为正这不是巧合而是某个外部因素比如高温、促销、排产调整让序列整体抬升ARIMA 没跟上。第二种是区间往返残差从正值区间跳到负值区间再跳回来形成类似窄带振荡的形态。第三种是方差分层训练集前段残差小、后段残差大说明序列的波动结构发生了改变。这三个形态对应一个共同点残差序列的当前值对下一时刻取值有预测力。这正是马尔可夫链能建模的信息。举个例子可穿戴设备里做健康指标的时序预测时序列天然存在偏低、正常、偏高这类分级状态残差的转移路径本身就对应生理状态的切换。这类数据在构建高血压预测模型的前置特征工程里很常见残差修正后往往比直接加大模型复杂度更有效。判断残差有没有修的价值有一个很实用的先验指标计算残差的一阶自相关系数。如果一阶自相关系数的绝对值大于 0.3说明残差里确实还有结构值得往下做。小于 0.1 就不必费劲了那是真噪声。2.3 修残差的三条路为什么加权马尔可夫链更省事处理非白噪声残差常见有三条路。第一条是换非线性模型比如把历史特征喂给 xgboost回归预测模型直接做有监督回归。这条路的问题是特征工程成本高需要构造滞后特征、窗口统计特征、外部变量而且对样本量要求不低数据短了就很容易过拟合。第二条是上 prophet时序预测模型它对季节性和节假日效应建模好但残差修正不是它的核心设计目标处理不了那种状态依赖很强的残差。第三条就是加权马尔可夫链把残差划分成几个状态区间用转移概率描述状态之间的跳转再加权体现近期样本的重要性。三条路放在一起看加权马尔可夫链的优点非常突出参数少只有状态数、权重衰减系数、滞后阶数三个核心参数可解释性强每一行转移概率矩阵都能翻译成业务语言比如误差从偏高状态跳回正常状态的概率是 0.6对样本量不敏感几百个残差点就能把转移矩阵估计出来。对比逻辑见下表。方案特征工程成本可解释性样本量要求适用场景xgboost回归预测模型高低高特征丰富、样本充足prophet时序预测模型中中中周期强、节假日效应明显加权马尔可夫链修正低高低残差有状态惯性、样本量中等3. 加权马尔可夫链的原理与参数两个加权分别加在哪里3.1 从残差到状态分位数划分与转移矩阵把马尔可夫链用在残差修正上第一步是把连续残差变成离散状态。做法一般是按残差的分位数切出 K 个区间比如 K5对应大幅偏低、偏低、正常、偏高、大幅偏高五个状态。用分位数而不是等宽划分是因为残差通常集中在 0 附近等宽划分会导致极端状态的样本极少转移概率估计不可靠。状态序列构造好之后统计状态之间的跳转频数就得到转移矩阵。假设三个状态 A、B、C转移矩阵第 i 行第 j 列的含义是当前处于状态 i下一步转移到状态 j 的概率。训练集上如果观察到从 A 跳到 B 出现 8 次从 A 跳到 A 出现 2 次那 A 行就是 [0.2, 0.8, 0.0]。这个矩阵就是修正的核心依据。预测时看当前时刻残差落在哪个状态从矩阵里取出对应行把行概率与每个状态的代表值通常取该状态区间内残差的均值做加权平均就得到下一时刻的残差期望修正量。最终预测值等于 ARIMA 预测值加上这个修正量。逻辑上是把预测残差当成一个独立的小模型来处理。这里要特别注意一点马尔可夫链的无后效性假设。标准马尔可夫链认为下一时刻状态只取决于当前状态但真实残差序列往往不完全满足这一点。这也是为什么要引入加权——通过多步转移矩阵组合把更久之前的状态信息也带进来。3.2 加权一近期样本权重让转移矩阵更贴合当下第一个加权维度在转移概率估计的阶段。常规做法是直接统计频数但这样所有历史转移样本是等权的。实际场景里残差的状态模式可能随业务环境缓慢漂移半年前的转移规律未必适用于现在。我一般会引入一个指数衰减权重距今越近的转移事件贡献越大。具体实现是在统计从状态 i 转移到状态 j 的次数时给每一条转移事件乘一个权重 w_t λ^(T-t)其中 T 是残差序列末尾时刻t 是该转移事件发生的时间位置λ 是衰减系数。λ 越接近 1历史信息保留得越多λ 越小模型对近期模式越敏感。按我的使用经验λ 落在 0.90 到 0.99 之间最稳。样本量超过 500 时可以激进一点取 0.90让模型快速适应当前状态样本量只有一两百时取 0.98 以上避免某个近期异常值把矩阵拉偏。不建议低于 0.85否则转移矩阵会退化成只看最近十几个点稳定性明显变差。3.3 加权二滞后步长权重组合多阶信息第二个加权维度在预测阶段。为了弥补一阶马尔可夫链的短视常见做法是同时构建滞后 1 步、2 步、L 步的转移矩阵再给不同滞后赋予不同权重。滞后步长的权重也做衰减β^(l-1)l 是滞后阶数。比如滞后 1 阶权重 1.0滞后 2 阶权重 0.7滞后 3 阶权重 0.49做归一化后合成最终的修正期望。这两个加权叠加起来就是标题里加权二字的完整含义既在估计阶段向近期样本倾斜又在预测阶段组合多步转移信息。前者解决模式漂移问题后者解决无后效性假设过强的问题。两者不是必选只做其中一个也能工作但组合起来效果最稳。3.4 参数与稀疏矩阵处理不加平滑会翻车核心参数归结为四个状态数 K、近端样本衰减系数 λ、滞后阶数 L、滞后步长权重系数 β。推荐范围如下表。参数含义推荐范围经验说明K残差状态数36超过 6 矩阵稀疏低于 3 信息太少λ样本时间衰减系数0.900.99样本量大取 0.90量小取 0.98L最大滞后阶数24超过 4 权重趋零收益递减β滞后衰减系数0.50.8常用 0.7业务状态变化快就取 0.5还有一个几乎每次都会撞上的问题某个转移行可能完全没有样本。比如状态大幅偏高最近出现的次数本来就少从它出发的转移记录可能为零归一化时分母为 0。常规处理是拉普拉斯平滑在频数矩阵上整体加 1再做行归一化。这样确保每一行都是合法的概率分布不会出现预测时取到 NaN。之前有同事没做这一步上线第一个星期就遇到了输出空值排查半天发现是转移矩阵某个行和为 0。4. Python 复现从 ARIMA 拟合到加权马尔可夫链修正的完整流程4.1 数据准备与 ARIMA 超参选择实现这套方案不需要特别重的依赖statsmodels 加 numpy、pandas 就够。我习惯先把数据读进来按时间排序然后做 ARIMA 参数的网格搜索。用 AIC 作为选择标准因为 AIC 在样本量中等时比 BIC 更适合预测导向的选模。import numpy as np import pandas as pd from statsmodels.tsa.arima.model import ARIMA df pd.read_csv(your_series.csv, parse_dates[date], index_coldate) df df.sort_index() # 用AIC网格搜索ARIMA(p,d,q)范围按业务经验控制 best_aic np.inf best_order None for p in range(0, 4): for d in range(0, 2): for q in range(0, 4): try: model ARIMA(df[value], order(p, d, q)).fit() if model.aic best_aic: best_aic model.aic best_order (p, d, q) except Exception: continue print(fbest_order: {best_order}, AIC: {best_aic:.2f})p、d、q 的范围收敛在 03、01、03 是常规做法。d 取到 2 的情况很少除非序列本身就是 I(2) 过程。搜索过程用 try 包住是因为某些参数组合下模型可能收敛失败或矩阵奇异直接跳过比中断主流程更省心。4.2 拟合 ARIMA 并提取样本内残差选定参数后在训练集上拟合提取样本内残差。注意差分阶数 d 大于 0 时fittedvalues 靠前的位置会出现 NaN因为差分后的初始值无法被模型复现需要剔除。train df.iloc[: int(len(df) * 0.8)] test df.iloc[int(len(df) * 0.8):] model ARIMA(train[value], orderbest_order).fit() fitted model.fittedvalues resid train[value] - fitted resid resid.dropna() print(f训练集样本数: {len(train)}, 有效残差数: {len(resid)})残差的构造方式需要想清楚这里用的是样本内拟合值与真实值的差代表 ARIMA 在训练集上的未解释部分。后面预测阶段产生的残差也会逐步加入状态序列保持状态序列的持续更新。4.3 分位数状态编码用分位数把残差切成 K 个状态。K 的选择我会先看残差分布如果残差基本对称K5 通常够用如果希望捕捉极端情况可以加到 6但不要超过 6。K 越大转移矩阵的每行样本越少统计可靠性下降。n_states 5 quantiles np.quantile(resid, np.linspace(0, 1, n_states 1)) quantiles[0] -np.inf quantiles[-1] np.inf states np.digitize(resid, binsquantiles[1:-1]) state_means [resid[states i].mean() for i in range(n_states)] print(分位边界:, quantiles[1:-1]) print(各状态残差均值:, state_means)state_means 是每个状态的代表值。修正时转移概率行向量与 state_means 做点积得到的是残差的期望估计。用区间均值而不是区间中点是因为残差在区间内往往不是均匀分布。4.4 构建加权转移矩阵下面这段是核心逻辑。统计转移频数时加入指数衰减权重近期样本权重更高再用拉普拉斯平滑兜底。def build_weighted_transition_matrix(states, alpha0.95): n len(states) k states.max() 1 transition np.zeros((k, k)) for t in range(n - 1): w alpha ** (n - 1 - t) # 越靠近末尾权重越大 i states[t] j states[t 1] transition[i, j] w # 拉普拉斯平滑避免零行导致的NaN transition transition 1.0 P transition / transition.sum(axis1, keepdimsTrue) return P这里的关键细节是权重计算的方向。设 T n - 1 为最后一个转移事件的位置第 t 个转移事件的权重是 α^(T-t)距离末尾越近指数越小权重越接近 1。尾部样本在矩阵中的话语权就越大。alpha 取 0.95 时20 个时间步之前的事件权重约为 0.36100 个时间步之前只剩约 0.006。4.5 多阶转移矩阵与最终修正单阶转移矩阵的信息量有限我会再构建滞后 2、3 阶的矩阵并用 β 衰减合成期望修正值。def multi_step_expectation(states, max_lag3, alpha0.95, beta0.7): n len(states) k states.max() 1 P_list [] for lag in range(1, max_lag 1): trans np.zeros((k, k)) for t in range(n - lag): w alpha ** (n - lag - t) trans[states[t], states[t lag]] w trans trans 1.0 P trans / trans.sum(axis1, keepdimsTrue) P_list.append(P) # 滞后步长权重短滞后优先 lag_w np.array([beta ** (l - 1) for l in range(1, max_lag 1)]) lag_w lag_w / lag_w.sum() cur_state states[-1] expectation 0.0 for lag in range(max_lag): expectation lag_w[lag] * np.dot(P_list[lag][cur_state], state_means) return expectation, P_list这个函数返回两个东西修正期望值和多阶转移矩阵列表。修正期望就是下一时刻残差的预测值最终预测等于 ARIMA 预测加上这个修正期望。4.6 滚动预测评估验证阶段采用单步滚动预测。每一步用截至当前时刻的数据重新拟合 ARIMA再叠加修正值然后与真实值对比。from sklearn.metrics import mean_absolute_error history train[value].tolist() test_values test[value].tolist() pred_arima_all [] pred_final_all [] states_history states.copy() for i in range(len(test_values)): model_refit ARIMA(history, orderbest_order).fit() pred_arima model_refit.forecast(1).iloc[0] correction, _ multi_step_expectation(states_history) pred_final pred_arima correction pred_arima_all.append(pred_arima) pred_final_all.append(pred_final) actual test_values[i] new_resid actual - pred_arima new_state np.digitize(new_resid, binsquantiles[1:-1]) states_history np.append(states_history, new_state) history.append(actual) mae_arima mean_absolute_error(test_values, pred_arima_all) mae_final mean_absolute_error(test_values, pred_final_all) print(fARIMA MAE: {mae_arima:.4f}) print(fARIMA马尔可夫修正 MAE: {mae_final:.4f})每一步都重新拟合 ARIMA 在数据量大时比较慢。生产环境里常见的优化是每 10 步或 20 步重估一次 ARIMA 参数中间步数直接使用模型外推只有状态序列逐步更新。这种做法的精度损失通常很小但速度提升明显。5. 避坑与常见问题四个踩过才会懂的参数陷阱5.1 差分阶数过高转移矩阵退化成单位矩阵现象修正后的预测结果几乎等于纯 ARIMA 预测MAE 没有改善打印转移矩阵发现对角线元素接近 1。原因d 阶差分把残差序列的短期结构磨平了。差分本身是强滤波d 越大序列的波动细节丢失越多。残差状态序列变成缓慢爬行的形态相邻状态基本保持不变转移矩阵自然收敛到单位矩阵。解决把 d 的搜索范围限制在 0 和 1不要轻易尝试 d2。如果业务序列本身有很强的趋势和季节性优先考虑 SARIMA 而不是加高差分阶数。另一个做法是检查残差序列的一阶自相关系数如果差分后残差自相关接近 0说明马尔可夫链没有信息可用直接放弃修正。5.2 状态数设太多转移矩阵稀疏导致预测值抖动现象K 取到 8 或 10 以后预测曲线出现很多毛刺修正值在相邻两步之间大幅跳变。原因残差样本量不变状态区间变多每个状态对应的转移样本变少。某些状态行只有两三个样本转移概率估计受单个样本影响过大行概率向量不光滑。解决K 控制在 36 之间。如果业务场景需要区分更多状态级别至少保证每个状态区间内样本量不低于 30。样本量只有 200 时K5 已经是上限。还有一个辅助手段对转移矩阵做一次列方向的平滑让相邻状态的概率过渡更自然。5.3 验证集残差方差大于训练集状态偏移现象训练集上修正效果明显验证集上一测试就失效甚至 MAE 比纯 ARIMA 还差。原因样本内拟合残差的方差通常小于一步预测残差的方差。ARIMA 在训练集上的拟合值用的是全部历史信息预测值只用了截至当前时刻的信息预测误差天然更大。按训练集分位数划出的状态边界在验证集上会导致大量残差落在偏高和大幅偏高这两个状态里转移矩阵缺乏对这些状态的有力过渡。解决在构建状态序列时给训练集残差乘以一个方差异常系数近似一步预测误差的分布。常见做法是先用前 20% 的训练集做一次模拟滚动预测得到一步预测残差用这个残差的方差重新缩放状态边界。代价是要多跑一次滚动预测但状态边界贴合真实预测场景修正效果稳定很多。5.4 多步预测时修正失效误差累积现象预测未来 5 步、10 步时修正模型的结果反而不如纯 ARIMA且步数越多差距越大。原因马尔可夫链修正的是残差的期望一步预测时残差状态已知修正可靠。多步预测时ARIMA 的预测值本身在滚动更新残差状态只能依赖前面步数的预测残差误差层层传递修正量本身就带噪声。解决这个方案建议只做单步或最多三步以内的短期预测。业务上确实需要多步预测时可以对修正量加一个衰减因子比如第 h 步修正量乘以 ρ^hρ 取 0.50.8让修正的置信度随步长递减。别指望马尔可夫链能解决长期预测问题那不是它的适用边界。5.5 权重衰减系数取太大修正过于激进现象修正模型在大多数时段表现好但遇到个别异常值后连续好几个步数的预测都被拉偏。原因λ 取 0.99 时近期样本权重占比过高一个极端的近期残差事件会在转移矩阵里留下很大痕迹后续几步修正都受影响。解决λ 不要一刀切。样本量大且序列波动稳定时取 0.900.93让单个异常事件的影响快速衰减样本量小或业务状态切换缓慢时取 0.970.98。判断标准是如果修正后的 MAE 在正常时段下降了但每遇到异常值就要震荡五六步才恢复说明权重衰减过慢把 λ 往 0.90 的方向调。6. 验证修正是否有效三种对比方法和一个进阶技巧6.1 前置检验先确认残差不是白噪声修正前先跑一次 Ljung-Box 检验用 p 值判断有没有修正空间。from statsmodels.stats.diagnostic import acorr_ljungbox lb acorr_ljungbox(resid, lags[10], return_dfTrue) print(lb)p 值大于 0.05 时残差已经接近白噪声加马尔可夫链修正属于硬加噪声只会让模型变差。p 值小于 0.01 时修正价值明显。这是一个成本几乎为零的前置筛选值得养成习惯。6.2 基线对比纯 ARIMA、修正模型、直接换非线性模型评估阶段至少要保留两条基线纯 ARIMA 和修正模型。如果条件允许再加一条 xgboost回归预测模型 的基线作为成本参考。三者的对比不只看 MAE还要看误差分布。修正模型的优势往往体现在误差分位数上P90 误差下降明显说明那些原本偏得离谱的样本被拉了回来而不是只降了均值。我习惯把误差图按时间顺序画出来观察修正模型是否把原来连片的同号误差打断了。如果曲线从长条形同色块变成短促交替说明状态转移机制确实捕捉到了残差惯性。6.3 进阶技巧把修正状态从残差扩展到业务状态马尔可夫链修正不一定只作用于残差。如果业务本身有明确的状态定义比如设备运行模式、库存周转级别、血压监测数据的风险等级可以直接把业务状态序列和残差状态序列拼接成一个复合状态。这样修正时不仅看残差往哪走还看业务状态有没有切换。复合状态矩阵的维度会变成两个状态数的乘积K 的取值要相应缩小否则矩阵稀疏问题会立刻回来。我在一个用电负荷预测项目里用过这个技巧复合状态修正比单纯残差修正的 MAPE 额外下降了大约 8%。代价是状态序列的维护逻辑复杂一些但产出回报是值得的。这个方向做透以后你会发现预测模型调参的精力不需要都花在 ARIMA 上把残差和状态的交互吃透往往才是预测精度真正上台阶的地方。希望这篇笔记能帮你把加权马尔可夫链修正 ARIMA 从论文概念变成自己手里的可用工具。我自己的习惯是任何改动的第一步先跑 Ljung-Box 看残差第二步跑一次滚动验证看增益从不跳过。这两个动作做完了模型效果好不好、值不值得上线大概率已经有了答案。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →