跳转至

8.3   多元线性回归

本节学习目标

  • 把简单线性回归推广到 多个自变量
  • 掌握 矩阵形式 与正规方程
  • 理解 偏回归系数 含义
  • 警惕 多重共线性 (Multicollinearity)

8.3.1   房价 700 万差价里谁买的单

均哥, 800 万和 1500 万差 700 万, 到底是哪个变量在背锅?
经纪人能编十条故事, 我们只要一个方程, 让数字自己说话。

链家挂出来的房价像谜题:同一个城市,两套房一个 800 万一个 1500 万,差价 700 万到底是 面积 ** 、 学区 ** 、** 楼龄** 哪个买的单?经纪人嘴里能说出十条理由,老板想要的却是一个简单方程:

\[ \widehat{\text{价格}} = \beta_0 + \beta_1 \cdot \text{面积} + \beta_2 \cdot \text{学区} + \beta_3 \cdot \text{楼龄} \]

每个 \(\beta_j\) 应该回答一个具体问题:『 控制其他条件不变 ,每多 1 平米涨多少?是不是学区房真的多卖 8 千/平?楼龄一年掉多少?』上节的简单回归只能放一个 \(X\),搞不定这个买卖。 本节把 OLS 推广到多个变量,并直面三个新麻烦:偏系数怎么解释、整体显著怎么测、变量打架(多重共线)怎么办。


8.3.2   从拟合面到偏回归系数

一根直线变一张面, 一张面变超平面——加变量, 维度涨, 干的活没变。

一个 \(X\) 拟合一条直线,两个 \(X\) 拟合一张 平面 ** :每个数据点在 3D 空间里找到自己的高度(房价),最小二乘还在干同一件事——让所有点到这张平面的竖直距离平方和最小。 推广到 \(p\)\(X\),平面变成 \(p\) 维的 ** 超平面 ,只是没法画了,但代数干活完全一样。

图 8.3.1 多元回归拟合超平面

图 8.3.1   两个自变量时, 拟合面变成二维平面 (超平面)。

关键的直觉转变是『 偏系数 』:\(\beta_1\) 不是『面积单独看对房价的影响』,而是『 ** 学区与楼龄都不变** 时,面积每涨 1 平米的房价变化』。 这就是 partial 在做的事——它把其他变量先扣掉,只留下面积 独自 解释的那一部分变异。

下面的动画把这个『控制其他变量』变成可以看见的动作:拖动『固定 \(X_2\)』滑块,偏回归线整体平移但斜率不变——斜率才是 \(\beta_1\)

动画末尾的提示已经预告了第二个直觉:当 \(X\) 之间互相高度相关(『大房子卧室多』),同一栋房子的『面积涨价』和『卧室涨价』就互相抢功劳——这种情况叫 多重共线性 ,下面会详谈。

面积和卧室抢功劳? 听着像两个销售争提成。
就是这个意思。 抢得越凶, 系数越乱, 一会儿讲怎么治。

8.3.3   设计矩阵与正规方程

该用符号说话了。 把变量打包成矩阵, 一行公式打包十个 β。

把所有自变量打包成 设计矩阵 \(\mathbf{X} \in \mathbb{R}^{n \times (p+1)}\)(第一列全 1,对应截距),目标变量是 \(\mathbf{y} \in \mathbb{R}^n\),模型写作:

\[ \mathbf{y} = \mathbf{X} \boldsymbol{\beta} + \boldsymbol{\varepsilon} \]

OLS 还是最小化残差平方和 \(\|\mathbf{y} - \mathbf{X}\boldsymbol{\beta}\|^2\),对 \(\boldsymbol{\beta}\) 求导置 0 解出 正规方程

\[ \hat{\boldsymbol{\beta}} = (\mathbf{X}^\top \mathbf{X})^{-1} \mathbf{X}^\top \mathbf{y} \]

要求 \(\mathbf{X}^\top \mathbf{X}\) 可逆 → 各列线性无关(无完全多重共线)。 一旦解出,每个 \(\hat{\beta}_j\) 都是『偏回归系数』:在所有其他 \(X\) 保持不变时,\(X_j\) 增 1 单位对 \(Y\) 的期望变化。


8.3.4   拟合优度:\(R^2\) 与调整 \(R^2\)

加变量 $R^2$ 只会涨? 那我塞 100 个噪声不就赢麻了?
所以要看 adj-$R^2$。 塞噪声它会扣你分。

加变量时 \(R^2\) 永远不降(哪怕加进来的是噪声),所以单看 \(R^2\) 会被骗。 用自由度做修正:

\[ R^2_{\text{adj}} = 1 - (1 - R^2) \cdot \dfrac{n - 1}{n - p - 1} \]

加无关变量时 \(R^2_{\text{adj}}\) 会下降,模型对比要看 adj-\(R^2\)、AIC、BIC 才公平。


8.3.5   F 检验与 t 检验

整体 F 检验 :测试『所有 \(X\) 都没用』这个零假设:

\[ H_0: \beta_1 = \beta_2 = \dots = \beta_p = 0,\quad F = \dfrac{\text{SSR}/p}{\text{SSE}/(n-p-1)} \sim F_{p, n-p-1} \]
F 和 t 一起上, 是不是重复检查同一件事?

显著 → 至少有一个 \(X\) 有效(但不知道是哪个)。

单系数 t 检验 :每个 \(\hat{\beta}_j\)\(t = \hat{\beta}_j / \text{SE}(\hat{\beta}_j)\) 服从 \(t_{n-p-1}\),逐个判断显著性。 注意常出现『F 显著但每个 t 都不显著』的怪局——通常正是多重共线性在作祟。


8.3.6   多重共线性:诊断与修正

\(X\) 之间高度相关 → \((\mathbf{X}^\top \mathbf{X})^{-1}\) 接近奇异,系数估计的 方差暴增 ,某个 \(\beta\) 可能从大正数翻到大负数,t 全部不显著。

诊断工具 —— 方差膨胀因子 VIF

\[ \text{VIF}_j = \dfrac{1}{1 - R_j^2} \]

其中 \(R_j^2\) 是把 \(X_j\) 用其他 \(X\) 回归得到的 \(R^2\)。 经验阈值:VIF \(> 10\) 报警,\(> 5\) 就该关注。 也可以直接看相关矩阵,\(|r| > 0.8\) 是危险信号。

修正方案:删冗余变量、做主成分(PCA)、用岭回归(§8.7)。

铁律: VIF $> 10$ 报警。 别强行解释每个 β, 先治病。

陷阱:F 显著 + 每个 t 都不显著

这是多重共线性的招牌信号——『一群人合起来重要,但你说不清谁更重要』。 别强行解释单个系数,先查 VIF。


8.3.7   范畴变量编码与交互项

范畴变量 不能直接进矩阵,需要编码:

  • One-hot 编码\(k\) 个类别 → \(k-1\) 个 0/1 哑变量(多出来的全 1 会与截距共线,所以扔掉一个做基准)
  • 效应编码\(-1/0/+1\)(适合 ANOVA 风格分析)
  • 目标编码 :用类别均值代替(小心训练集泄漏)

例:颜色 \(\in \{\)红, 绿, 蓝\(\}\) → 设 \(D_1 = \text{红?}, D_2 = \text{绿?}\),蓝色作基准(\(D_1 = D_2 = 0\))。

交互项 处理『A 的效应取决于 B』:

\[ Y = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \beta_3 X_1 X_2 + \varepsilon \]

\(\beta_3 \neq 0\) 说明 \(X_1\) 的边际效应不是常数,会随 \(X_2\) 变。 例:教育对收入的拉抬幅度,在大城市远大于小城镇——这就需要 教育 \(\times\) 城市规模 的交互。

所以交互项就是『效应看场合』, 不是一个数走天下。

8.3.8   房价模型解读

回到引言里的房价模型,假设跑出 200 套房的 OLS 结果:

\[ \widehat{\text{价格}} = 5 + 0.3 \cdot \text{面积} + 8 \cdot \text{学区} - 1.5 \cdot \text{楼龄}\quad (R^2 = 0.82) \]

每个系数对应一句人话:

  • 控制其他变量, 面积每增 1 平米 → 价格增 300 元
  • 学区房比非学区贵 8 千/平
  • 每老 1 年 → 跌 1500 元/平
  • 三个变量解释了 82% 的房价变异,剩下 18% 留给装修、楼层、朝向、户型……
三个数字, 三句人话——这才叫『模型可解读』。

应用场景

工资模型(学历 + 经验 + 行业)、医疗成本预测(年龄 + 慢病 + 城市)、广告归因(多渠道投入 → 销量)、房地产估值、保险精算——只要决策者想知道『其他条件相同时, 这一项独自值多少钱』,多元回归就是第一站。


8.3.9   statsmodels 跑 OLS 并算 VIF

Python 跑一行能出 F、t、$R^2$ 全套?
import numpy as np, pandas as pd, statsmodels.api as sm

rng = np.random.default_rng(0)
n = 200
area = rng.uniform(50, 200, n)
school = rng.binomial(1, 0.3, n)
age = rng.uniform(0, 30, n)
price = 5 + 0.3*area + 8*school - 0.15*age + rng.normal(0, 5, n)

df = pd.DataFrame({'area': area, 'school': school, 'age': age, 'price': price})
X = sm.add_constant(df[['area', 'school', 'age']])
model = sm.OLS(df['price'], X).fit()
print(model.summary())

# VIF
from statsmodels.stats.outliers_influence import variance_inflation_factor
for i, name in enumerate(X.columns):
 print(f"VIF[{name}] = {variance_inflation_factor(X.values, i):.2f}")

summary() 给出每个 \(\hat{\beta}\) 的估计、SE、t、p,外加整体 F、\(R^2\)、adj-\(R^2\);下面的 VIF 循环能立刻把多重共线性可视化。

你知道吗

『偏回归系数』和『简单回归系数』可以差到符号都翻——这叫 辛普森悖论 (Simpson's paradox) 。 历史上最有名的例子是 1973 年加州大学伯克利分校的研究生录取率:单看『总录取率』男生比女生高,看似性别歧视;按 专业 分组后却发现 女生在大多数专业反而更容易被录取 ,只是她们更倾向申请录取率本身就低的专业。 这是『漏掉重要协变量』在多元回归里付出的代价。


8.3.10   本节小结

  • 多元 OLS 用矩阵闭式 \(\hat{\beta} = (X^\top X)^{-1} X^\top y\),每个 \(\hat{\beta}_j\) 是『控制其他变量』的偏效应。
  • 模型对比看 adj-\(R^2\),整体看 F,单变量看 t;F 显著而 t 集体不显著是共线性的招牌。
  • 多重共线性用 VIF 诊断,必要时删变量、做 PCA 或转 Ridge(§8.7)。
  • 范畴变量哑编码、交互项让模型能容纳更复杂关系,但解读会随之变难。
  • 下节 §8.4 学习 回归诊断 ,把 BLUE 假设逐条体检。