🧠 第四章 机器学习算法
📄 一句话概括

365 天 PM2.5 序列:持续法 MAE 10.09、七日移动平均 9.62、AR(1) 9.51。 但三次重污染过程里,AR(1) 的误差 27/26/48,全都比持续法的 17/8/38 大。

📝 本节和前面几节的关系

上一节做视觉,这一节处理时间序列。它的特点和前面都不同:样本之间不独立,今天和昨天强相关。

一、时间序列的规矩:只能往前看

图像和文本的样本是独立的,打乱顺序不影响。时间序列不行——用第 300 天的数据预测第 200 天,那是作弊。 所以所有验证都必须按时间切:用前面的数据训练,用后面的数据测试。 随机切分是时间序列里最常见的错误,它会让结果好得离谱。 Demo 里三个方法都只用「当前时刻之前」的数据,没有一处用到未来。 这一条不是洁癖,是生死线。做出来的模型要上线,上线那天你拿不到明天数据。

二、三个朴素基线

别小看基线。任何复杂模型都要先跟这三条线比: - 持续法:明天等于今天。MAE 10.09、RMSE 13.17。 - 七日移动平均:取前七天的均值。MAE 9.62、RMSE 14.96。 - AR(1):用最小二乘拟合「今天 = a×昨天 + b」。MAE 9.51、RMSE 12.43。 AR(1) 学到的系数是 a = 0.7836、b = 9.5024。 a 小于 1,说明序列有回归均值的倾向——今天是高值,明天大概率往中间掉一点。 三个数的差距很小:MAE 从 10.09 到 9.51,只好了 6%。 这说明这份数据的「可预测性」本来就不高,换个花哨模型也难大幅改善。

三、关键的那几天,最好的模型最差

Demo 单独看了三次重污染过程的第三天: - 第 63 天,真实 109:持续法错 17,AR(1) 错 27。 - 第 153 天,真实 133:持续法错 8,AR(1) 错 26。 - 第 263 天,真实 126:持续法错 38,AR(1) 错 48。 三次都是 AR(1) 更差。为什么?因为它学到的是「平常日子怎么变」——a = 0.78 意味着向均值回归。 而重污染那几天恰恰是不回归的,一路往上冲。 持续法反而占便宜:它直接复制昨天的值,昨天已经很高,今天更高,误差就小。 这就是极端事件预测的悖论:平均指标最好的模型,恰恰在关键时刻最不可靠。 空气质量预警要的偏偏是那几天。

四、指标选错,结论就反

再仔细看三个基线:七日移动平均的 MAE(9.62)比持续法(10.09)小, 但 RMSE(14.96)比持续法(13.17)大。 也就是说,按 MAE 它更好,按 RMSE 它更差。两句话都对,看你用哪个指标。 MAE 对每个误差一视同仁;RMSE 会放大大的误差。 所以:关心「平时误差多大」用 MAE,关心「会不会爆一个大错」用 RMSE。 空气质量预警关心的是后者——宁可平均差一点,也不能漏掉重污染。 所以这个场景应该盯 RMSE,甚至盯「重污染日召回率」。 指标选错,整份评估就白做。这在模型评估那一章还会再展开一次。

五、动手 Demo:PM2.5 预测:三种朴素办法

造一条 365 天的 PM2.5 序列(季节正弦 + 缓慢趋势 + 噪声 + 三次重污染冲击); 分别用持续法、七日移动平均、AR(1) 最小二乘做一步预测;比较 MAE 与 RMSE; 再单独看三次重污染第三天的误差。

base = 45 + 18 * np.sin(2 * np.pi * (t - 100) / 365)
pm = base - 0.02 * t + rg.normal(0, 8, days)
for c in (60, 150, 260):
    pm[c:c + 6] += np.array([30, 60, 85, 70, 40, 20])

p1 = pm[:-1]                                   # 持续法
p2 = np.array([pm[i - 7:i].mean() for i in range(7, days)])

A = np.column_stack([pm[:-1], np.ones(days - 1)])
coef, *_ = np.linalg.lstsq(A, pm[1:], rcond=None)
p3 = A @ coef                                  # AR(1)

实跑输出:

--------------------------------------------------------------------
PM2.5 预测:三种朴素办法,谁的错误更小
--------------------------------------------------------------------
  方法                     MAE    RMSE
  -----------------------------------
  持续法(昨天=今天)   10.09   13.17
  七日移动平均            9.62   14.96
  AR(1) 最小二乘          9.51   12.43

  AR(1) 学到的系数         a = 0.7836,b = 9.5024
  均值                     43.76 微克/立方米
  标准差                   20.10
  最高一天                 132.8(第 153 天)

  重污染那几天,三种方法各错多少(单位同上):
  第几天   真实值   持续法误差   AR(1) 误差
  ----------------------------------------
      63      109           17           27
     153      133            8           26
     263      126           38           48

  AR(1) 的 RMSE 比持续法小,但重污染那几天的误差反而更大——
  因为它学的是「平常日子怎么变」,学不到「突然冲高」。
  这就是极端事件预测的难点:平均值好看,关键的那几天不行。

  数据是我按「季节 + 趋势 + 噪声 + 三次冲击」造出来的,
  不是真实监测站数据。真实 PM2.5 还有风向、湿度、周边排放的影响。

三条基线的 MAE:10.09 / 9.62 / 9.51。差距只有 6%,说明这份数据的可预测性本来就有限。 但 RMSE 的排序换了:13.17 / 14.96 / 12.43。 七日移动平均在 MAE 上赢,在 RMSE 上输——两个指标给出相反的结论。 AR(1) 系数 a = 0.7836、b = 9.5024。 a 小于 1 表示「向均值回归」,这正好解释了它在重污染日的失败。 重污染三行:AR(1) 的误差 27 / 26 / 48,持续法 17 / 8 / 38,三次都更差。 第 153 天差得最多:8 对 26。

30 秒实验

  1. 把三次冲击去掉重跑,看 AR(1) 和持续法谁更好。
  2. 加一个「前三日均值」的基线,看它在这三次冲击上的表现。
  3. 想一想:为什么时间序列不能随机划分训练集和测试集?

常见误区

  1. 「随机切分就行」——会用到未来数据,结果虚高。
  2. 「MAE 小就是好」——本例七日移动平均 MAE 最小、RMSE 最大。
  3. 「平均指标好就能上线」——重污染那几天它最差,而那几天才是重点。
自测三问(点开对答案) 1. 为什么时间序列必须按时间切分? —— 随机切分会让模型用到未来数据,等于作弊。 2. AR(1) 的系数 0.78 意味着什么? —— 今天有向均值回归的倾向,不适合预测持续冲高的过程。 3. MAE 和 RMSE 的区别在哪儿? —— RMSE 会放大大的误差,关心「会不会爆大错」时看它。

第四章的应用场景到此结束,下一章进深度学习——从「为什么要更深的网络」开始。

相关笔记