Day 57 经典时序模型(1)——差分、ACF/PACF 与 AR/MA/ARMA

文章目录

Day 57 · 经典时序模型(1)——差分、ACF/PACF 与 AR/MA/ARMA

学习要点

  1. 平稳性为什么重要(很多经典模型的前提)。
  2. 差分如何消除趋势(让序列更接近平稳)。
  3. 季节性差分如何消除周期波动。
  4. ACF / PACF如何辅助判断:AR§、MA(q)、ARMA(p,q)。

注意

  • 下面的例子主要用模拟数据,目的是把概念“看见”。
  • ACF/PACF 的经验规律适用于已经平稳的序列;如果原序列不平稳,请先差分。

先回顾:我们要检验什么?

做经典时间序列建模(如 ARIMA)前,常见的“体检项目”包括:

  1. 自相关性(ACF/PACF):序列是否存在滞后相关(是否“有记忆”)。
  2. 平稳性(ADF):均值/方差等统计特性是否随时间变化。
  3. 季节性:是否存在固定周期(如月度数据的 12 个月周期)。

接下来我们主要处理两类“常见问题”:

  • 趋势导致的非平稳 → 用(普通)差分处理。
  • 季节性导致的周期结构 → 用季节性差分处理。

而“自相关性”并不是要消除的毛病,反而是后续选择 AR/MA/ARMA 的重要线索。

一、让序列更平稳:差分

1.1 为什么要平稳?

很多经典时序模型假设序列的统计特性相对稳定(均值、方差、协方差不随时间漂移)。
如果序列存在明显趋势(均值在变)或波动强度在变(方差在变),模型会更难“抓住规律”。

1.2 普通差分(处理趋势)

差分的思想:把“水平”变化转为“变化速度”。

  • 一阶差分
    Δ y t = y t − y t − 1 \Delta y_t = y_t - y_{t-1} Δyt​=yt​−yt−1​
  • 二阶差分(对一阶差分再差分):
    Δ 2 y t = Δ y t − Δ y t − 1 \Delta^2 y_t = \Delta y_t - \Delta y_{t-1} Δ2yt​=Δyt​−Δyt−1​

实践中通常先尝试一阶差分;差分次数越高,越容易把结构“过度差分”掉(信息被抹平)。

# 通用依赖与工具函数import warnings warnings.filterwarnings("ignore")import numpy as np import pandas as pd import matplotlib.pyplot as plt from statsmodels.tsa.stattools import adfuller from statsmodels.graphics.tsaplots import plot_acf, plot_pacf from statsmodels.tsa.arima_process import ArmaProcess from statsmodels.tsa.arima.model import ARIMA # 尽量避免中文乱码:优先使用 SimHei,没有的话会回退到其他字体 plt.rcParams["font.sans-serif"]=["SimHei","Arial Unicode MS","DejaVu Sans"] plt.rcParams["axes.unicode_minus"]=Falsedefadf_test(series: pd.Series, name:str="序列"):"""ADF 单位根检验:p-value 越小,越倾向于拒绝“存在单位根(非平稳)”的原假设。""" series = pd.Series(series).dropna() stat, p_value, _, _, critical_values, _ = adfuller(series, autolag="AIC")print(f"[{name}] ADF Statistic: {stat:.4f}")print(f"[{name}] p-value : {p_value:.6f}")print(f"[{name}] Critical : {{k:round(v,4)for k, v in critical_values.items()}}")

1.3 用“随机游走 + 趋势”构造一个典型的非平稳序列

随机游走(Random Walk)是时间序列里非常经典的“非平稳”例子:

  • 它会随时间漂移,没有稳定的均值;
  • 叠加一个线性趋势后,非平稳性会更明显。

下面我们生成一段数据,并用 ADF 检验 + 一阶差分来观察“治疗前后”的变化。

# 1) 生成非平稳数据:随机游走 + 线性趋势 np.random.seed(42) n =500 random_walk = np.random.randn(n).cumsum()# 累积和 -> 随机游走 trend = np.linspace(0,100, n)# 线性趋势 data = pd.Series(random_walk + trend) data.index = pd.date_range(start="2022-01-01", periods=n, freq="D") plt.figure(figsize=(12,4)) plt.plot(data) plt.title("原始序列:随机游走 + 趋势(明显非平稳)") plt.tight_layout() plt.show() adf_test(data, name="原始序列")
在这里插入图片描述
[原始序列] ADF Statistic: 0.1358 [原始序列] p-value : 0.968421 [原始序列] Critical : {'1%': np.float64(-3.4435), '5%': np.float64(-2.8673), '10%': np.float64(-2.5699)} 
# 2) 一阶差分:尝试消除趋势 data_diff_1 = data.diff().dropna() plt.figure(figsize=(12,4)) plt.plot(data_diff_1) plt.axhline(0, color="gray", linewidth=1, linestyle="--") plt.title("一阶差分后的序列(通常更接近平稳)") plt.tight_layout() plt.show() adf_test(data_diff_1, name="一阶差分后")
在这里插入图片描述
[一阶差分后] ADF Statistic: -22.3130 [一阶差分后] p-value : 0.000000 [一阶差分后] Critical : {'1%': np.float64(-3.4435), '5%': np.float64(-2.8674), '10%': np.float64(-2.5699)} 

二、处理季节性:季节性差分

很多序列(销量、客流、气温)会在固定周期内重复波动,这就是季节性。

2.1 季节性差分(Seasonal Differencing)

思想与普通差分相同,只是“减去的不是上一期”,而是“减去上一个周期的同位置”。

Δ s y t = y t − y t − s \Delta_s y_t = y_t - y_{t-s} Δs​yt​=yt​−yt−s​

  • 月度数据的年度季节:s = 12
  • 季度数据的年度季节:s = 4

如果序列同时存在趋势 + 季节性,常见做法是:

  • 先做季节性差分(去周期),再对结果做一阶差分(去趋势)。
# 生成一段“趋势 + 季节性 + 噪声”的月度序列,并做季节性差分 np.random.seed(7)# 4 年月度数据(48个点),周期为 12 time_index = pd.date_range(start="2020-01-01", periods=48, freq="M") seasonal =10* np.sin(np.arange(48)*(2* np.pi /12))# 振幅10,周期12 trend = np.linspace(0,20,48) noise = np.random.randn(48)*2 seasonal_data = pd.Series(seasonal + trend + noise, index=time_index) seasonal_diff_12 = seasonal_data.diff(periods=12).dropna() fig, axes = plt.subplots(2,1, figsize=(12,6), sharex=True) axes[0].plot(seasonal_data) axes[0].set_title("原始季节性序列(趋势 + 季节 + 噪声)") axes[1].plot(seasonal_diff_12) axes[1].axhline(0, color="gray", linewidth=1, linestyle="--") axes[1].set_title("季节性差分后(s=12)") plt.tight_layout() plt.show() adf_test(seasonal_data, name="原始季节性序列") adf_test(seasonal_diff_12, name="季节性差分后(s=12)")
在这里插入图片描述
[原始季节性序列] ADF Statistic: 0.7819 [原始季节性序列] p-value : 0.991338 [原始季节性序列] Critical : {'1%': np.float64(-3.6155), '5%': np.float64(-2.9413), '10%': np.float64(-2.6092)} [季节性差分后(s=12)] ADF Statistic: -5.5909 [季节性差分后(s=12)] p-value : 0.000001 [季节性差分后(s=12)] Critical : {'1%': np.float64(-3.6327), '5%': np.float64(-2.9485), '10%': np.float64(-2.613)} 

三、模型选择:AR / MA / ARMA 与 ACF/PACF

现在假设我们已经拿到了平稳序列(原序列平稳,或通过差分变得平稳)。

3.1 ACF 与 PACF:分别在看什么?

  • ACF(自相关): y t y_t yt​ 与 y t − k y_{t-k} yt−k​ 的相关性(包含间接影响)。
  • PACF(偏自相关):控制了中间滞后项后, y t y_t yt​ 与 y t − k y_{t-k} yt−k​ 的“直接相关”。

3.2 “截尾”与“拖尾”(经验规律)

模型ACF 特征PACF 特征
AR§拖尾在 p 阶后截尾
MA(q)在 q 阶后截尾拖尾
ARMA(p,q)拖尾拖尾

注意:这是非常常用的入门规律,但真实业务数据里常需要结合 AIC/BIC、残差白噪声检验等一起判断。

3.3 AR§:自回归(“惯性/记忆”)

AR§ 的直观解释:当前值由过去 p 期的值线性决定(再加上随机扰动)。

y t = ϕ 1 y t − 1 + ⋯ + ϕ p y t − p + ε t y_t = \phi_1 y_{t-1} + \cdots + \phi_p y_{t-p} + \varepsilon_t yt​=ϕ1​yt−1​+⋯+ϕp​yt−p​+εt​

下面模拟一个 AR(2) 序列,并用 ACF/PACF 验证“PACF 在 2 阶后截尾”的现象。

# --- 案例一:AR(2) ---print("--- 案例一:AR(2) 模型 ---")# AR(2):y_t = 0.7 y_{t-1} + 0.2 y_{t-2} + ε_t ar_params = np.array([0.7,0.2]) ma_params = np.array([])# from_coeffs 的 AR 系数会按统计学常见写法自动处理符号 ar_process = ArmaProcess.from_coeffs(arcoefs=ar_params, macoefs=ma_params) np.random.seed(100) ar_data = ar_process.generate_sample(nsample=500) fig, axes = plt.subplots(3,1, figsize=(10,9)) axes[0].plot(ar_data) axes[0].set_title("模拟序列:AR(2)") plot_acf(ar_data, ax=axes[1], lags=20, title="ACF(AR 通常拖尾)") plot_pacf(ar_data, ax=axes[2], lags=20, title="PACF(AR(p) 通常在 p 阶截尾)") plt.tight_layout() plt.show()
--- 案例一:AR(2) 模型 --- 
在这里插入图片描述
# 使用 ARIMA(p,d,q) 形式拟合:AR(2) 等价于 ARIMA(2,0,0) model_ar = ARIMA(ar_data, order=(2,0,0)).fit()print(model_ar.summary())
 SARIMAX Results ============================================================================== Dep. Variable: y No. Observations: 500 Model: ARIMA(2, 0, 0) Log Likelihood -724.007 Date: Fri, 09 Jan 2026 AIC 1456.014 Time: 15:58:24 BIC 1472.873 Sample: 0 HQIC 1462.629 - 500 Covariance Type: opg ============================================================================== coef std err z P>|z| [0.025 0.975] ------------------------------------------------------------------------------ const -0.0971 0.578 -0.168 0.867 -1.231 1.036 ar.L1 0.6557 0.042 15.552 0.000 0.573 0.738 ar.L2 0.2646 0.043 6.096 0.000 0.180 0.350 sigma2 1.0562 0.066 16.075 0.000 0.927 1.185 =================================================================================== Ljung-Box (L1) (Q): 0.04 Jarque-Bera (JB): 3.45 Prob(Q): 0.84 Prob(JB): 0.18 Heteroskedasticity (H): 0.96 Skew: 0.19 Prob(H) (two-sided): 0.79 Kurtosis: 3.15 =================================================================================== Warnings: [1] Covariance matrix calculated using the outer product of gradients (complex-step). 

3.4 MA(q):移动平均(“短期冲击”)

MA(q) 的直观解释:当前值由当前与过去 q 期的**随机冲击(误差项)**叠加形成。

y t = ε t + θ 1 ε t − 1 + ⋯ + θ q ε t − q y_t = \varepsilon_t + \theta_1 \varepsilon_{t-1} + \cdots + \theta_q \varepsilon_{t-q} yt​=εt​+θ1​εt−1​+⋯+θq​εt−q​

它很适合描述“突发冲击会影响一小段时间然后消失”的现象,例如:

  • 生产线短暂故障、突发促销、短期测量误差。

MA(q) 的典型经验规律:ACF 在 q 阶后截尾,而 PACF 往往拖尾。

# --- 案例二:MA(2) ---print("--- 案例二:MA(2) 模型 ---")# MA(2):y_t = ε_t + 0.8 ε_{t-1} + 0.4 ε_{t-2} ar_params = np.array([]) ma_params = np.array([0.8,0.4]) ma_process = ArmaProcess.from_coeffs(arcoefs=ar_params, macoefs=ma_params) np.random.seed(200) ma_data = ma_process.generate_sample(nsample=500) fig, axes = plt.subplots(3,1, figsize=(10,9)) axes[0].plot(ma_data) axes[0].set_title("模拟序列:MA(2)") plot_acf(ma_data, ax=axes[1], lags=20, title="ACF(MA(q) 通常在 q 阶截尾)") plot_pacf(ma_data, ax=axes[2], lags=20, title="PACF(MA 通常拖尾)") plt.tight_layout() plt.show()
--- 案例二:MA(2) 模型 --- 
在这里插入图片描述
# MA(2) 等价于 ARIMA(0,0,2) model_ma = ARIMA(ma_data, order=(0,0,2)).fit()print(model_ma.summary())
 SARIMAX Results ============================================================================== Dep. Variable: y No. Observations: 500 Model: ARIMA(0, 0, 2) Log Likelihood -704.426 Date: Fri, 09 Jan 2026 AIC 1416.852 Time: 15:58:25 BIC 1433.710 Sample: 0 HQIC 1423.467 - 500 Covariance Type: opg ============================================================================== coef std err z P>|z| [0.025 0.975] ------------------------------------------------------------------------------ const 0.0582 0.100 0.584 0.559 -0.137 0.253 ma.L1 0.8252 0.041 19.978 0.000 0.744 0.906 ma.L2 0.4180 0.041 10.099 0.000 0.337 0.499 sigma2 0.9785 0.063 15.604 0.000 0.856 1.101 =================================================================================== Ljung-Box (L1) (Q): 0.42 Jarque-Bera (JB): 0.01 Prob(Q): 0.51 Prob(JB): 0.99 Heteroskedasticity (H): 1.08 Skew: -0.01 Prob(H) (two-sided): 0.62 Kurtosis: 2.99 =================================================================================== Warnings: [1] Covariance matrix calculated using the outer product of gradients (complex-step). 

3.5 ARMA(p,q):惯性 + 冲击的混合

真实世界经常同时存在:

  • 惯性(AR):例如销量受上个月销量影响;
  • 短期冲击(MA):例如某次活动/舆情导致短期偏离。

ARMA(p,q) 的经验特征:ACF 与 PACF 往往都会拖尾,因此仅凭图形精确定阶会更难。
常见策略是从低阶(如 (1,1))开始,结合 AIC/BIC 与残差诊断逐步选择。

# --- 案例三:ARMA(1,1) ---print("--- 案例三:ARMA(1,1) 模型 ---")# ARMA(1,1):y_t = 0.8 y_{t-1} + ε_t + 0.5 ε_{t-1} ar_params = np.array([0.8]) ma_params = np.array([0.5]) arma_process = ArmaProcess.from_coeffs(arcoefs=ar_params, macoefs=ma_params) np.random.seed(300) arma_data = arma_process.generate_sample(nsample=500) fig, axes = plt.subplots(3,1, figsize=(10,9)) axes[0].plot(arma_data) axes[0].set_title("模拟序列:ARMA(1,1)") plot_acf(arma_data, ax=axes[1], lags=20, title="ACF(ARMA 常拖尾)") plot_pacf(arma_data, ax=axes[2], lags=20, title="PACF(ARMA 常拖尾)") plt.tight_layout() plt.show()
--- 案例三:ARMA(1,1) 模型 --- 
在这里插入图片描述
# ARMA(1,1) 等价于 ARIMA(1,0,1) model_arma = ARIMA(arma_data, order=(1,0,1)).fit()print(model_arma.summary())
 SARIMAX Results ============================================================================== Dep. Variable: y No. Observations: 500 Model: ARIMA(1, 0, 1) Log Likelihood -709.905 Date: Fri, 09 Jan 2026 AIC 1427.810 Time: 15:58:25 BIC 1444.669 Sample: 0 HQIC 1434.426 - 500 Covariance Type: opg ============================================================================== coef std err z P>|z| [0.025 0.975] ------------------------------------------------------------------------------ const 0.4134 0.284 1.455 0.146 -0.144 0.970 ar.L1 0.7579 0.032 24.059 0.000 0.696 0.820 ma.L1 0.5038 0.043 11.664 0.000 0.419 0.588 sigma2 0.9982 0.062 16.094 0.000 0.877 1.120 =================================================================================== Ljung-Box (L1) (Q): 0.49 Jarque-Bera (JB): 11.71 Prob(Q): 0.48 Prob(JB): 0.00 Heteroskedasticity (H): 0.82 Skew: 0.35 Prob(H) (two-sided): 0.20 Kurtosis: 3.26 =================================================================================== Warnings: [1] Covariance matrix calculated using the outer product of gradients (complex-step). 

总结

今日所学

  • 趋势导致的非平稳:用 一阶/二阶差分Series.diff())。
  • 季节性:用 季节性差分Series.diff(periods=s))。
  • 定阶线索:在平稳序列上观察 ACF/PACF 的截尾与拖尾。

与 ARIMA 的关系

ARIMA(p, d, q) 三个参数含义:

  • p:AR 阶数(常从 PACF 的截尾特征获取线索)
  • d:差分次数(让序列更接近平稳)
  • q:MA 阶数(常从 ACF 的截尾特征获取线索)

@浙大疏锦行

Read more

从Prompt到成片仅需2.3秒,Seedance 2.0如何重构AIGC工作流?——头部客户实测ROI提升340%,但90%团队尚未启用映射热更新模式

第一章:Seedance 2.0语义理解与视频生成映射的技术本质 Seedance 2.0 的核心突破在于将自然语言语义空间与高保真视频表征空间建立可微、对齐且可泛化的双向映射。该映射并非简单地将文本嵌入向量输入扩散模型,而是通过分层语义解耦机制,在动词时态、空间关系、主体属性、镜头运动四个正交维度上构建结构化语义图谱,并驱动时空潜在变量的协同演化。 语义解析的层级化建模 系统首先调用轻量级语义角色标注(SRL)模块提取谓词-论元结构,继而通过多头跨模态注意力对齐视觉先验知识库(如 Kinetics-700 动作本体与 COCO-Spatial 关系图谱)。该过程确保“她缓缓旋转并伸展手臂”被分解为: * 主语:“她” → 对应人体姿态关键点拓扑约束 * 动作序列:“旋转”(轴向角速度)、“伸展”(关节角度增量)→ 驱动运动轨迹生成器 * 副词修饰:“缓缓” → 映射至帧间光流平滑度损失权重 视频生成的隐空间对齐策略 Seedance 2.0 引入语义-视觉对比学习(SVCL)损失,强制文本编码器输出与视频潜在码(来自

1000多万次播放背后的AIGC方法论:从爆款视频《牌子》开始思考

这篇深度分析文章,基于《牌子》(SIGN)这部现象级AIGC短片的全面拆解,构建一套完整的AIGC内容创作方法论。将分章节系统性地展开,涵盖技术解析、创作方法论、产业影响和未来展望等多个维度。 引言:一个内容事件的诞生 2026年初,中国视频平台Bilibili上出现了一条名为《牌子》(SIGN)的7分钟短片。这部由独立创作者使用AI工具制作的奇幻短片,在一周内获得了超过1000万次播放、80多万点赞、30多万投币,被著名导演郭帆转发点赞,在YouTube上引发国际观众的热议,甚至专业影视后期团队都在上班时间逐帧分析其制作技术。 这不是一次简单的"技术展示",而是一个内容事件的诞生——它标志着AIGC(人工智能生成内容)从"实验室玩具"正式迈入"大众审美"的领域。更重要的是,它证明了一件事:在正确的创作方法论指导下,单个创作者借助AI工具,可以产出媲美专业团队的内容。 本文将从《牌子》的逐帧技术解析出发,深入探讨其背后的创作逻辑,提炼出一套可复用的AIGC内容创作方法论,

AI写作大师Qwen3-4B参数详解:4B模型核心配置优化

AI写作大师Qwen3-4B参数详解:4B模型核心配置优化 1. 引言 1.1 技术背景与应用趋势 随着大语言模型在内容生成、代码辅助和智能对话等领域的广泛应用,轻量级但高性能的模型正成为开发者和内容创作者的新宠。尤其是在边缘设备或无GPU环境下,如何在资源受限条件下实现高质量的语言生成,已成为AI落地的关键挑战。 在此背景下,阿里云推出的 Qwen3-4B-Instruct 模型凭借其40亿参数规模,在推理能力、知识广度与生成质量之间实现了良好平衡。相比更小的0.5B模型,它不仅具备更强的逻辑理解与长文本生成能力,还能胜任复杂任务如Python游戏开发、技术文档撰写和多轮对话管理。 1.2 项目定位与核心价值 本文聚焦于基于 Qwen/Qwen3-4B-Instruct 构建的“AI写作大师”镜像系统,深入解析其核心参数配置、内存优化策略与WebUI集成机制。该系统专为CPU环境优化设计,通过精细化资源配置,使4B级别模型可在普通服务器甚至个人电脑上稳定运行,极大降低了高性能AI写作工具的使用门槛。 本技术方案的核心优势在于: - 使用官方正版模型保障生成质量 - 集

WhisperLiveKit:本地部署实时语音转文字+说话人识别,这个开源神器让会议纪要秒生成!

WhisperLiveKit:本地部署实时语音转文字+说话人识别,这个开源神器让会议纪要秒生成!

还在为会议纪要熬夜爆肝?线上讨论时总错过关键信息?别急,今天给大家挖到一个开源宝藏——WhisperLiveKit,只需简单几步,就能在自己电脑上搭建一套实时语音转文字系统,连谁在说话都能自动标清楚! 项目地址:github.com/QuentinFuxa/WhisperLiveKit 🚀 这才是语音转文字的终极形态? 用过语音转文字工具的人都懂:要么延迟高到跟不上对话,要么多人发言时文字一锅粥,要么就得把音频上传到云端担惊受怕。 但WhisperLiveKit直接把这些痛点按在地上摩擦—— ✅ 实时性拉满:靠2025年最新的SimulStreaming技术,转录延迟低至1秒级,说话人刚讲完,文字就同步显示,比人工速记还快。 ✅ 多人识别精准:搭载双引擎——2025年SOTA的Streaming Sortformer和经典的Diart,哪怕三五个人交替抢话,也能清晰标注“Speaker 1”“Speaker 2”,再也不用对着文字猜是谁说的。 ✅ 完全本地运行:所有语音处理都在你的电脑上完成,不上传云端,会议机密、私人对话绝对安全。 ✅ 抗噪能力MAX:内置Sil