[机器学习从入门到入土] 自回归滑动平均ARMA

机器学习从入门到入土 自回归滑动平均ARMA

个人导航

知乎:https://www.zhihu.com/people/byzh_rc

CSDN:https://blog.csdn.net/qq_54636039

注:本文仅对所述内容做了框架性引导,具体细节可查询其余相关资料or源码

参考文章:各方资料

文章目录

参考资料

Box & Jenkins:时间序列分析经典框架

背景

很多序列同时存在两类朴素现象

  • 一类是惯性与相关性:当前值和过去若干时刻的值强相关
  • 另一类是冲击回响:随机扰动并非立刻消失 而会在短期内拖尾

-> AR 负责刻画值的记忆
-> MA 负责刻画噪声的记忆

ARMA 就是把两者合在一起的最经典统计基线之一

  • 既用过去的观测值解释现在
  • 也用过去的随机冲击解释现在
  • 常作为 ARIMA 的基础模块

架构(公式)

1) ARMA(p,q) 定义

设序列为 { x t } \{x_t\} {xt} 白噪声为 ε t ∼ N ( 0 , σ 2 ) \varepsilon_t \sim \mathcal{N}(0,\sigma^2) εt∼N(0,σ2)

x t = c + ∑ i = 1 p ϕ i x t − i + ε t + ∑ j = 1 q θ j ε t − j x_t = c + \sum_{i=1}^{p}\phi_i x_{t-i} + \varepsilon_t + \sum_{j=1}^{q}\theta_j \varepsilon_{t-j} xt=c+i=1∑pϕixt−i+εt+j=1∑qθjεt−j

  • c c c:常数项
  • ϕ i \phi_i ϕi:AR 系数 表示第 i i i 个滞后观测对当前的贡献
  • θ j \theta_j θj:MA 系数 表示第 j j j 个滞后冲击对当前的回响
  • p p p:AR 阶数
  • q q q:MA 阶数

直观理解

  • AR 部分负责建模可预测的结构
  • MA 部分负责建模误差的相关结构
2) 滞后算子形式

定义滞后算子 L L L 满足 L x t = x t − 1 L x_t = x_{t-1} Lxt=xt−1

定义 AR 多项式 Φ ( L ) \Phi(L) Φ(L) 和 MA 多项式 Θ ( L ) \Theta(L) Θ(L)

Φ ( L ) = 1 − ϕ 1 L − ϕ 2 L 2 − ⋯ − ϕ p L p Θ ( L ) = 1 + θ 1 L + θ 2 L 2 + ⋯ + θ q L q \Phi(L) = 1 - \phi_1 L - \phi_2 L^2 - \cdots - \phi_p L^p \\ \Theta(L) = 1 + \theta_1 L + \theta_2 L^2 + \cdots + \theta_q L^q Φ(L)=1−ϕ1L−ϕ2L2−⋯−ϕpLpΘ(L)=1+θ1L+θ2L2+⋯+θqLq

则 ARMA 可写成:
Φ ( L ) x t = c + Θ ( L ) ε t \Phi(L) x_t = c + \Theta(L)\varepsilon_t Φ(L)xt=c+Θ(L)εt

这个形式很适合讨论平稳性与可逆性

3) 平稳性

ARMA 通常要求序列平稳 否则参数会漂 预测会爆

平稳性主要由 AR 部分决定

条件是 AR 特征多项式 Φ ( z ) = 0 \Phi(z)=0 Φ(z)=0 的根都在单位圆外

记忆法

  • 根在单位圆外
  • 系统不爆炸
  • 自相关会衰减
4) 可逆性

MA 部分参数要唯一且估计稳定 常要求可逆

条件是 MA 多项式 Θ ( z ) = 0 \Theta(z)=0 Θ(z)=0 的根都在单位圆外

记忆法

  • AR 看平稳
  • MA 看可逆
  • 两者都是为了防止爆和不唯一
5) 自相关结构(ACF/PACF的经验判断)

AR§

  • PACF 往往在 p p p 阶截尾
  • ACF 往往拖尾

MA(q)

  • ACF 往往在 q q q 阶截尾
  • PACF 往往拖尾

ARMA(p,q)

  • ACF 通常拖尾
  • PACF 通常也拖尾

所以 ARMA 常需要信息准则去选阶

6) 选阶与拟合(实战最常用)

选阶常用 AIC/BIC 越小越好

  • AIC 更偏向拟合
  • BIC 更偏向简洁

ARMA 的拟合一般不用 OLS

因为 MA 部分涉及不可观测的 ε t − j \varepsilon_{t-j} εt−j

主流做法是 MLE 或数值优化

创新点

  1. 极简但强:同时建模值的记忆 与噪声的记忆
  2. 可解释: ϕ i \phi_i ϕi 对应惯性贡献 θ j \theta_j θj 对应冲击回响
  3. 强基线:Box-Jenkins 体系核心模块
  4. 低成本:参数少 拟合快 小数据友好

ARMA到底有什么用

1) 作为强基线

在预测任务里 ARMA 是经典强基线

当你上 LSTM Transformer 之前 先用 ARMA 能快速得到一个可解释且靠谱的参考误差

2) 拆结构与做残差白化

很多真实序列的误差不是白噪声 而是带短期相关的 colored noise

ARMA 可以把

  • 观测值的惯性结构
  • 噪声的拖尾结构

一起解释掉

剩下的残差更接近白噪声 方便后续做控制与检测

3) 小数据与低成本场景

ARMA 参数少 训练快 数据需求小

在样本不多或实时性强时很实用

4) 特征工程与信号任务

对 1D 信号分类任务常见用法

  • 拟合 ARMA 后用 ϕ , θ , σ 2 \phi,\theta,\sigma^2 ϕ,θ,σ2 当统计特征
  • 或者用 ARMA 先白化再做分类 提升对异常冲击的敏感度

代码实现 - numpy(模拟为主)

说明:ARMA 的严格拟合通常用 MLE statsmodels 更合适

numpy 这里重点给序列模拟与预测接口 便于理解机制

py 复制代码
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False


# =========================
# 1) ARMA(p,q) 序列模拟
# =========================
def simulate_arma(
    n: int = 400,
    phi=(0.7, -0.25),
    theta=(0.6,),
    c=0.0,
    noise_std=1.0,
    burn_in=200,
    seed=0
):
    """
    x_t = c + sum_i phi_i x_{t-i} + eps_t + sum_j theta_j eps_{t-j}
    """
    rng = np.random.default_rng(seed)

    phi = np.asarray(phi, dtype=float)
    theta = np.asarray(theta, dtype=float)
    p = len(phi)
    q = len(theta)

    # 预留足够长度用于 burn-in 与滞后
    T = n + burn_in + max(p, q) + 1

    eps = rng.normal(0.0, noise_std, size=T)
    x = np.zeros(T, dtype=float)

    # 初始化一些随机值避免全 0 起步
    for t in range(max(p, q)):
        x[t] = rng.normal(0.0, noise_std)

    for t in range(max(p, q), T):
        if p > 0:
            # 取 x[t-p],...,x[t-1] 再反转成 [x_{t-1},...,x_{t-p}]
            ar_part = float(phi @ x[t - p:t][::-1])
        else:
            ar_part = 0.0

        if q > 0:
            # 取 eps[t-q],...,eps[t-1] 再反转成 [eps_{t-1},...,eps_{t-q}]
            ma_part = float(theta @ eps[t - q:t][::-1])
        else:
            ma_part = 0.0

        x[t] = c + ar_part + eps[t] + ma_part

    return x[-n:]


# =========================
# 2) 给定参数的递推预测(多步)
# =========================
def forecast_arma_multi_step(history: np.ndarray, phi: np.ndarray, theta: np.ndarray, c: float, steps: int):
    """
    用已知参数做多步递推
    注意:严格 ARMA 预测需要对未来 eps 做条件期望
    这里给一个教学版近似:未来 eps 取 0 仅保留 AR 递推与已知历史 eps 项
    """
    history = list(np.asarray(history, dtype=float))
    phi = np.asarray(phi, dtype=float)
    theta = np.asarray(theta, dtype=float)

    p = len(phi)
    q = len(theta)

    # 近似处理:仅使用历史残差缓冲 未来残差取 0
    eps_buf = [0.0] * q

    preds = []
    for _ in range(steps):
        last_x = np.array(history[-p:][::-1]) if p > 0 else np.array([])
        last_eps = np.array(eps_buf[::-1]) if q > 0 else np.array([])

        ar_part = float(phi @ last_x) if p > 0 else 0.0
        ma_part = float(theta @ last_eps) if q > 0 else 0.0

        yhat = c + ar_part + ma_part
        preds.append(yhat)

        history.append(yhat)
        if q > 0:
            eps_buf = eps_buf[1:] + [0.0]

    return np.array(preds, dtype=float)


# =========================
# 3) Demo:模拟 + 可视化
# =========================
def demo():
    x = simulate_arma(
        n=600,
        phi=(0.75, -0.35),
        theta=(0.55,),
        c=0.2,
        noise_std=0.8,
        burn_in=400,
        seed=42
    )

    n_train = 450
    train = x[:n_train]
    test = x[n_train:]

    # 教学演示:假设我们已知真实参数
    phi = np.array([0.75, -0.35], dtype=float)
    theta = np.array([0.55], dtype=float)
    c = 0.2

    pred_multi = forecast_arma_multi_step(train, phi, theta, c, steps=len(test))
    mse_multi = float(np.mean((pred_multi - test) ** 2))

    t_train = np.arange(len(train))
    t_test = np.arange(len(train), len(train) + len(test))

    plt.figure(figsize=(10, 5))
    plt.plot(t_train, train, label="train")
    plt.plot(t_test, test, label="test (true)")
    plt.plot(t_test, pred_multi, label="ARMA多步递推预测(教学近似)")
    plt.axvline(len(train) - 1)
    plt.title(f"ARMA(p=2,q=1) - 多步递推预测 | MSE={mse_multi:.3f}")
    plt.xlabel("时间 t")
    plt.ylabel("$x_t$")
    plt.legend()
    plt.tight_layout()
    plt.show()


if __name__ == "__main__":
    demo()
相关推荐
2501_938140072 小时前
做内容很省心,2026好用AI笔记,支持抖音小红书视频无水印保存
人工智能
sell-cloud5 小时前
Prompt Engineering要凉了?Fable 5.5能“猜“意图,但银行正在封杀AI Agent——企业AI的真正护城河是什么
人工智能·prompt
Navicat中国6 小时前
Navicat 18 内置 AI 助手让数据库开发从繁琐操作迈向智能协作
大数据·人工智能·数据库开发
4SAPI7 小时前
多模型请求路由怎么设计?成本、速度和能力如何平衡
人工智能·python·gateway·php
魔乐社区7 小时前
翼芯・智算测试与适配优化专区,让国产算力“选得准、跑得通、用得好“
人工智能·开源·大模型
XCDoris9 小时前
郴州logo设计机构
大数据·人工智能·python
Goboy9 小时前
一个人带三个Agent,我用全新TRAE从0到1搭了个资讯周刊站
人工智能·trae
俊哥V9 小时前
每日 AI 研究简报 · 2026-10-19
人工智能·ai
AI_AGENT_DEV_AI9 小时前
AI英语教培智能体的开发
人工智能
物联网软硬件开发-轨物科技9 小时前
【技术白皮书】光伏清检一体化机器人系统解决方案技术白皮书
大数据·运维·网络·人工智能·机器人