跳转至

8.4   回归诊断

本节学习目标

  • 残差图 检验线性、同方差、独立、正态
  • 识别 离群值、高杠杆点、强影响点
  • 掌握 修正方法 : 变换、加权、稳健回归

8.4.1   \(R^2 = 0.78\) 也救不了的客单价模型

某电商团队上线了一版 预测客单价 ** 的 OLS 模型,\(R^2 = 0.78\),老板满意,PPT 上线。 三个月后报表对不上:高消费用户的预测严重 ** 系统性偏低 ,而几个超级 VIP 的成交把整个模型的斜率整体抬偏了,普通用户预测又系统性偏高。 数据科学家回头看才发现:

  • 残差画出来呈 喇叭形 :客单越大,预测误差越大(异方差)
  • 残差对拟合值还有 轻微 U 形 :模型漏了一项非线性
  • 几个 VIP 是 强影响点 :删掉他们重跑,斜率从 0.42 掉到 0.31

\(R^2 = 0.78\) 这个漂亮数字什么也没保护——OLS 的 BLUE 假设悄悄被违反了。 本节的故事就是: 线拟好之后,必须做体检 。 不做诊断的回归就像不复盘的交易:盈亏全是运气。

R²=0.78 还能翻车? 我以为稳了。
R² 漂亮, 假设照样能塌。 不做诊断 = 闭眼上线

8.4.2   残差图与 Q-Q 图上的『指纹』

回到 §8.2 列的五条假设:线性、独立、同方差、正态、无强影响点。 怎么知道哪条破了?最有力的工具不是哪个 p 值,而是 两张图

  • 残差 vs 拟合值 :横轴是模型预测 \(\hat{y}\),纵轴是残差 \(e\)。 理想情况下应该是一片『随机散布在 0 周围、宽窄一致』的云。
  • Q-Q 图 :把残差按大小排序,与正态分布的理论分位数对比。 理想是一条直线。

每种『违反』在这两张图上都有自己的指纹:

  • U 形 / 倒 U 形 → 漏了非线性项
  • 喇叭形(左窄右宽) → 异方差
  • 明显的趋势或周期 → 自相关 / 漏变量
  • Q-Q 两端翘 → 重尾、有离群

下面的动画把这几种『指纹』并排放出来,让你一眼就能学会读图。

图 8.4.1 诊断双图

图 8.4.1   左: 残差 vs 拟合值 (出现喇叭形 = 异方差); 右: Q-Q 图 (点偏离直线 = 非正态)。
原来残差图里全是指纹? 我之前只盯 R²。
残差是模型的体检报告——别只看体重。

8.4.3   检查清单

把直觉落到一张表格——五条假设、对应的诊断手段、常见的修复方案:

假设 诊断 修正
线性 残差 vs 拟合值 加多项式、log 变换
独立 Durbin-Watson、ACF 时间序列模型 (ARIMA)
同方差 残差 vs \(\hat{y}\) 散点;Breusch-Pagan log Y、WLS、Huber-White 稳健 SE
正态 Q-Q 图、Shapiro 大样本 CLT 救场,或 bootstrap
无强影响点 Cook's \(D\)、leverage 稳健回归;删点要慎重

下面把表里的关键统计量逐个解释。

五条假设、三张图——一次能记住吗?
记不住没事, 这张表贴墙上, 上线前对一遍就行。

8.4.4   杠杆、学生化残差、Cook 距离

杠杆 (leverage) \(h_{ii}\) :第 \(i\) 个观测对自身预测 \(\hat{y}_i\) 的拉力。 \(X\) 离均值越远,\(h_{ii}\) 越大。 经验阈值:\(h_{ii} > 2(p+1)/n\) 视为高杠杆。

学生化残差 :把残差按局部尺度标准化,

\[ t_i = \dfrac{e_i}{s \sqrt{1 - h_{ii}}} \]

\(|t_i| > 3\) 视为离群。

Cook 距离 :把『杠杆 + 残差大小』合成一个『删点影响力』指标——

\[ D_i = \dfrac{e_i^2}{(p+1)\,s^2} \cdot \dfrac{h_{ii}}{(1 - h_{ii})^2} \]

\(D_i > 4/n\) 是经验报警线。 强影响点 = 高杠杆 + 大残差 ;只高杠杆但残差不大,并不一定致命。

那只杠杆高、残差不大的点, 是良民?
算良民。 它在 X 边缘, 但模型对它预测得准

8.4.5   异方差与自相关

Breusch-Pagan 检验 :把残差平方对 \(X\) 回归,看是否显著:

\[ \text{LM} = n \cdot R_{e^2}^2 \sim \chi^2_p \]

显著 → 拒绝同方差。 White 检验 是它的更通用版(含交叉项),不依赖具体分布。

Durbin-Watson 统计量 (检验一阶自相关):

\[ \text{DW} = \dfrac{\sum_{i=2}^n (e_i - e_{i-1})^2}{\sum e_i^2} \]

DW \(\approx 2\) → 无自相关;DW \(< 1.5\)\(> 2.5\) 警惕。 时间序列残差自相关 → 改用 ARMA / GLS。

正态性 ** 用 Shapiro-Wilk 与 Q-Q 图配合。 注意: 大样本下 Shapiro 极易拒** (任何小偏离都显著),但 OLS 推断对正态偏离 本来就稳健 ,不必苛求。

Shapiro 一拒, 是不是模型作废?
大样本下小偏离都拒, 别瞎慌。 OLS 推断本来就抗正态

8.4.6   异常值的三步走

发现某点 Cook \(D = 0.5\)\(|t_i| = 5\),怎么办?冲动是『删了重跑』,但这是数据造假的开场。 正确流程:

  1. 确认是不是录入错误 :打错小数点、单位混淆——这种优先剔。
  2. 评估影响 :删除前后对比 \(\hat{\beta}\)\(R^2\),量化它对模型的贡献。
  3. 决策
  4. 真实但极端 → 用 稳健回归 (Huber、RANSAC、分位数回归),保留点但降权
  5. 报告时 透明声明 处理过程
Cook D=0.5 的点, 我直接删了行不行?
先问: 录入错? 还是真极端? 盲删 = 数据造假

陷阱:看不顺眼就删

挑掉所有让 \(R^2\) 不好看的点,等于给数据剃掉胡子。 模型在论文上漂亮,落地就翻车。 任何点的删除都必须有 业务上 的理由,而不是 统计上的方便


8.4.7   诊断到修正的工作动线

这一节工具多,给一条工作动线:

  1. 看图先于看数 :残差 vs \(\hat{y}\)、Q-Q、Cook D 三张图过一遍
  2. 哪条假设破了 → 选对应修正
  3. 非线性 → 加多项式(§8.6)/ 样条 / GAM
  4. 异方差 → log 变换、WLS、HC3 稳健 SE
  5. 自相关 → ARIMA / GLS(→ 第 12 章)
  6. 强影响点 → 稳健回归、Huber、RANSAC
  7. 修正后重诊断 ——一次没解决就再来一轮
口诀: 看图—修正—重诊断。 一轮不解决就再来一轮。

应用场景

所有上线前的回归模型都该走一遍诊断:信用打分、价格弹性、医疗剂量响应、房价估值、用户 LTV 预测——任何决策依赖『系数解读』或『预测区间』的场合,没做诊断的模型都是黑盒赌博。


8.4.8   BP 检验、DW 与 Cook 距离实测

import numpy as np, statsmodels.api as sm
import matplotlib.pyplot as plt
from statsmodels.stats.diagnostic import het_breuschpagan
from statsmodels.stats.stattools import durbin_watson
from scipy import stats

rng = np.random.default_rng(0)
n = 80
x = rng.uniform(0, 10, n)
y = 2 + 1.5*x + rng.normal(0, 1.5 + 0.3*x, n) # 异方差

X = sm.add_constant(x)
m = sm.OLS(y, X).fit()
e = m.resid

# 异方差
bp = het_breuschpagan(e, X)
print(f"BP test p = {bp[1]:.4f}") # < 0.05 → 异方差
# DW
print(f"Durbin-Watson = {durbin_watson(e):.2f}")
# 正态
print(f"Shapiro p = {stats.shapiro(e).pvalue:.3f}")
# 影响点
inf = m.get_influence()
cooks = inf.cooks_distance[0]
print(f"max Cook's D = {cooks.max():.3f}")

# 修正: 用稳健 SE 重跑
m_robust = sm.OLS(y, X).fit(cov_type='HC3')
print(m_robust.summary())

最后那行 cov_type='HC3' 是『懒人福音』:系数估计完全不变,但 SE 与 p 值都被换成对异方差稳健的版本,几乎是默认就该开。

一行就能拿稳健 SE? 这么便宜!
所以说默认就该开。 系数不变, p 值更可信。

8.4.9   稳健回归

当『删不删』成了难题,把决策权交给 稳健回归

  • Huber 损失 :小残差用平方(高效),大残差用线性(不被极端点拽歪)
  • RANSAC :随机采样找最大内点集,对高离群率非常友好
  • 分位数回归 :拟合中位数(而不是均值),天然抗异常值
from sklearn.linear_model import HuberRegressor
hr = HuberRegressor().fit(x.reshape(-1,1), y)
print(hr.coef_, hr.intercept_)
稳健回归会不会让 R² 变难看?
可能。 但稳定 > 漂亮, 上线再好看也救不了你。

你知道吗

Cook 距离的提出者 R. Dennis Cook 在 1977 年发表的那篇论文里只有 4 页,定义出奇简洁,却成了现代回归诊断的核心工具之一。 它的精妙在于把『移除一个点对所有预测的总扰动』压成一个标量——你不需要真把每个点删一遍重跑 \(n\) 次模型,公式里 \(h_{ii}\) 已经把这件事代数化了。


8.4.10   本节小结

  • 一定要看 残差图 + Q-Q + Cook D ,而不是只看 \(R^2\)
  • 异方差用 WLS / 稳健 SE(HC3 几乎是默认),自相关用 GLS / ARIMA。
  • 异常值要 诊断而非盲删 :录入错→删;真实但极端→稳健回归。
  • 大样本下正态性偏离不必苛求;模型修正后 必须重诊断
  • 下节 §8.5 把回归扩展到 二分类问题 :逻辑回归。