【特征选择方法】L2正则化(岭回归)
特征选择与防过拟合:L2正则化(岭回归)|原理+公式+Python实战全攻略
L2正则化(又称岭回归/Ridge Regression)是机器学习中控制模型过拟合、处理多重共线性的核心方法,也是特征选择的“隐形工具”。它不会直接删除特征,而是通过压缩不重要特征的系数实现“软筛选”,兼顾模型稳定性与泛化能力。
一、先搞懂:L2正则化到底解决什么问题?
1. 核心痛点:过拟合与多重共线性
- 过拟合:模型在训练数据上表现极好,但换了新数据就“翻车”(比如把噪声当成规律)
- 多重共线性:特征之间高度相关(如“身高”和“体重”),导致普通线性回归系数不稳定、解释性差
2. L2正则化的核心作用
- 防止过拟合:惩罚模型的复杂系数,让参数“变小”,避免过度依赖个别特征
- 处理多重共线性:通过正则化让相关特征的系数更均衡,避免系数波动过大
- 软特征选择:把不重要特征的系数压缩到接近0,间接筛选出关键特征(不直接删除)
3. 形象比喻:给模型“套紧箍咒”
普通线性回归像“无拘无束的学生”,为了考好(拟合训练数据)会死记硬背所有细节;而L2正则化像给学生套了“紧箍咒”,限制它过度复杂——虽然还是会学所有知识点(保留所有特征),但不会对无关细节(无用特征)过度关注,换套题(新数据)也能考好。
二、L2正则化是什么?通俗理解
1. 本质:给损失函数加“惩罚项”
L2正则化的核心是在模型的“损失函数”后,添加一项参数平方和的惩罚项,强制参数尽量“小而温和”:
- 重要特征:系数虽被惩罚,但仍保持较大值
- 不重要特征:系数被压缩到接近0,对预测结果影响极小
2. 与L1正则化的核心区别
| 对比项 | L2正则化(岭回归) | L1正则化(Lasso) |
|---|---|---|
| 正则项形式 | 系数的平方和(∑wj2\sum w_j^2∑wj2) | 系数的绝对值和(∑\sum∑ |wjw_jwj|) |
| 特征处理 | 系数接近0(软筛选) | 系数直接为0(硬删除) |
| 共线性处理 | 强(均衡相关特征系数) | 弱(随机保留一个相关特征) |
| 模型稳定性 | 高 | 低 |
三、核心公式(必须掌握)
1. 普通线性回归目标函数(最小二乘)
J(w,b)=12m∑i=1m(y^(i)−y(i))2 J(w, b) = \frac{1}{2m} \sum_{i=1}^m \left( \hat{y}^{(i)} - y^{(i)} \right)^2 J(w,b)=2m1i=1∑m(y^(i)−y(i))2
- 仅追求“预测误差最小”,容易导致系数过大(过拟合)或不稳定(多重共线性)
2. L2正则化(岭回归)目标函数
J(w,b)=12m∑i=1m(w⊤x(i)+b−y(i))2+λ2∥w∥22 J(w, b) = \frac{1}{2m} \sum_{i=1}^m \left( w^\top x^{(i)} + b - y^{(i)} \right)^2 + \frac{\lambda}{2} \|w\|_2^2 J(w,b)=2m1i=1∑m(w⊤x(i)+b−y(i))2+2λ∥w∥22
或矩阵形式(更简洁):
J(w)=12m∥Xw−y∥22+λ2∥w∥22 J(w) = \frac{1}{2m} \|Xw - y\|_2^2 + \frac{\lambda}{2} \|w\|_2^2 J(w)=2m1∥Xw−y∥22+2λ∥w∥22
各部分含义:
- ∥Xw−y∥22\|Xw - y\|_2^2∥Xw−y∥22:残差平方和(拟合误差项),衡量模型对数据的拟合程度
- λ\lambdaλ:正则化强度(惩罚系数)
- λ\lambdaλ 越大:惩罚越重,系数越小(模型越简单)
- λ\lambdaλ 越小:惩罚越轻,系数越接近普通回归(易过拟合)
- ∥w∥22=∑j=1nwj2\|w\|_2^2 = \sum_{j=1}^n w_j^2∥w∥22=∑j=1nwj2:L2范数(惩罚项核心),即所有特征系数的平方和
- bbb(偏置项):通常不参与惩罚(避免模型整体偏移)
3. 解析解(岭回归解)
对目标函数求导并令导数为0,可得到闭合解(无需迭代,直接计算):
wridge=(X⊤X+mλI)−1X⊤y w_{ridge} = (X^\top X + m\lambda I)^{-1} X^\top y wridge=(X⊤X+mλI)−1X⊤y
- III:单位矩阵,作用是让X⊤XX^\top XX⊤X可逆(解决多重共线性导致的矩阵奇异问题)
- 这也是岭回归比普通线性回归更稳定的核心原因
四、L2正则化的算法流程(必背)
- 数据准备:输入特征矩阵XXX,目标变量yyy
- 特征标准化(关键步骤):
L2对特征尺度敏感(如“收入(万元)”和“年龄(岁)”),需标准化为“均值=0,方差=1”,确保惩罚公平 - 设置正则化系数λ\lambdaλ:
通过交叉验证选择最优λ\lambdaλ,平衡拟合误差与模型复杂度 - 训练岭回归模型:
最小化目标函数,得到稳定的系数www - 软特征选择:
保留系数绝对值较大的特征,剔除系数接近0的特征(可设定阈值,如∣wj∣<0.01|w_j| < 0.01∣wj∣<0.01) - 模型评估:用筛选后的特征重新建模,验证泛化能力
五、Python 完整实战:加州房价预测与特征选择
1. 导入库+加载数据
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.linear_model import Ridge
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, r2_score
# 加载数据(20640个样本,8个特征)
housing = fetch_california_housing()
X = pd.DataFrame(housing.data, columns=housing.feature_names)
y = housing.target
print("样本数:", X.shape[0])
print("特征数:", X.shape[1])
print("特征名:", list(X.columns))
X.head()
2. 探索性数据分析(EDA)
# 1. 目标变量分布
plt.figure(figsize=(8, 4))
sns.histplot(y, bins=50, kde=True, color='#3498db')
plt.title("目标变量:房价中位数分布", fontsize=12)
plt.xlabel("房价中位数(单位:10万美元)")
plt.ylabel("频数")
plt.show()
# 2. 特征相关性热力图(查看多重共线性)
df_corr = X.copy()
df_corr['Target'] = y
corr = df_corr.corr()
plt.figure(figsize=(10, 8))
sns.heatmap(corr, annot=True, fmt=".2f", cmap='RdBu_r', vmin=-1, vmax=1)
plt.title("特征相关性热力图", fontsize=14)
plt.tight_layout()
plt.show()
3. 数据预处理(拆分+标准化)
# 1. 拆分训练集/测试集(7:3)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42
)
# 2. 标准化(L2正则化必须步骤)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
print("训练集标准化后形状:", X_train_scaled.shape)
print("测试集标准化后形状:", X_test_scaled.shape)
4. 初始岭回归模型(固定λ\lambdaλ)
# 设置初始正则化系数
alpha_init = 1.0
ridge_init = Ridge(alpha=alpha_init, random_state=42)
ridge_init.fit(X_train_scaled, y_train)
# 查看特征系数
coef_init = pd.Series(ridge_init.coef_, index=X.columns).sort_values()
print("=== 初始岭回归(alpha=1.0)特征系数 ===")
print(coef_init)
# 模型性能评估
y_train_pred = ridge_init.predict(X_train_scaled)
y_test_pred = ridge_init.predict(X_test_scaled)
print(f"\n训练集 MSE: {mean_squared_error(y_train, y_train_pred):.4f}")
print(f"训练集 R²: {r2_score(y_train, y_train_pred):.4f}")
print(f"测试集 MSE: {mean_squared_error(y_test, y_test_pred):.4f}")
print(f"测试集 R²: {r2_score(y_test, y_test_pred):.4f}")
# 可视化特征系数
plt.figure(figsize=(10, 6))
coef_init.plot(kind='barh', color='teal')
plt.axvline(0, color='black', linewidth=1)
plt.title("初始模型特征系数(alpha=1.0)", fontsize=12)
plt.xlabel("系数大小")
plt.grid(alpha=0.3, axis='x')
plt.show()
5. 交叉验证找最优λ\lambdaλ(推荐做法)
# 生成候选lambda(对数分布,覆盖范围更广)
alphas = np.logspace(-3, 3, 50) # 从0.001到1000的50个值
# 网格搜索+5折交叉验证
param_grid = {'alpha': alphas}
grid = GridSearchCV(
Ridge(random_state=42),
param_grid,
cv=5,
scoring='neg_mean_squared_error', # 负MSE(越大越好)
n_jobs=-1 # 并行计算
)
grid.fit(X_train_scaled, y_train)
# 最优结果
best_alpha = grid.best_params_['alpha']
best_ridge = grid.best_estimator_
print(f"=== 交叉验证最优结果 ===")
print(f"最优lambda: {best_alpha:.4f}")
# 最优模型性能
y_test_pred_best = best_ridge.predict(X_test_scaled)
print(f"优化后测试集 MSE: {mean_squared_error(y_test, y_test_pred_best):.4f}")
print(f"优化后测试集 R²: {r2_score(y_test, y_test_pred_best):.4f}")
6. λ\lambdaλ对模型的影响可视化
# 1. MSE随lambda变化趋势
mse_train_list = []
mse_test_list = []
for a in alphas:
model = Ridge(alpha=a, random_state=42)
model.fit(X_train_scaled, y_train)
mse_train_list.append(mean_squared_error(y_train, model.predict(X_train_scaled)))
mse_test_list.append(mean_squared_error(y_test, model.predict(X_test_scaled)))
plt.figure(figsize=(10, 6))
plt.plot(alphas, mse_train_list, label='训练集MSE', color='blue')
plt.plot(alphas, mse_test_list, label='测试集MSE', color='red')
plt.xscale('log') # 对数刻度,更清晰
plt.xlabel('lambda(正则化强度)')
plt.ylabel('均方误差(MSE)')
plt.title('MSE随lambda变化趋势', fontsize=12)
plt.legend()
plt.grid(alpha=0.3)
plt.show()
# 2. 特征系数随lambda变化趋势
coef_df = pd.DataFrame(index=alphas, columns=X.columns)
for a in alphas:
model = Ridge(alpha=a, random_state=42)
model.fit(X_train_scaled, y_train)
coef_df.loc[a] = model.coef_
plt.figure(figsize=(12, 6))
for col in X.columns:
plt.plot(alphas, coef_df[col], label=col)
plt.xscale('log')
plt.xlabel('lambda(正则化强度)')
plt.ylabel('特征系数')
plt.title('特征系数随lambda变化路径', fontsize=12)
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.grid(alpha=0.3)
plt.tight_layout()
plt.show()
7. 最优模型的特征筛选与可视化
# 最优模型特征系数
coef_best = pd.Series(best_ridge.coef_, index=X.columns).sort_values()
# 可视化最优系数
plt.figure(figsize=(10, 6))
coef_best.plot(kind='barh', color='purple')
plt.axvline(0, color='black', linewidth=1)
plt.title(f"最优模型特征系数(lambda={best_alpha:.4f})", fontsize=12)
plt.xlabel("系数大小")
plt.grid(alpha=0.3, axis='x')
plt.show()
# 软特征选择(筛选系数绝对值>0.05的特征)
threshold = 0.05
selected_features = coef_best[abs(coef_best) > threshold].index.tolist()
print(f"=== 筛选后的关键特征 ===")
print(selected_features)
# 用筛选后的特征重新建模
X_train_selected = X_train[selected_features]
X_test_selected = X_test[selected_features]
# 标准化筛选后的特征
scaler_selected = StandardScaler()
X_train_selected_scaled = scaler_selected.fit_transform(X_train_selected)
X_test_selected_scaled = scaler_selected.transform(X_test_selected)
# 训练最终模型
final_model = Ridge(alpha=best_alpha, random_state=42)
final_model.fit(X_train_selected_scaled, y_train)
# 最终性能
y_pred_final = final_model.predict(X_test_selected_scaled)
print(f"\n筛选后模型 R²: {r2_score(y_test, y_pred_final):.4f}")
print(f"筛选后模型 MSE: {mean_squared_error(y_test, y_pred_final):.4f}")
8. 预测结果可视化(真实值vs预测值)
plt.figure(figsize=(8, 6))
plt.scatter(y_test, y_test_pred_best, alpha=0.3, color='blue')
plt.plot([y.min(), y.max()], [y.min(), y.max()], 'k--', linewidth=2) # 对角线(理想预测)
plt.xlabel('真实房价中位数')
plt.ylabel('预测房价中位数')
plt.title('真实值 vs 预测值(最优岭回归模型)', fontsize=12)
plt.grid(alpha=0.3)
plt.show()
# 残差分布(验证模型假设合理性)
residuals = y_test - y_test_pred_best
plt.figure(figsize=(8, 4))
sns.histplot(residuals, bins=50, kde=True, color='gray')
plt.title('残差分布(真实值-预测值)', fontsize=12)
plt.xlabel('残差值')
plt.ylabel('频数')
plt.grid(alpha=0.3)
plt.show()
六、L2正则化的优缺点(必背)
优点
- 稳定处理多重共线性:通过正则化让相关特征系数均衡,避免普通回归的系数波动
- 防止过拟合:惩罚系数平方和,控制模型复杂度,提升泛化能力
- 数学解稳定:解析解存在且可逆(解决矩阵奇异问题),计算高效
- 保留全部特征:软筛选不直接删除特征,避免信息丢失(适合特征都有潜在价值的场景)
- 对异常值相对稳健:相比普通回归,受极端值影响更小
缺点
- 不能显式特征选择:系数不会直接为0,无法彻底删除无用特征(需手动设定阈值)
- 模型解释性略差:保留所有特征,即使系数接近0也会参与预测,不如L1简洁
- 依赖标准化:对特征尺度敏感,必须先标准化才能保证惩罚公平
- 不适用于稀疏建模:若需构建“少特征”的稀疏模型,L2不如L1或ElasticNet
七、L2正则化与其他特征选择方法对比
| 方法 | 正则项形式 | 是否稀疏 | 抗多重共线性 | 特征选择方式 | 适合场景 |
|---|---|---|---|---|---|
| L2正则化(岭回归) | ∑wj2\sum w_j^2∑wj2 | 否 | 强 | 软选择(系数接近0) | 特征相关、需保留全部特征 |
| L1正则化(Lasso) | ∑\sum∑ |wjw_jwj| | 是 | 弱 | 硬选择(系数=0) | 高维数据、需稀疏建模 |
| ElasticNet | λ1∑\lambda_1\sumλ1∑ |wjw_jwj| + λ2∑wj2\lambda_2\sum w_j^2λ2∑wj2 | 是 | 中 | 混合选择 | 需平衡稀疏性与稳定性 |
| 树模型(RF/XGBoost) | 基于节点分裂增益 | 是 | 强 | 嵌入式选择 | 非线性关系、特征交互复杂 |
| 过滤法(卡方/方差) | 无(基于统计指标) | 是 | 弱 | 过滤式选择 | 初步粗筛、快速去除低价值特征 |
八、适用场景与替代方案
优先用L2正则化的情况
- 特征存在显著多重共线性(如经济、金融数据)
- 不希望删除任何特征(担心信息丢失)
- 追求模型稳定性和泛化能力(预测优先于解释)
- 线性模型场景(如线性回归、逻辑回归)
考虑其他方法的情况
- 需显式删除特征(稀疏建模):用L1正则化或ElasticNet
- 数据非线性、特征交互复杂:用随机森林、XGBoost(自带特征重要性)
- 快速粗筛特征:用过滤法(如方差阈值、互信息)
- 既要稀疏性又要稳定性:用ElasticNet(L1+L2混合)
九、最简单总结(背诵版)
- L2正则化(岭回归)= 线性回归 + L2范数惩罚(系数平方和)
- 核心作用:防过拟合、处理多重共线性、软特征选择
- 关键步骤:必须标准化特征 + 交叉验证调λ\lambdaλ
- 优点:稳定、抗共线性、保留全部特征
- 缺点:不直接删除特征、依赖标准化、不适用于稀疏建模
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)