本节摘要:评估时序模型需要把"预测误差"量化成可比较的数字。本节系统介绍 MAE、RMSE、MAPE、SMAPE、MASE、R² 六类指标,并讨论各自的适用场景、单位敏感性、对异常值的反应。
阅读完本节,你应当能够:
没有任何一个指标能完整描述"预测得好不好"。比如:
A 和 C 的 MAE 差 1,但 A 在业务上可能更危险(RMSE 高说明存在"少数极端预测错误")。单一指标会掩盖模型的真实特征。
MAE = (1/n) Σ |y(t) - ŷ(t)|
RMSE = √((1/n) Σ (y(t) - ŷ(t))²)
MAPE = (100%/n) Σ |y(t) - ŷ(t)| / |y(t)|
SMAPE = (100%/n) Σ 2|y(t) - ŷ(t)| / (|y(t)| + |ŷ(t)|)
MASE = MAE_model / MAE_naive
其中 MAE_naive = (1/n) Σ |y(t) - y(t-1)|(朴素季节性预测的 MAE)。
import numpy as np from sklearn.metrics import mean_absolute_error, mean_squared_error y_true = np.array([100, 110, 105, 120, 115]) y_pred = np.array([98, 112, 103, 118, 117]) mae = mean_absolute_error(y_true, y_pred) rmse = np.sqrt(mean_squared_error(y_true, y_pred)) mape = np.mean(np.abs((y_true - y_pred) / y_true)) * 100 smape = np.mean(2 * np.abs(y_true - y_pred) / (np.abs(y_true) + np.abs(y_pred))) * 100 # 朴素基线 naive_mae = np.mean(np.abs(np.diff(y_true))) mase = mae / naive_mae print(f"MAE = {mae:.2f}") print(f"RMSE = {rmse:.2f}") print(f"MAPE = {mape:.2f}%") print(f"SMAPE = {smape:.2f}%") print(f"MASE = {mase:.3f}")
| 业务场景 | 推荐指标 |
|---|---|
| 给非技术 stakeholder 汇报 | MAE(单位直观) |
| 异常值很关键(风控、运维) | RMSE(敏感于大误差) |
| 跨业务线对比 | MASE(相对朴素基线) |
| 销量有 0 或接近 0 | SMAPE(不用 MAPE) |
| 量级差异大的多模型 | MAPE 或 MASE |
| 学术 / 比赛 | MAPE + RMSE 双指标 |
除了误差大小,业务上还关心方向:
# 系统性高估 / 低估 errors = y_true - y_pred mean_error = np.mean(errors) # MBE (Mean Bias Error) print(f"系统偏差 = {mean_error:.2f}") # 正 = 预测偏低
如果 MBE 显著不为 0 → 模型系统性高估或低估。MAE / RMSE 只看绝对值,不看方向。
| 指标 | 公式 | 单位 | 适合场景 | 坑 |
|---|---|---|---|---|
| MAE | mean(abs(y - ŷ)) | 同原数据 | 通用 | 对极端值不敏感 |
| MSE | mean((y - ŷ)²) | 同原数据² | 训练时 | 单位不可解释 |
| RMSE | sqrt(MSE) | 同原数据 | 报告 | 对极端值敏感 |
| MAPE | mean(abs((y - ŷ)/y)) | % | 跨量级比较 | y=0 时爆炸 |
| R² | 1 - SSE/SST | 无量纲 | 解释力 | 趋势数据会虚高 |
反直觉:R² = 0.95 听起来很好,但若数据是单调上升,预测"等于上一个值"的 R² 也是 0.95。R² 必须配合残差图看,不能单独信。