文章目录
-
- [1. 线性回归的几何直觉与梯度下降](#1. 线性回归的几何直觉与梯度下降)
- [2. 统计视角](#2. 统计视角)
-
- [R²、调整 R² 与 R² 的误区](#R²、调整 R² 与 R² 的误区)
- [F 检验与 t 检验](#F 检验与 t 检验)
- 残差的四大假设
- [3. 残差诊断](#3. 残差诊断)
- [4. 正则化三策略](#4. 正则化三策略)
-
- [L2 正则化(Ridge)](#L2 正则化(Ridge))
- [L1 正则化(Lasso)](#L1 正则化(Lasso))
- ElasticNet
- 正则化强度的选择:交叉验证
- [5. 逻辑回归](#5. 逻辑回归)
-
- [sigmoid 与概率解释](#sigmoid 与概率解释)
- [最大似然估计 vs 最小二乘](#最大似然估计 vs 最小二乘)
- 多分类扩展
- 概率校准:逻辑回归的天然优势
- [6. 特征选择三法论](#6. 特征选择三法论)
- [7. 选型边界](#7. 选型边界)
- [8. 多项式回归与核技巧](#8. 多项式回归与核技巧)
- [9. 实战](#9. 实战)
-
- [步骤1:VIF 多重共线性诊断](#步骤1:VIF 多重共线性诊断)
- 步骤2:残差诊断
- 步骤3:三种正则化对比
- [步骤4:与 XGBoost 的精度-可解释性权衡](#步骤4:与 XGBoost 的精度-可解释性权衡)
- 小结
线性模型是机器学习的"零号算法"------简单到让人觉得"不够高级"。但金融风控的首选模型至今仍是逻辑回归(监管要求可解释),高维稀疏文本分类线性模型依然碾压,线性回归的假设检验更是连接统计学与机器学习的核心桥梁。
真正的问题不是"线性模型够不够好",而是线性假设什么时候成立、什么时候必须放弃。本文从几何直觉出发,经由统计视角,最终落到正则化、特征选择和选型边界的系统方法论。
1. 线性回归的几何直觉与梯度下降
最小二乘的投影本质
线性回归的目标是找一个超平面,使所有样本点到该平面的垂直距离的平方和最小 。换一种说法:目标向量 y y y 在特征矩阵 X X X 的列空间上的投影,就是线性回归的最优解 y ^ \hat{y} y^。
这个几何理解有一个重要推论:当特征之间高度共线(多重共线性), X X X 的列空间几乎是"退化"的,投影方向变得极不稳定------参数估计的方差会爆炸。正则化正是从这个角度来"稳定"解的。
python
import numpy as np
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.datasets import make_regression
X, y, coef = make_regression(n_samples=200, n_features=10, noise=10, coef=True, random_state=42)
# 原始 OLS
ols = LinearRegression().fit(X, y)
print("OLS 系数范围:", ols.coef_.min().round(2), "~", ols.coef_.max().round(2))
# Ridge 正则化
ridge = Ridge(alpha=10).fit(X, y)
print("Ridge 系数范围:", ridge.coef_.min().round(2), "~", ridge.coef_.max().round(2))
梯度下降与最小二乘的等价性
最小二乘有解析解 β ^ = ( X T X ) − 1 X T y \hat{\beta} = (X^TX)^{-1}X^Ty β^=(XTX)−1XTy,梯度下降则是迭代逼近。两者在凸目标函数下收敛到同一点。区别在于:
| 方法 | 适用场景 | 计算复杂度 | 优缺点 |
|---|---|---|---|
| 解析解(Normal Equation) | 小数据( n < 10 5 n < 10^5 n<105) | O ( n ⋅ p 2 + p 3 ) O(n \cdot p^2 + p^3) O(n⋅p2+p3) | 精确但矩阵求逆代价大 |
| 批量梯度下降 | 中等数据 | O ( n ⋅ p ) O(n \cdot p) O(n⋅p)/轮 | 需调学习率,内存友好 |
| 随机梯度下降(SGD) | 大数据( n > 10 6 n > 10^6 n>106) | O ( p ) O(p) O(p)/样本 | 噪声大但可扩展 |
2. 统计视角
线性回归的统计诊断工具对于判断"线性假设是否成立"至关重要。
R²、调整 R² 与 R² 的误区
R 2 = 1 − S S r e s S S t o t R^2 = 1 - \frac{SS_{res}}{SS_{tot}} R2=1−SStotSSres 表示模型解释的方差比例,范围 0 , 1 0, 1 0,1。
常见误区:
- R 2 = 0.95 R^2 = 0.95 R2=0.95 不代表预测误差小------如果 y y y 的方差本身很小,0.95 的 R 2 R^2 R2 对应的绝对误差可能仍然很大
- 增加特征数量一定会提升 R 2 R^2 R2,即使加的是随机噪声。调整 R² ( R ˉ 2 \bar{R}^2 Rˉ2)通过惩罚特征数量来修正这一问题
F 检验与 t 检验
F 检验 检验"模型整体是否有解释力",原假设是所有系数同时为零。若 p < 0.05 p < 0.05 p<0.05,说明模型至少有一个特征是有意义的。
t 检验 检验单个系数 β j \beta_j βj 是否显著,原假设是 β j = 0 \beta_j = 0 βj=0。t 统计量 = β ^ j / S E ( β ^ j ) = \hat{\beta}_j / SE(\hat{\beta}_j) =β^j/SE(β^j),SE 是标准误差。
python
import statsmodels.api as sm
X_const = sm.add_constant(X)
model = sm.OLS(y, X_const).fit()
print(model.summary())
# 重点关注:F-statistic, Prob(F-statistic), 各特征的 P>|t|
残差的四大假设
线性回归的统计推断(t/F 检验、置信区间)依赖于四大假设。不满足时,系数估计可能仍然无偏,但标准误差和检验结果失效:
| 假设 | 含义 | 违反时的症状 |
|---|---|---|
| 线性性 | E y ∣ X = X β Ey|X = X\beta Ey∣X=Xβ | 残差 vs 预测值图中有系统性弯曲 |
| 独立性 | 残差之间不相关 | 时间序列数据中的自相关(Durbin-Watson < 1.5) |
| 同方差性 | V a r ( ε i ) Var(\varepsilon_i) Var(εi) 为常数 | 残差散布随预测值增大而扩大(漏斗形) |
| 正态性 | 残差服从正态分布 | Q-Q 图偏离对角线,大样本下影响较小 |
3. 残差诊断
线性假设不是"信仰"而是"假设"------需要通过诊断来验证。
#mermaid-svg-TGtQKitnhynfXJqq{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-TGtQKitnhynfXJqq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-TGtQKitnhynfXJqq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-TGtQKitnhynfXJqq .error-icon{fill:#552222;}#mermaid-svg-TGtQKitnhynfXJqq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TGtQKitnhynfXJqq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-TGtQKitnhynfXJqq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TGtQKitnhynfXJqq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TGtQKitnhynfXJqq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-TGtQKitnhynfXJqq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TGtQKitnhynfXJqq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TGtQKitnhynfXJqq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TGtQKitnhynfXJqq .marker.cross{stroke:#333333;}#mermaid-svg-TGtQKitnhynfXJqq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TGtQKitnhynfXJqq p{margin:0;}#mermaid-svg-TGtQKitnhynfXJqq .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-TGtQKitnhynfXJqq .cluster-label text{fill:#333;}#mermaid-svg-TGtQKitnhynfXJqq .cluster-label span{color:#333;}#mermaid-svg-TGtQKitnhynfXJqq .cluster-label span p{background-color:transparent;}#mermaid-svg-TGtQKitnhynfXJqq .label text,#mermaid-svg-TGtQKitnhynfXJqq span{fill:#333;color:#333;}#mermaid-svg-TGtQKitnhynfXJqq .node rect,#mermaid-svg-TGtQKitnhynfXJqq .node circle,#mermaid-svg-TGtQKitnhynfXJqq .node ellipse,#mermaid-svg-TGtQKitnhynfXJqq .node polygon,#mermaid-svg-TGtQKitnhynfXJqq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TGtQKitnhynfXJqq .rough-node .label text,#mermaid-svg-TGtQKitnhynfXJqq .node .label text,#mermaid-svg-TGtQKitnhynfXJqq .image-shape .label,#mermaid-svg-TGtQKitnhynfXJqq .icon-shape .label{text-anchor:middle;}#mermaid-svg-TGtQKitnhynfXJqq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-TGtQKitnhynfXJqq .rough-node .label,#mermaid-svg-TGtQKitnhynfXJqq .node .label,#mermaid-svg-TGtQKitnhynfXJqq .image-shape .label,#mermaid-svg-TGtQKitnhynfXJqq .icon-shape .label{text-align:center;}#mermaid-svg-TGtQKitnhynfXJqq .node.clickable{cursor:pointer;}#mermaid-svg-TGtQKitnhynfXJqq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-TGtQKitnhynfXJqq .arrowheadPath{fill:#333333;}#mermaid-svg-TGtQKitnhynfXJqq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-TGtQKitnhynfXJqq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-TGtQKitnhynfXJqq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TGtQKitnhynfXJqq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-TGtQKitnhynfXJqq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TGtQKitnhynfXJqq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-TGtQKitnhynfXJqq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-TGtQKitnhynfXJqq .cluster text{fill:#333;}#mermaid-svg-TGtQKitnhynfXJqq .cluster span{color:#333;}#mermaid-svg-TGtQKitnhynfXJqq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-TGtQKitnhynfXJqq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-TGtQKitnhynfXJqq rect.text{fill:none;stroke-width:0;}#mermaid-svg-TGtQKitnhynfXJqq .icon-shape,#mermaid-svg-TGtQKitnhynfXJqq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TGtQKitnhynfXJqq .icon-shape p,#mermaid-svg-TGtQKitnhynfXJqq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-TGtQKitnhynfXJqq .icon-shape .label rect,#mermaid-svg-TGtQKitnhynfXJqq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TGtQKitnhynfXJqq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-TGtQKitnhynfXJqq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-TGtQKitnhynfXJqq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
是
否
是
否
是
否
拟合线性回归
绘制残差 vs 预测值图
是否有系统性
弯曲或趋势?
线性假设不成立
→ 考虑多项式特征
或树模型
检查同方差性
Breusch-Pagan 检验
漏斗形分布?
异方差
→ WLS 加权最小二乘
或对 y 做 log 变换
检查多重共线性
VIF 诊断
VIF > 10?
共线性严重
→ 去除相关特征
或用 Ridge 正则化
检查残差正态性
Q-Q 图 / Shapiro-Wilk
大幅偏离正态?
小样本谨慎推断
大样本中心极限定理保障
诊断通过
模型可信
多重共线性诊断:VIF
方差膨胀因子(VIF)衡量某个特征能被其他特征解释的程度:
V I F j = 1 1 − R j 2 VIF_j = \frac{1}{1 - R_j^2} VIFj=1−Rj21
其中 R j 2 R_j^2 Rj2 是以 X j X_j Xj 为响应变量、其余特征为预测变量的 R 2 R^2 R2。
python
from statsmodels.stats.outliers_influence import variance_inflation_factor
import pandas as pd
vif_data = pd.DataFrame()
vif_data["feature"] = X.columns
vif_data["VIF"] = [variance_inflation_factor(X.values, i) for i in range(X.shape[1])]
print(vif_data.sort_values("VIF", ascending=False))
# VIF > 10:高度共线,需处理;VIF 5~10:中度,需关注;VIF < 5:可接受
4. 正则化三策略
正则化的本质不是"惩罚"系数------而是在系数估计的无偏性和稳定性之间做取舍(偏差-方差权衡)。在多重共线性存在时,OLS 估计方差极大;正则化引入少量偏差,换来系数稳定性的大幅提升。
#mermaid-svg-5WCh9nCA1hmo8bLp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-5WCh9nCA1hmo8bLp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-5WCh9nCA1hmo8bLp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-5WCh9nCA1hmo8bLp .error-icon{fill:#552222;}#mermaid-svg-5WCh9nCA1hmo8bLp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-5WCh9nCA1hmo8bLp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-5WCh9nCA1hmo8bLp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-5WCh9nCA1hmo8bLp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-5WCh9nCA1hmo8bLp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-5WCh9nCA1hmo8bLp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-5WCh9nCA1hmo8bLp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-5WCh9nCA1hmo8bLp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-5WCh9nCA1hmo8bLp .marker.cross{stroke:#333333;}#mermaid-svg-5WCh9nCA1hmo8bLp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-5WCh9nCA1hmo8bLp p{margin:0;}#mermaid-svg-5WCh9nCA1hmo8bLp .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-5WCh9nCA1hmo8bLp .cluster-label text{fill:#333;}#mermaid-svg-5WCh9nCA1hmo8bLp .cluster-label span{color:#333;}#mermaid-svg-5WCh9nCA1hmo8bLp .cluster-label span p{background-color:transparent;}#mermaid-svg-5WCh9nCA1hmo8bLp .label text,#mermaid-svg-5WCh9nCA1hmo8bLp span{fill:#333;color:#333;}#mermaid-svg-5WCh9nCA1hmo8bLp .node rect,#mermaid-svg-5WCh9nCA1hmo8bLp .node circle,#mermaid-svg-5WCh9nCA1hmo8bLp .node ellipse,#mermaid-svg-5WCh9nCA1hmo8bLp .node polygon,#mermaid-svg-5WCh9nCA1hmo8bLp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-5WCh9nCA1hmo8bLp .rough-node .label text,#mermaid-svg-5WCh9nCA1hmo8bLp .node .label text,#mermaid-svg-5WCh9nCA1hmo8bLp .image-shape .label,#mermaid-svg-5WCh9nCA1hmo8bLp .icon-shape .label{text-anchor:middle;}#mermaid-svg-5WCh9nCA1hmo8bLp .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-5WCh9nCA1hmo8bLp .rough-node .label,#mermaid-svg-5WCh9nCA1hmo8bLp .node .label,#mermaid-svg-5WCh9nCA1hmo8bLp .image-shape .label,#mermaid-svg-5WCh9nCA1hmo8bLp .icon-shape .label{text-align:center;}#mermaid-svg-5WCh9nCA1hmo8bLp .node.clickable{cursor:pointer;}#mermaid-svg-5WCh9nCA1hmo8bLp .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-5WCh9nCA1hmo8bLp .arrowheadPath{fill:#333333;}#mermaid-svg-5WCh9nCA1hmo8bLp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-5WCh9nCA1hmo8bLp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-5WCh9nCA1hmo8bLp .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5WCh9nCA1hmo8bLp .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-5WCh9nCA1hmo8bLp .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5WCh9nCA1hmo8bLp .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-5WCh9nCA1hmo8bLp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-5WCh9nCA1hmo8bLp .cluster text{fill:#333;}#mermaid-svg-5WCh9nCA1hmo8bLp .cluster span{color:#333;}#mermaid-svg-5WCh9nCA1hmo8bLp div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-5WCh9nCA1hmo8bLp .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-5WCh9nCA1hmo8bLp rect.text{fill:none;stroke-width:0;}#mermaid-svg-5WCh9nCA1hmo8bLp .icon-shape,#mermaid-svg-5WCh9nCA1hmo8bLp .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5WCh9nCA1hmo8bLp .icon-shape p,#mermaid-svg-5WCh9nCA1hmo8bLp .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-5WCh9nCA1hmo8bLp .icon-shape .label rect,#mermaid-svg-5WCh9nCA1hmo8bLp .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5WCh9nCA1hmo8bLp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-5WCh9nCA1hmo8bLp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-5WCh9nCA1hmo8bLp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 系数稳定
防过拟合
自动特征选择
稀疏模型
两者兼顾
或特征分组
是
否
是
否
需要正则化?
主要目标是什么?
Ridge L2
alpha控制缩小程度
系数缩小不归零
Lasso L1
alpha控制稀疏度
部分系数精确归零
ElasticNet
l1_ratio控制L1/L2比例
有高度相关特征?
Ridge 分配权重给
所有相关特征
Ridge 均匀缩小
有高度相关特征?
Lasso 随机保留
一个,丢弃其余
Lasso 精确选出
重要特征
L2 正则化(Ridge)
目标函数: min β ∥ y − X β ∥ 2 2 + α ∥ β ∥ 2 2 \min_\beta \|y - X\beta\|_2^2 + \alpha\|\beta\|_2^2 minβ∥y−Xβ∥22+α∥β∥22
L2 正则化的解析解: β ^ R i d g e = ( X T X + α I ) − 1 X T y \hat{\beta}_{Ridge} = (X^TX + \alpha I)^{-1}X^Ty β^Ridge=(XTX+αI)−1XTy。当 X T X X^TX XTX 奇异(共线性)时, α I \alpha I αI 让矩阵可逆------这正是 Ridge 的几何本质:在系数球约束下的最小二乘。
特点:系数缩小趋向于零,但不精确归零;适合特征之间高度相关的场景(Ridge 会分配权重给所有相关特征,而不是随机丢弃)。
L1 正则化(Lasso)
目标函数: min β ∥ y − X β ∥ 2 2 + α ∥ β ∥ 1 \min_\beta \|y - X\beta\|_2^2 + \alpha\|\beta\|_1 minβ∥y−Xβ∥22+α∥β∥1
L1 约束区域是菱形(L1 球),目标函数的等高线与 L1 球相切,切点通常在坐标轴上------这就是为什么 L1 产生稀疏解(部分系数精确为零)。
特点:自动特征选择;当有 p > n p > n p>n(特征数超过样本数)时,Lasso 最多保留 n n n 个特征;高度相关特征中随机丢弃(不稳定)。
ElasticNet
目标函数: min β ∥ y − X β ∥ 2 2 + α 1 ∥ β ∥ 1 + α 2 ∥ β ∥ 2 2 \min_\beta \|y - X\beta\|_2^2 + \alpha_1\|\beta\|_1 + \alpha_2\|\beta\|_2^2 minβ∥y−Xβ∥22+α1∥β∥1+α2∥β∥22
参数 l1_ratio 控制 L1/L2 比例。适合特征有分组结构时(同一组内的特征共同保留或丢弃,而非 Lasso 的随机选择)。
python
from sklearn.linear_model import Ridge, Lasso, ElasticNet
from sklearn.model_selection import cross_val_score
import numpy as np
alphas = [0.01, 0.1, 1, 10, 100]
for alpha in alphas:
ridge_cv = cross_val_score(Ridge(alpha=alpha), X, y, cv=5, scoring='neg_mean_squared_error')
lasso_cv = cross_val_score(Lasso(alpha=alpha), X, y, cv=5, scoring='neg_mean_squared_error')
print(f"alpha={alpha}: Ridge CV={-ridge_cv.mean():.2f}, Lasso CV={-lasso_cv.mean():.2f}")
正则化强度的选择:交叉验证
python
from sklearn.linear_model import RidgeCV, LassoCV
# RidgeCV 自动用交叉验证搜索最优 alpha
ridge_cv = RidgeCV(alphas=[0.1, 1, 10, 100], cv=5).fit(X, y)
print("Ridge 最优 alpha:", ridge_cv.alpha_)
# LassoCV 自动搜索 alpha 路径
lasso_cv = LassoCV(cv=5, random_state=42).fit(X, y)
print("Lasso 最优 alpha:", lasso_cv.alpha_)
print("Lasso 选中特征数:", (lasso_cv.coef_ != 0).sum())
5. 逻辑回归
逻辑回归是线性回归加上 sigmoid 函数的自然延伸------不改变线性决策边界,只是把输出映射到 0 , 1 0, 1 0,1 的概率空间。
sigmoid 与概率解释
P ( y = 1 ∣ x ) = σ ( x T β ) = 1 1 + e − x T β P(y=1|x) = \sigma(x^T\beta) = \frac{1}{1 + e^{-x^T\beta}} P(y=1∣x)=σ(xTβ)=1+e−xTβ1
对数几率(log-odds)是关于 x x x 的线性函数:
log P ( y = 1 ) P ( y = 0 ) = x T β \log\frac{P(y=1)}{P(y=0)} = x^T\beta logP(y=0)P(y=1)=xTβ
这是逻辑回归"线性"的本质:它在对数几率空间是线性的,在概率空间是非线性的。
最大似然估计 vs 最小二乘
逻辑回归用最大似然估计(MLE)求解,而非最小二乘。为什么?线性回归的最小二乘等价于高斯噪声下的 MLE;但二分类问题的噪声服从伯努利分布,此时 MLE 对应二元交叉熵损失:
L ( β ) = − ∑ i y i log p \^ i + ( 1 − y i ) log ( 1 − p \^ i ) L(\beta) = -\sum_i y_i \\log \\hat{p}_i + (1-y_i)\\log(1-\\hat{p}_i) L(β)=−i∑yilogp\^i+(1−yi)log(1−p\^i)
多分类扩展
| 策略 | 方法 | 适用场景 |
|---|---|---|
| OVR(One-vs-Rest) | K 个二分类器,取最高概率 | 类别独立、K 较大 |
| Multinomial | 直接建模 K 类 softmax | 类别间有关联、精度要求高 |
python
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
X_iris, y_iris = load_iris(return_X_y=True)
# multinomial(softmax)多分类
lr = LogisticRegression(multi_class='multinomial', solver='lbfgs', C=1.0, max_iter=200)
lr.fit(X_iris, y_iris)
print("多分类准确率:", lr.score(X_iris, y_iris))
# 查看校准的概率输出
proba = lr.predict_proba(X_iris[:3])
print("概率矩阵(前3行):\n", proba.round(3))
概率校准:逻辑回归的天然优势
相比朴素贝叶斯(输出概率往往过于极端)和随机森林(概率分布呈 S 形偏态),逻辑回归的概率输出天然校准------预测 70% 的样本中,确实约有 70% 是正例。在需要概率而非分类结果的场景(风险评分、广告点击率预估),这一特性至关重要。
6. 特征选择三法论
特征选择不仅仅是"删掉不重要的列"------它是在计算代价、模型交互捕获能力和结果稳定性之间的权衡。
#mermaid-svg-k7ShbS70gAuiTOO5{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-k7ShbS70gAuiTOO5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-k7ShbS70gAuiTOO5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-k7ShbS70gAuiTOO5 .error-icon{fill:#552222;}#mermaid-svg-k7ShbS70gAuiTOO5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-k7ShbS70gAuiTOO5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-k7ShbS70gAuiTOO5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-k7ShbS70gAuiTOO5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-k7ShbS70gAuiTOO5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-k7ShbS70gAuiTOO5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-k7ShbS70gAuiTOO5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-k7ShbS70gAuiTOO5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-k7ShbS70gAuiTOO5 .marker.cross{stroke:#333333;}#mermaid-svg-k7ShbS70gAuiTOO5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-k7ShbS70gAuiTOO5 p{margin:0;}#mermaid-svg-k7ShbS70gAuiTOO5 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-k7ShbS70gAuiTOO5 .cluster-label text{fill:#333;}#mermaid-svg-k7ShbS70gAuiTOO5 .cluster-label span{color:#333;}#mermaid-svg-k7ShbS70gAuiTOO5 .cluster-label span p{background-color:transparent;}#mermaid-svg-k7ShbS70gAuiTOO5 .label text,#mermaid-svg-k7ShbS70gAuiTOO5 span{fill:#333;color:#333;}#mermaid-svg-k7ShbS70gAuiTOO5 .node rect,#mermaid-svg-k7ShbS70gAuiTOO5 .node circle,#mermaid-svg-k7ShbS70gAuiTOO5 .node ellipse,#mermaid-svg-k7ShbS70gAuiTOO5 .node polygon,#mermaid-svg-k7ShbS70gAuiTOO5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-k7ShbS70gAuiTOO5 .rough-node .label text,#mermaid-svg-k7ShbS70gAuiTOO5 .node .label text,#mermaid-svg-k7ShbS70gAuiTOO5 .image-shape .label,#mermaid-svg-k7ShbS70gAuiTOO5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-k7ShbS70gAuiTOO5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-k7ShbS70gAuiTOO5 .rough-node .label,#mermaid-svg-k7ShbS70gAuiTOO5 .node .label,#mermaid-svg-k7ShbS70gAuiTOO5 .image-shape .label,#mermaid-svg-k7ShbS70gAuiTOO5 .icon-shape .label{text-align:center;}#mermaid-svg-k7ShbS70gAuiTOO5 .node.clickable{cursor:pointer;}#mermaid-svg-k7ShbS70gAuiTOO5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-k7ShbS70gAuiTOO5 .arrowheadPath{fill:#333333;}#mermaid-svg-k7ShbS70gAuiTOO5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-k7ShbS70gAuiTOO5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-k7ShbS70gAuiTOO5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-k7ShbS70gAuiTOO5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-k7ShbS70gAuiTOO5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-k7ShbS70gAuiTOO5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-k7ShbS70gAuiTOO5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-k7ShbS70gAuiTOO5 .cluster text{fill:#333;}#mermaid-svg-k7ShbS70gAuiTOO5 .cluster span{color:#333;}#mermaid-svg-k7ShbS70gAuiTOO5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-k7ShbS70gAuiTOO5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-k7ShbS70gAuiTOO5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-k7ShbS70gAuiTOO5 .icon-shape,#mermaid-svg-k7ShbS70gAuiTOO5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-k7ShbS70gAuiTOO5 .icon-shape p,#mermaid-svg-k7ShbS70gAuiTOO5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-k7ShbS70gAuiTOO5 .icon-shape .label rect,#mermaid-svg-k7ShbS70gAuiTOO5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-k7ShbS70gAuiTOO5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-k7ShbS70gAuiTOO5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-k7ShbS70gAuiTOO5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 快速筛选
无需训练模型
模型性能最优
考虑特征交互
训练时自动选择
嵌入到模型
特征选择需求
优先考虑什么?
过滤法
Filter Methods
包裹法
Wrapper Methods
嵌入法
Embedded Methods
相关系数
Pearson/Spearman
互信息
Mutual Information
卡方检验
分类特征
方差阈值过滤
递归特征消除
RFE
顺序特征选择
SFS
遗传算法
特征子集搜索
Lasso L1 稀疏化
树模型特征重要性
弹性网络
ElasticNet
过滤法:快速但忽略特征交互
python
from sklearn.feature_selection import SelectKBest, mutual_info_regression, f_regression
import pandas as pd
# 互信息:捕获非线性依赖
mi_selector = SelectKBest(mutual_info_regression, k=5)
X_mi = mi_selector.fit_transform(X, y)
mi_scores = mi_selector.scores_
print("互信息得分 Top5:", sorted(enumerate(mi_scores), key=lambda x: -x[1])[:5])
# 皮尔逊相关系数(线性关系)
f_selector = SelectKBest(f_regression, k=5)
X_f = f_selector.fit_transform(X, y)
过滤法的局限:独立地评估每个特征,无法捕获特征之间的联合效应(A 和 B 单独看都不重要,但组合起来很强大的情况会被遗漏)。
包裹法:最优但计算昂贵
递归特征消除(RFE):反复训练模型,每次去掉最不重要的特征。
python
from sklearn.feature_selection import RFE, RFECV
from sklearn.linear_model import LinearRegression
# 固定选 5 个特征
rfe = RFE(estimator=LinearRegression(), n_features_to_select=5)
rfe.fit(X, y)
print("RFE 选中特征:", rfe.support_)
print("特征排名:", rfe.ranking_)
# 交叉验证自动确定最优特征数
rfecv = RFECV(estimator=LinearRegression(), step=1, cv=5, scoring='r2')
rfecv.fit(X, y)
print("CV 最优特征数:", rfecv.n_features_)
嵌入法:平衡效率与特征交互
Lasso 稀疏化是嵌入法的典型代表------在模型训练的同时完成特征选择,计算代价接近一次模型训练。
python
from sklearn.linear_model import LassoCV
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
lasso = LassoCV(cv=5, random_state=42, max_iter=10000).fit(X_scaled, y)
selected = np.where(lasso.coef_ != 0)[0]
print(f"Lasso 选中 {len(selected)} 个特征: {selected}")
print("被置零的特征:", np.where(lasso.coef_ == 0)[0])
三法对比速查表
| 方法类别 | 代表算法 | 计算代价 | 捕获特征交互 | 结果稳定性 | 适用场景 |
|---|---|---|---|---|---|
| 过滤法 | 互信息、相关系数 | O ( n ⋅ p ) O(n \cdot p) O(n⋅p) 低 | ❌ | 高 | 快速初筛, p > 1000 p > 1000 p>1000 |
| 包裹法 | RFE、RFECV | O ( n ⋅ p 2 ) O(n \cdot p^2) O(n⋅p2) 高 | ✅ | 中(依赖模型) | 追求最优子集, p < 100 p < 100 p<100 |
| 嵌入法 | Lasso、树重要性 | O ( n ⋅ p ) O(n \cdot p) O(n⋅p) 中 | 部分 | 高(L1 不稳定高相关时) | 平衡选择,大多数场景 |
7. 选型边界
线性模型 vs 树模型不是"谁精度更高"的比较,而是"谁更匹配数据结构和业务需求"的决策。
#mermaid-svg-9AG1vuA5dC2fjDMH{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-9AG1vuA5dC2fjDMH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-9AG1vuA5dC2fjDMH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-9AG1vuA5dC2fjDMH .error-icon{fill:#552222;}#mermaid-svg-9AG1vuA5dC2fjDMH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-9AG1vuA5dC2fjDMH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-9AG1vuA5dC2fjDMH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-9AG1vuA5dC2fjDMH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-9AG1vuA5dC2fjDMH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-9AG1vuA5dC2fjDMH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-9AG1vuA5dC2fjDMH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-9AG1vuA5dC2fjDMH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-9AG1vuA5dC2fjDMH .marker.cross{stroke:#333333;}#mermaid-svg-9AG1vuA5dC2fjDMH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-9AG1vuA5dC2fjDMH p{margin:0;}#mermaid-svg-9AG1vuA5dC2fjDMH .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-9AG1vuA5dC2fjDMH .cluster-label text{fill:#333;}#mermaid-svg-9AG1vuA5dC2fjDMH .cluster-label span{color:#333;}#mermaid-svg-9AG1vuA5dC2fjDMH .cluster-label span p{background-color:transparent;}#mermaid-svg-9AG1vuA5dC2fjDMH .label text,#mermaid-svg-9AG1vuA5dC2fjDMH span{fill:#333;color:#333;}#mermaid-svg-9AG1vuA5dC2fjDMH .node rect,#mermaid-svg-9AG1vuA5dC2fjDMH .node circle,#mermaid-svg-9AG1vuA5dC2fjDMH .node ellipse,#mermaid-svg-9AG1vuA5dC2fjDMH .node polygon,#mermaid-svg-9AG1vuA5dC2fjDMH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-9AG1vuA5dC2fjDMH .rough-node .label text,#mermaid-svg-9AG1vuA5dC2fjDMH .node .label text,#mermaid-svg-9AG1vuA5dC2fjDMH .image-shape .label,#mermaid-svg-9AG1vuA5dC2fjDMH .icon-shape .label{text-anchor:middle;}#mermaid-svg-9AG1vuA5dC2fjDMH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-9AG1vuA5dC2fjDMH .rough-node .label,#mermaid-svg-9AG1vuA5dC2fjDMH .node .label,#mermaid-svg-9AG1vuA5dC2fjDMH .image-shape .label,#mermaid-svg-9AG1vuA5dC2fjDMH .icon-shape .label{text-align:center;}#mermaid-svg-9AG1vuA5dC2fjDMH .node.clickable{cursor:pointer;}#mermaid-svg-9AG1vuA5dC2fjDMH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-9AG1vuA5dC2fjDMH .arrowheadPath{fill:#333333;}#mermaid-svg-9AG1vuA5dC2fjDMH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-9AG1vuA5dC2fjDMH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-9AG1vuA5dC2fjDMH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9AG1vuA5dC2fjDMH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-9AG1vuA5dC2fjDMH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9AG1vuA5dC2fjDMH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-9AG1vuA5dC2fjDMH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-9AG1vuA5dC2fjDMH .cluster text{fill:#333;}#mermaid-svg-9AG1vuA5dC2fjDMH .cluster span{color:#333;}#mermaid-svg-9AG1vuA5dC2fjDMH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-9AG1vuA5dC2fjDMH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-9AG1vuA5dC2fjDMH rect.text{fill:none;stroke-width:0;}#mermaid-svg-9AG1vuA5dC2fjDMH .icon-shape,#mermaid-svg-9AG1vuA5dC2fjDMH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9AG1vuA5dC2fjDMH .icon-shape p,#mermaid-svg-9AG1vuA5dC2fjDMH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-9AG1vuA5dC2fjDMH .icon-shape .label rect,#mermaid-svg-9AG1vuA5dC2fjDMH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9AG1vuA5dC2fjDMH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-9AG1vuA5dC2fjDMH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-9AG1vuA5dC2fjDMH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是,监管/审计要求
否
高维稀疏
文本/one-hot
低维稠密
数值特征
是
否
近似线性
强非线性
选型决策起点
业务要求可解释性?
线性模型
逻辑回归/Ridge
数据维度特征?
线性模型
Lasso/SVM线性核
特征间交互多?
树模型
XGBoost/RF
特征与目标关系?
线性模型
更稳定/可解释
树模型
或多项式扩展
残差检验
假设成立则可信
注意特征缩放
及正则化选择
注意特征重要性
可能需要 SHAP
量化对比:三种数据场景下的表现
场景一:高维稀疏文本分类(TF-IDF 特征, p = 10000 p=10000 p=10000)
- 逻辑回归(L2):在线性可分场景下接近 SVM 精度,训练速度快 10x
- XGBoost:在高维稀疏下反而因为特征选择开销而精度略低
- 结论:高维稀疏 → 线性模型优先
场景二:低维稠密特征,强非线性( p = 20 p=20 p=20,复杂交叉效应)
- 逻辑回归:约 72% 准确率
- XGBoost:约 91% 准确率
- 结论:低维稠密非线性 → 树模型优先
场景三:金融风控评分卡( p = 50 p=50 p=50,强可解释性要求)
- 逻辑回归:WOE 编码 + L2 正则,信用评分满足监管要求,可输出评分卡规则
- XGBoost:精度更高,但 SHAP 解释成本高,监管难以审核
- 结论:可解释性约束 → 线性模型 + 业务规则编码
多重共线性对线性模型的影响(量化分析)
python
import numpy as np
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.preprocessing import StandardScaler
# 模拟高度共线性场景
np.random.seed(42)
X_base = np.random.randn(100, 3)
# 特征4 = 特征1 + 0.1*噪声(几乎完全共线)
X_collinear = np.column_stack([
X_base,
X_base[:, 0] + 0.1 * np.random.randn(100)
])
y_sim = X_base @ [1, 2, 3] + np.random.randn(100) * 0.5
# OLS 系数不稳定
ols_coefs = []
for _ in range(50):
noise = np.random.randn(100) * 0.1
ols = LinearRegression().fit(X_collinear + noise.reshape(-1, 1) * 0.01, y_sim)
ols_coefs.append(ols.coef_[:2])
ols_coefs = np.array(ols_coefs)
print("OLS 系数1 标准差:", ols_coefs[:, 0].std().round(3)) # 应该很大
# Ridge 系数稳定
ridge_coefs = []
for _ in range(50):
noise = np.random.randn(100) * 0.1
ridge = Ridge(alpha=1.0).fit(X_collinear + noise.reshape(-1, 1) * 0.01, y_sim)
ridge_coefs.append(ridge.coef_[:2])
ridge_coefs = np.array(ridge_coefs)
print("Ridge 系数1 标准差:", ridge_coefs[:, 0].std().round(3)) # 应该更小
8. 多项式回归与核技巧
"线性模型"不等于"只能拟合直线"。通过特征工程,线性模型同样可以捕获非线性关系。
多项式特征扩展
python
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
# 二阶多项式:原始2个特征 → 1+2+1+2+1=6个特征(含交叉项)
poly_pipeline = Pipeline([
('poly', PolynomialFeatures(degree=2, include_bias=False)),
('ridge', Ridge(alpha=1.0))
])
poly_pipeline.fit(X[:, :2], y)
print("多项式+Ridge 特征数:", poly_pipeline.named_steps['poly'].n_output_features_)
警告 :三阶多项式在 p = 20 p=20 p=20 时会生成约 ( 20 + 3 3 ) ≈ 1771 \binom{20+3}{3} \approx 1771 (320+3)≈1771 个特征,容易过拟合。对于复杂非线性,树模型更安全。
核技巧的本质
核函数 k ( x i , x j ) = ϕ ( x i ) T ϕ ( x j ) k(x_i, x_j) = \phi(x_i)^T \phi(x_j) k(xi,xj)=ϕ(xi)Tϕ(xj) 允许在高维甚至无限维特征空间中做线性计算,而无需显式构建特征向量。RBF 核 SVM 本质上是在无限维特征空间中的线性分类器------这说明"线性假设"在足够丰富的特征空间中是普遍成立的。
9. 实战
房价预测是线性建模的经典场景,但真实的房价数据几乎必然违反某些线性假设------以此为切入点,完整走一遍诊断-修正流程。
python
import pandas as pd
import numpy as np
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import Ridge, Lasso, ElasticNet, LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
import statsmodels.api as sm
from statsmodels.stats.outliers_influence import variance_inflation_factor
import matplotlib.pyplot as plt
# 数据加载
housing = fetch_california_housing()
X_df = pd.DataFrame(housing.data, columns=housing.feature_names)
y = housing.target # 房价(10万美元单位)
print("特征概况:")
print(X_df.describe().round(2))
步骤1:VIF 多重共线性诊断
python
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_df)
X_scaled_df = pd.DataFrame(X_scaled, columns=X_df.columns)
vif_data = pd.DataFrame({
'feature': X_df.columns,
'VIF': [variance_inflation_factor(X_scaled, i) for i in range(X_scaled.shape[1])]
}).sort_values('VIF', ascending=False)
print("\nVIF 诊断:")
print(vif_data)
# AveRooms 和 AveBedrms 通常高度相关,VIF > 5
步骤2:残差诊断
python
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
ols = LinearRegression().fit(X_train, y_train)
y_pred_train = ols.predict(X_train)
residuals = y_train - y_pred_train
# 残差 vs 预测值(检验同方差性)
plt.figure(figsize=(8, 4))
plt.scatter(y_pred_train, residuals, alpha=0.3, s=5)
plt.axhline(0, color='red', linestyle='--')
plt.xlabel('预测值')
plt.ylabel('残差')
plt.title('残差 vs 预测值(同方差性检验)')
plt.tight_layout()
plt.savefig('residual_plot.png', dpi=100)
# 若残差随预测值增大而扩大 → 异方差 → 考虑对 y 做 log 变换
步骤3:三种正则化对比
python
models = {
'OLS': LinearRegression(),
'Ridge(α=1)': Ridge(alpha=1),
'Lasso(α=0.01)': Lasso(alpha=0.01),
'ElasticNet': ElasticNet(alpha=0.01, l1_ratio=0.5)
}
results = []
for name, model in models.items():
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
rmse = mean_squared_error(y_test, y_pred, squared=False)
r2 = r2_score(y_test, y_pred)
n_nonzero = (model.coef_ != 0).sum() if hasattr(model, 'coef_') else 8
results.append({'模型': name, 'RMSE': round(rmse, 4), 'R²': round(r2, 4), '非零系数': n_nonzero})
print(pd.DataFrame(results).to_string(index=False))
典型输出:
模型 RMSE R² 非零系数
OLS 0.7312 0.5862 8
Ridge(α=1) 0.7290 0.5875 8
Lasso(α=0.01) 0.7341 0.5829 6
ElasticNet 0.7308 0.5868 7
步骤4:与 XGBoost 的精度-可解释性权衡
python
from xgboost import XGBRegressor
xgb = XGBRegressor(n_estimators=100, random_state=42, verbosity=0).fit(X_train, y_train)
y_pred_xgb = xgb.predict(X_test)
print(f"XGBoost RMSE: {mean_squared_error(y_test, y_pred_xgb, squared=False):.4f}")
print(f"XGBoost R²: {r2_score(y_test, y_pred_xgb):.4f}")
# XGBoost 通常有明显精度提升,但线性模型输出每个特征的系数,便于业务解读
小结
#mermaid-svg-sjvuK9K08DCs8H5Q{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-sjvuK9K08DCs8H5Q .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-sjvuK9K08DCs8H5Q .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-sjvuK9K08DCs8H5Q .error-icon{fill:#552222;}#mermaid-svg-sjvuK9K08DCs8H5Q .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-sjvuK9K08DCs8H5Q .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-sjvuK9K08DCs8H5Q .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-sjvuK9K08DCs8H5Q .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-sjvuK9K08DCs8H5Q .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-sjvuK9K08DCs8H5Q .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-sjvuK9K08DCs8H5Q .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-sjvuK9K08DCs8H5Q .marker{fill:#333333;stroke:#333333;}#mermaid-svg-sjvuK9K08DCs8H5Q .marker.cross{stroke:#333333;}#mermaid-svg-sjvuK9K08DCs8H5Q svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-sjvuK9K08DCs8H5Q p{margin:0;}#mermaid-svg-sjvuK9K08DCs8H5Q .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-sjvuK9K08DCs8H5Q .cluster-label text{fill:#333;}#mermaid-svg-sjvuK9K08DCs8H5Q .cluster-label span{color:#333;}#mermaid-svg-sjvuK9K08DCs8H5Q .cluster-label span p{background-color:transparent;}#mermaid-svg-sjvuK9K08DCs8H5Q .label text,#mermaid-svg-sjvuK9K08DCs8H5Q span{fill:#333;color:#333;}#mermaid-svg-sjvuK9K08DCs8H5Q .node rect,#mermaid-svg-sjvuK9K08DCs8H5Q .node circle,#mermaid-svg-sjvuK9K08DCs8H5Q .node ellipse,#mermaid-svg-sjvuK9K08DCs8H5Q .node polygon,#mermaid-svg-sjvuK9K08DCs8H5Q .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-sjvuK9K08DCs8H5Q .rough-node .label text,#mermaid-svg-sjvuK9K08DCs8H5Q .node .label text,#mermaid-svg-sjvuK9K08DCs8H5Q .image-shape .label,#mermaid-svg-sjvuK9K08DCs8H5Q .icon-shape .label{text-anchor:middle;}#mermaid-svg-sjvuK9K08DCs8H5Q .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-sjvuK9K08DCs8H5Q .rough-node .label,#mermaid-svg-sjvuK9K08DCs8H5Q .node .label,#mermaid-svg-sjvuK9K08DCs8H5Q .image-shape .label,#mermaid-svg-sjvuK9K08DCs8H5Q .icon-shape .label{text-align:center;}#mermaid-svg-sjvuK9K08DCs8H5Q .node.clickable{cursor:pointer;}#mermaid-svg-sjvuK9K08DCs8H5Q .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-sjvuK9K08DCs8H5Q .arrowheadPath{fill:#333333;}#mermaid-svg-sjvuK9K08DCs8H5Q .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-sjvuK9K08DCs8H5Q .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-sjvuK9K08DCs8H5Q .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sjvuK9K08DCs8H5Q .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-sjvuK9K08DCs8H5Q .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sjvuK9K08DCs8H5Q .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-sjvuK9K08DCs8H5Q .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-sjvuK9K08DCs8H5Q .cluster text{fill:#333;}#mermaid-svg-sjvuK9K08DCs8H5Q .cluster span{color:#333;}#mermaid-svg-sjvuK9K08DCs8H5Q div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-sjvuK9K08DCs8H5Q .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-sjvuK9K08DCs8H5Q rect.text{fill:none;stroke-width:0;}#mermaid-svg-sjvuK9K08DCs8H5Q .icon-shape,#mermaid-svg-sjvuK9K08DCs8H5Q .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sjvuK9K08DCs8H5Q .icon-shape p,#mermaid-svg-sjvuK9K08DCs8H5Q .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-sjvuK9K08DCs8H5Q .icon-shape .label rect,#mermaid-svg-sjvuK9K08DCs8H5Q .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sjvuK9K08DCs8H5Q .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-sjvuK9K08DCs8H5Q .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-sjvuK9K08DCs8H5Q :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 线性模型知识体系
几何基础
投影/梯度下降
统计诊断
R²/F/t检验/残差四假设
正则化三策略
L1稀疏/L2稳定/ElasticNet
特征选择三法
过滤/包裹/嵌入
逻辑回归
概率校准/MLE
选型边界
高维稀疏/可解释性要求
实战应用
房价预测全流程
线性模型的价值不在于"简单",而在于:
- 诊断工具完善:残差分析、VIF、假设检验让模型行为透明
- 正则化路径清晰:L1/L2/ElasticNet 对应不同的数据特征
- 可解释性无可替代:金融风控、医疗诊断、监管合规场景的首选
树模型更强,但线性模型更可信。两者不是替代关系,而是互补的工具------理解线性模型的假设边界,才能知道什么时候应该"升级"。
如果这篇文章帮助理清了线性模型的思路,欢迎点赞收藏,也欢迎关注账号,后续会持续更新机器学习实战系列。之前的文章中,机器学习项目方法论 讲解了从业务问题到算法选型的系统决策框架,数据预处理与质量保障 覆盖了缺失值分型诊断和数据泄漏防范,两篇可作为本文的前置阅读。有任何疑问欢迎在评论区留言交流。