机器学习正则化完全指南:方法、语法、案例与表格
一、正则化核心基础
1. 定义
正则化(Regularization)是防止模型过拟合的核心技术,通过在损失函数中引入惩罚项或通过限制模型训练过程,控制模型复杂度,平衡“偏差-方差权衡”(Bias-Variance Tradeoff):
- 过拟合:模型在训练集上表现极好,但泛化到新数据时误差剧增(高方差、低偏差);
- 正则化本质:“约束模型的学习能力”,避免模型过度学习训练集中的噪声。
2. 核心目标
- 降低模型方差,提升泛化能力;
- 不显著增加模型偏差(避免欠拟合);
- 处理高维数据时减少冗余特征影响(如L1正则化的特征选择)。
二、正则化方法全梳理(按类型分类)
正则化方法可分为 5大类:参数正则化(最核心)、训练过程正则化、数据增强类、集成学习类、神经网络专用正则化。以下逐一详解:
三、第一类:参数正则化(核心方法)
定义
通过在损失函数中添加权重惩罚项,限制模型参数(如线性模型的系数、神经网络的权重)的绝对值或平方和,降低模型复杂度。
核心公式:
正则化损失=原始损失+λ×惩罚项\text{正则化损失} = \text{原始损失} + \lambda \times \text{惩罚项}正则化损失=原始损失+λ×惩罚项
- λ\lambdaλ(正则化强度):λ>0\lambda>0λ>0,越大惩罚越强(易欠拟合),越小惩罚越弱(易过拟合),λ=0\lambda=0λ=0 无正则化。
1. L2正则化(岭回归/Ridge Regression)
(1)原理
惩罚项为参数权重的平方和,迫使权重趋近于0(但不绝对为0),让模型更“平滑”。
惩罚项公式:L2=λ∑i=1nwi2L_2 = \lambda \sum_{i=1}^n w_i^2L2=λi=1∑nwi2(wiw_iwi 为模型参数)
(2)语法格式(Python-scikit-learn)
from sklearn.linear_model import Ridge
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score
# 1. 初始化模型(关键参数)
model = Ridge(
alpha=1.0, # 正则化强度(核心参数),默认1.0
fit_intercept=True, # 是否拟合截距(截距不参与正则化)
solver='auto' # 优化器(auto/lsqr/sag等)
)
# 2. 训练与预测
model.fit(X_train, y_train) # X: 特征矩阵,y: 标签
y_pred = model.predict(X_test)
# 3. 评估
print("R²得分:", r2_score(y_test, y_pred))
print("模型系数:", model.coef_) # 权重(趋近于0但不为0)
(3)案例:加州房价回归(对比无正则化)
# 加载数据(替代弃用的波士顿房价数据集)
from sklearn.datasets import fetch_california_housing
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler
# 1. 数据预处理
data = fetch_california_housing()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 标准化(正则化前必须标准化,避免特征尺度影响惩罚效果)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 2. 无正则化(普通线性回归)
lr = LinearRegression()
lr.fit(X_train_scaled, y_train)
lr_train_r2 = r2_score(y_train, lr.predict(X_train_scaled))
lr_test_r2 = r2_score(y_test, lr.predict(X_test_scaled))
# 3. L2正则化(岭回归)
ridge = Ridge(alpha=1.0)
ridge.fit(X_train_scaled, y_train)
ridge_train_r2 = r2_score(y_train, ridge.predict(X_train_scaled))
ridge_test_r2 = r2_score(y_test, ridge.predict(X_test_scaled))
# 4. 结果对比
print("普通线性回归:")
print(f"训练集R²: {lr_train_r2:.4f}, 测试集R²: {lr_test_r2:.4f}")
print("岭回归(L2正则化):")
print(f"训练集R²: {ridge_train_r2:.4f}, 测试集R²: {ridge_test_r2:.4f}")
print("岭回归系数(绝对值更小):", ridge.coef_)
(4)结果分析
- 岭回归的训练集R²略低于普通线性回归(牺牲部分训练拟合);
- 测试集R²更高(泛化能力提升);
- 岭回归系数的绝对值远小于普通线性回归(权重被“压制”)。
(5)优缺点
| 优点 | 缺点 |
|---|---|
| 稳定,不易受异常值影响 | 不具备特征选择能力(权重不置零) |
| 计算高效,适用于高维数据 | 对特征尺度敏感(需标准化) |
| 可同时保留所有特征 |
2. L1正则化(Lasso回归)
(1)原理
惩罚项为参数权重的绝对值和,会迫使部分权重直接变为0,实现“特征选择”(剔除冗余特征)。
惩罚项公式:L1=λ∑i=1n∣wi∣L_1 = \lambda \sum_{i=1}^n |w_i|L1=λi=1∑n∣wi∣
(2)语法格式(Python-scikit-learn)
from sklearn.linear_model import Lasso
# 1. 初始化模型(关键参数)
model = Lasso(
alpha=1.0, # 正则化强度(核心)
fit_intercept=True, # 拟合截距
max_iter=1000, # 迭代次数(Lasso是凸优化,需足够迭代)
tol=0.0001 # 收敛阈值
)
# 2. 训练与预测(同Ridge)
model.fit(X_train_scaled, y_train)
y_pred = model.predict(X_test_scaled)
# 3. 查看特征选择结果(系数为0的特征被剔除)
zero_coef_idx = [i for i, coef in enumerate(model.coef_) if coef == 0]
print("被剔除的特征索引:", zero_coef_idx)
print("保留的特征索引:", [i for i, coef in enumerate(model.coef_) if coef != 0])
(3)案例:加州房价特征选择
沿用上述加州房价数据,对比Lasso与Ridge的特征选择效果:
# L1正则化(Lasso)
lasso = Lasso(alpha=0.1, max_iter=10000) # alpha=0.1(适中强度)
lasso.fit(X_train_scaled, y_train)
lasso_train_r2 = r2_score(y_train, lasso.predict(X_train_scaled))
lasso_test_r2 = r2_score(y_test, lasso.predict(X_test_scaled))
# 结果对比
print("Lasso回归:")
print(f"训练集R²: {lasso_train_r2:.4f}, 测试集R²: {lasso_test_r2:.4f}")
print("Lasso系数(含0):", lasso.coef_)
print("被剔除的特征数:", sum(lasso.coef_ == 0))
(4)结果分析
- Lasso的部分系数变为0(例如:假设“平均房间数”特征系数为0,说明该特征对房价影响小,被剔除);
- 测试集R²可能高于Ridge(当存在冗余特征时)。
(5)优缺点
| 优点 | 缺点 |
|---|---|
| 自动特征选择,简化模型 | 高维稀疏数据下可能不稳定(系数波动大) |
| 剔除冗余特征,提升可解释性 | 对异常值敏感 |
| 适用于高维小样本数据 | 当特征高度相关时,可能随机剔除其中一个 |
3. 弹性网络(ElasticNet)
(1)原理
结合L1和L2正则化的优点,同时添加L1和L2惩罚项,解决L1在高维相关数据下的不稳定性。
惩罚项公式:Lelastic=λ1∑∣wi∣+λ2∑wi2L_{\text{elastic}} = \lambda_1 \sum |w_i| + \lambda_2 \sum w_i^2Lelastic=λ1∑∣wi∣+λ2∑wi2
或等价形式(scikit-learn采用):Lelastic=α×[l1_ratio×∑∣wi∣+(1−l1_ratio)×0.5∑wi2]L_{\text{elastic}} = \alpha \times [l1\_ratio \times \sum |w_i| + (1-l1\_ratio) \times 0.5 \sum w_i^2]Lelastic=α×[l1_ratio×∑∣wi∣+(1−l1_ratio)×0.5∑wi2]
- l1_ratiol1\_ratiol1_ratio:L1惩罚的比例(0≤l1_ratio≤1),0=纯L2,1=纯L1。
(2)语法格式(Python-scikit-learn)
from sklearn.linear_model import ElasticNet
# 1. 初始化模型(关键参数)
model = ElasticNet(
alpha=1.0, # 总正则化强度
l1_ratio=0.5, # L1比例(0.5=L1和L2各占一半)
fit_intercept=True,
max_iter=10000
)
# 2. 训练与预测
model.fit(X_train_scaled, y_train)
y_pred = model.predict(X_test_scaled)
(3)案例:高维相关特征回归
假设数据存在高度相关特征(如“房屋面积(平方米)”和“房屋面积(平方英尺)”),对比Lasso和ElasticNet:
# 构造高维相关数据(在加州房价数据中添加相关特征)
import numpy as np
X_corr = np.hstack([X_train_scaled, X_train_scaled[:, 0:2] * 0.8 + np.random.randn(X_train_scaled.shape[0], 2) * 0.1]) # 添加2个相关特征
X_test_corr = np.hstack([X_test_scaled, X_test_scaled[:, 0:2] * 0.8 + np.random.randn(X_test_scaled.shape[0], 2) * 0.1])
# Lasso在相关特征上的表现
lasso_corr = Lasso(alpha=0.1, max_iter=10000)
lasso_corr.fit(X_corr, y_train)
lasso_corr_test_r2 = r2_score(y_test, lasso_corr.predict(X_test_corr))
# ElasticNet在相关特征上的表现
elastic = ElasticNet(alpha=0.1, l1_ratio=0.5, max_iter=10000)
elastic.fit(X_corr, y_train)
elastic_test_r2 = r2_score(y_test, elastic.predict(X_test_corr))
print("高维相关数据下:")
print(f"Lasso测试集R²: {lasso_corr_test_r2:.4f}")
print(f"ElasticNet测试集R²: {elastic_test_r2:.4f}")
(4)结果分析
- ElasticNet的测试集R²高于Lasso(避免了L1随机剔除相关特征的问题);
- 系数更稳定,兼顾特征选择(L1)和权重平滑(L2)。
(5)优缺点
| 优点 | 缺点 |
|---|---|
| 兼顾L1的特征选择和L2的稳定性 | 需调参(alpha和l1_ratio),计算量略大 |
| 适用于高维、特征相关的数据 | 对特征尺度敏感(需标准化) |
核心参数正则化对比表
| 方法 | 惩罚项形式 | 权重影响 | 特征选择 | 适用场景 | 核心参数 |
|---|---|---|---|---|---|
| L2(Ridge) | λ∑wi2\lambda\sum w_i^2λ∑wi2 | 权重趋近于0(不为0) | 无 | 特征低维、无冗余、需稳定模型 | alpha |
| L1(Lasso) | $\lambda\sum | w_i | $ | 部分权重=0 | 有 |
| ElasticNet | $\alpha[l1_ratio\sum | w_i | + (1-l1_ratio)\sum w_i^2]$ | 部分权重=0,其余趋近于0 | 有 |
四、第二类:训练过程正则化
1. 早停(Early Stopping)
(1)原理
在模型训练过程中,监控验证集性能(如验证损失、准确率),当性能不再提升(或开始下降)时,提前停止训练,避免模型过度拟合训练数据。
核心逻辑:训练的“早期”模型泛化能力弱(欠拟合),“中期”泛化能力最优,“后期”过拟合。
(2)语法格式
- 场景1:神经网络(TensorFlow/Keras)(内置早停回调)
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
# 1. 定义早停回调
early_stopping = tf.keras.callbacks.EarlyStopping(
monitor='val_loss', # 监控指标(验证损失)
patience=5, # 连续5个epoch性能无提升则停止
restore_best_weights=True, # 恢复最优epoch的权重
mode='min' # 指标最小化(loss)/最大化(accuracy)
)
# 2. 构建神经网络
model = Sequential([
Dense(64, activation='relu', input_shape=(X_train_scaled.shape[1],)),
Dense(32, activation='relu'),
Dense(1)
])
model.compile(optimizer='adam', loss='mse')
# 3. 训练(加入早停回调)
history = model.fit(
X_train_scaled, y_train,
validation_data=(X_test_scaled, y_test),
epochs=100, # 最大迭代次数
batch_size=32,
callbacks=[early_stopping] # 早停回调
)
- 场景2:传统模型(scikit-learn)(手动实现)
from sklearn.linear_model import SGDRegressor
from sklearn.metrics import mean_squared_error
# 手动早停逻辑
n_epochs = 1000
best_val_mse = float('inf')
patience = 10
patience_counter = 0
best_weights = None
model = SGDRegressor(loss='squared_error', warm_start=True) # warm_start=True允许续训
for epoch in range(n_epochs):
model.partial_fit(X_train_scaled, y_train) # 增量训练
val_mse = mean_squared_error(y_test, model.predict(X_test_scaled))
# 监控验证MSE
if val_mse < best_val_mse:
best_val_mse = val_mse
best_weights = model.coef_.copy()
patience_counter = 0
else:
patience_counter += 1
# 早停条件
if patience_counter >= patience:
print(f"早停于epoch {epoch+1},最优验证MSE: {best_val_mse:.4f}")
break
# 恢复最优权重
model.coef_ = best_weights
(3)案例:神经网络训练早停
沿用加州房价数据,对比早停与不早停的效果:
# 无早停训练
model_no_earlystop = Sequential([
Dense(64, activation='relu', input_shape=(X_train_scaled.shape[1],)),
Dense(32, activation='relu'),
Dense(1)
])
model_no_earlystop.compile(optimizer='adam', loss='mse')
history_no_earlystop = model_no_earlystop.fit(
X_train_scaled, y_train,
validation_data=(X_test_scaled, y_test),
epochs=100, batch_size=32
)
# 可视化对比
import matplotlib.pyplot as plt
plt.plot(history.history['val_loss'], label='早停-验证损失')
plt.plot(history_no_earlystop.history['val_loss'], label='无早停-验证损失')
plt.xlabel('Epoch')
plt.ylabel('MSE')
plt.legend()
plt.show()
(4)结果分析
- 无早停的验证损失在后期会上升(过拟合);
- 早停会在验证损失最低时停止,避免过拟合。
(5)优缺点
| 优点 | 缺点 |
|---|---|
| 简单高效,无需修改模型结构 | 需合理设置监控指标和patience |
| 适用于所有迭代式训练模型(神经网络、SGD) | 可能因噪声导致过早停止 |
2. 权重衰减(Weight Decay)
(1)原理
与L2正则化完全等价,只是实现方式不同:L2是在损失函数中加惩罚项,权重衰减是在优化器中直接对权重更新施加惩罚(更新时权重乘以衰减系数)。
公式:wt+1=wt−η(∇L+λwt)w_{t+1} = w_t - \eta (\nabla L + \lambda w_t)wt+1=wt−η(∇L+λwt)(η\etaη 学习率,∇L\nabla L∇L 损失梯度)
(2)语法格式
- PyTorch:
import torch
import torch.nn as nn
import torch.optim as optim
# 定义模型
class SimpleNet(nn.Module):
def __init__(self):
super().__init__()
self.fc = nn.Sequential(nn.Linear(8, 64), nn.ReLU(), nn.Linear(64, 1))
def forward(self, x):
return self.fc(x)
model = SimpleNet()
# 优化器中设置权重衰减(weight_decay=lambda)
optimizer = optim.SGD(model.parameters(), lr=0.01, weight_decay=0.01) # weight_decay即λ
- TensorFlow/Keras:
# 在优化器中设置权重衰减
optimizer = tf.keras.optimizers.Adam(learning_rate=0.001, weight_decay=0.01)
model.compile(optimizer=optimizer, loss='mse')
(3)优缺点
| 优点 | 缺点 |
|---|---|
| 实现简洁,与优化器结合紧密 | 仅等价于L2正则化,无特征选择能力 |
| 适用于神经网络,无需手动修改损失函数 | 对特征尺度敏感 |
五、第三类:数据增强类正则化
核心思想
通过增加训练数据量(或等价增加数据多样性),让模型学习更通用的特征,从源头减少过拟合。适用于数据量小的场景(如图像、文本)。
1. 数据扩充(Data Augmentation)
(1)原理
对原始训练数据进行无标签变换(不改变数据语义),生成新的训练样本。
(2)常见变换方式
| 数据类型 | 常用变换 |
|---|---|
| 图像 | 旋转、翻转、裁剪、缩放、亮度/对比度调整、高斯噪声 |
| 文本 | 同义词替换、随机插入/删除单词、句子重排 |
| 结构化数据 | 特征扰动(如对数值特征加微小噪声)、采样增强 |
(3)语法格式(图像数据-TensorFlow)
from tensorflow.keras.preprocessing.image import ImageDataGenerator
# 1. 定义数据扩充器
datagen = ImageDataGenerator(
rotation_range=15, # 随机旋转±15°
width_shift_range=0.1, # 水平偏移±10%
height_shift_range=0.1, # 垂直偏移±10%
shear_range=0.1, # 剪切变换
zoom_range=0.1, # 随机缩放±10%
horizontal_flip=True, # 水平翻转
fill_mode='nearest' # 填充方式
)
# 2. 加载原始图像数据(假设从文件夹加载)
train_generator = datagen.flow_from_directory(
'train_images/',
target_size=(224, 224),
batch_size=32,
class_mode='binary'
)
# 3. 训练模型
model.fit(train_generator, epochs=50)
(4)案例:图像分类数据扩充
# 加载CIFAR-10数据集
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()
x_train = x_train / 255.0 # 归一化
# 数据扩充
datagen = ImageDataGenerator(
rotation_range=10,
horizontal_flip=True,
zoom_range=0.1
)
datagen.fit(x_train)
# 构建CNN模型
model = Sequential([
tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(32,32,3)),
tf.keras.layers.MaxPooling2D((2,2)),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# 用扩充数据训练
history_aug = model.fit(datagen.flow(x_train, y_train, batch_size=32), epochs=20, validation_data=(x_test/255.0, y_test))
(5)优缺点
| 优点 | 缺点 |
|---|---|
| 无需修改模型,直接提升数据多样性 | 仅适用于特定数据类型(图像、文本效果好,结构化数据有限) |
| 成本低,无需手动标注新数据 | 变换需合理(避免改变数据语义,如图像翻转数字6→9) |
2. 交叉验证(Cross Validation)
(1)原理
将训练集划分为kkk个互斥子集(kkk折),轮流用k−1k-1k−1个子集训练,1个子集验证,最终取kkk次验证结果的平均值作为模型性能指标。
核心作用:评估模型稳定性,避免单次数据划分的偶然性导致的过拟合判断误差,同时辅助选择最优正则化参数(如alpha)。
(2)常见类型
| 类型 | 适用场景 |
|---|---|
| k折交叉验证(k-Fold) | 数据量充足,无类别不平衡 |
| 分层k折(Stratified k-Fold) | 类别不平衡数据(保持各折类别比例一致) |
| 留一交叉验证(Leave-One-Out) | 数据量极小(k=样本数) |
(3)语法格式(scikit-learn)
from sklearn.model_selection import cross_val_score, KFold
from sklearn.linear_model import Ridge
# 1. 定义k折划分器
kf = KFold(n_splits=5, shuffle=True, random_state=42) # 5折,随机打乱
# 2. 定义模型(带正则化参数)
model = Ridge(alpha=1.0)
# 3. 交叉验证评估
scores = cross_val_score(model, X_scaled, y, cv=kf, scoring='r2') # 评估R²得分
print(f"5折交叉验证R²得分:{scores.mean():.4f} ± {scores.std():.4f}")
# 4. 用交叉验证选择最优alpha(网格搜索)
from sklearn.model_selection import GridSearchCV
param_grid = {'alpha': [0.001, 0.01, 0.1, 1, 10, 100]} # 候选alpha值
grid_search = GridSearchCV(Ridge(), param_grid, cv=5, scoring='r2')
grid_search.fit(X_scaled, y)
print(f"最优alpha: {grid_search.best_params_['alpha']}")
print(f"最优交叉验证R²: {grid_search.best_score_:.4f}")
(4)案例:用交叉验证选择Lasso的alpha
# 定义alpha候选集
param_grid = {'alpha': [0.001, 0.01, 0.1, 1, 5, 10]}
# 分层5折交叉验证(回归任务用普通KFold)
kf = KFold(n_splits=5, shuffle=True, random_state=42)
# 网格搜索
grid_lasso = GridSearchCV(Lasso(max_iter=10000), param_grid, cv=kf, scoring='r2')
grid_lasso.fit(X_scaled, y)
# 输出最优结果
print(f"最优alpha: {grid_lasso.best_params_['alpha']}")
print(f"最优模型测试集R²: {r2_score(y_test, grid_lasso.predict(X_test_scaled)):.4f}")
(5)优缺点
| 优点 | 缺点 |
|---|---|
| 评估更可靠,避免数据划分运气成分 | 计算量随k增加而增大(k=5时计算量是单次训练的5倍) |
| 辅助选择正则化参数 | 不适用于超大数据集(训练时间过长) |
六、第四类:集成学习类正则化
核心思想
通过训练多个基模型,将其预测结果组合(投票/平均),降低单个模型的方差(过拟合风险)。集成学习本身就是一种强正则化策略。
1. Bagging(套袋法)
(1)原理
- Bootstrap采样:对训练集进行有放回抽样,生成mmm个不同的子训练集;
- 并行训练:用每个子训练集训练一个基模型(同类型);
- 结果融合:回归任务取预测值平均,分类任务取投票结果。
- 代表算法:随机森林(Random Forest)(在Bagging基础上加入特征随机选择)。
(2)语法格式(scikit-learn)
from sklearn.ensemble import RandomForestRegressor
# 1. 初始化随机森林(Bagging的变种)
model = RandomForestRegressor(
n_estimators=100, # 基模型数量(树的数量)
max_depth=10, # 每棵树的最大深度(控制单棵树复杂度)
min_samples_split=2, # 节点分裂最小样本数
random_state=42
)
# 2. 训练与预测
model.fit(X_train, y_train) # 无需标准化(树模型对尺度不敏感)
y_pred = model.predict(X_test)
# 3. 评估
print("随机森林测试集R²:", r2_score(y_test, y_pred))
(3)案例:对比单棵决策树与随机森林
from sklearn.tree import DecisionTreeRegressor
# 单棵决策树(易过拟合)
dt = DecisionTreeRegressor(max_depth=None, random_state=42)
dt.fit(X_train, y_train)
dt_test_r2 = r2_score(y_test, dt.predict(X_test))
# 随机森林(Bagging正则化)
rf = RandomForestRegressor(n_estimators=100, max_depth=10, random_state=42)
rf.fit(X_train, y_train)
rf_test_r2 = r2_score(y_test, rf.predict(X_test))
print(f"单棵决策树测试集R²: {dt_test_r2:.4f}")
print(f"随机森林测试集R²: {rf_test_r2:.4f}")
(4)结果分析
- 随机森林的测试集R²远高于单棵决策树(降低了过拟合);
- 基模型数量(n_estimators)越多,方差越低(但计算量增大)。
2. Boosting(提升法)
(1)原理
- 串行训练:基模型按顺序训练,每个新模型专注于纠正前一个模型的预测错误(对错误样本赋予更高权重);
- 加权融合:最终预测结果是所有基模型的加权和(性能好的模型权重更高);
- 代表算法:XGBoost、LightGBM、CatBoost(通过正则化参数控制复杂度)。
(2)语法格式(XGBoost)
import xgboost as xgb
# 1. 数据格式转换(XGBoost支持DMatrix格式,更高效)
dtrain = xgb.DMatrix(X_train, label=y_train)
dtest = xgb.DMatrix(X_test, label=y_test)
# 2. 设置参数(含正则化参数)
params = {
'objective': 'reg:squarederror', # 回归任务
'max_depth': 5, # 树的最大深度(控制复杂度)
'learning_rate': 0.1, # 学习率(步长)
'subsample': 0.8, # 样本采样比例(防止过拟合)
'colsample_bytree': 0.8, # 特征采样比例(防止过拟合)
'reg_alpha': 0.1, # L1正则化系数
'reg_lambda': 1.0 # L2正则化系数
}
# 3. 训练模型
model = xgb.train(params, dtrain, num_boost_round=100, evals=[(dtest, 'test')], early_stopping_rounds=10)
# 4. 预测
y_pred = model.predict(dtest)
print("XGBoost测试集R²:", r2_score(y_test, y_pred))
(3)优缺点(Bagging vs Boosting)
| 方法 | 优点 | 缺点 |
|---|---|---|
| Bagging(随机森林) | 并行训练,速度快;不易过拟合;对异常值鲁棒 | 对超参数不敏感,但预测精度可能低于Boosting |
| Boosting(XGBoost) | 预测精度高;能处理非线性关系;支持特征重要性评估 | 串行训练,速度慢;易过拟合(需调参);对异常值敏感 |
3. Stacking(堆叠法)
(1)原理
- 第一层(基模型):训练多个不同类型的基模型(如随机森林、XGBoost、逻辑回归);
- 第二层(元模型):将基模型的预测结果作为新特征,训练一个元模型(如线性回归、逻辑回归),输出最终预测。
- 核心作用:结合不同模型的优势,进一步降低方差。
(2)语法格式(scikit-learn)
from sklearn.ensemble import StackingRegressor
from sklearn.linear_model import LinearRegression
# 1. 定义基模型
base_models = [
('rf', RandomForestRegressor(n_estimators=100, random_state=42)),
('xgb', xgb.XGBRegressor(n_estimators=100, random_state=42)),
('ridge', Ridge(alpha=1.0))
]
# 2. 定义元模型(线性回归)
meta_model = LinearRegression()
# 3. 初始化Stacking模型
stack_model = StackingRegressor(
estimators=base_models,
final_estimator=meta_model,
cv=5 # 交叉验证生成基模型的预测结果
)
# 4. 训练与预测
stack_model.fit(X_train, y_train)
y_pred = stack_model.predict(X_test)
print("Stacking测试集R²:", r2_score(y_test, y_pred))
七、第五类:神经网络专用正则化
1. Dropout(随机失活)
(1)原理
训练时,随机将部分神经元的输出置为0(按概率ppp),迫使模型不依赖单个神经元,学习更鲁棒的特征;测试时,所有神经元均激活,输出按1−p1-p1−p缩放(或训练时用“倒置Dropout”,测试时不缩放)。
核心参数:ppp(失活概率,通常取0.2~0.5)。
(2)语法格式(TensorFlow/Keras)
from tensorflow.keras.layers import Dropout
model = Sequential([
Dense(64, activation='relu', input_shape=(8,)),
Dropout(0.3), # 30%的神经元失活
Dense(32, activation='relu'),
Dropout(0.2), # 20%的神经元失活
Dense(1)
])
model.compile(optimizer='adam', loss='mse')
model.fit(X_train_scaled, y_train, epochs=50, validation_data=(X_test_scaled, y_test))
(3)案例:对比有无Dropout的神经网络
# 无Dropout
model_no_dropout = Sequential([
Dense(128, activation='relu', input_shape=(8,)),
Dense(64, activation='relu'),
Dense(1)
])
model_no_dropout.compile(optimizer='adam', loss='mse')
history_no_drop = model_no_dropout.fit(
X_train_scaled, y_train, epochs=50, validation_data=(X_test_scaled, y_test)
)
# 有Dropout
model_dropout = Sequential([
Dense(128, activation='relu', input_shape=(8,)),
Dropout(0.3),
Dense(64, activation='relu'),
Dropout(0.2),
Dense(1)
])
model_dropout.compile(optimizer='adam', loss='mse')
history_drop = model_dropout.fit(
X_train_scaled, y_train, epochs=50, validation_data=(X_test_scaled, y_test)
)
# 可视化
plt.plot(history_no_drop.history['val_loss'], label='无Dropout-验证损失')
plt.plot(history_drop.history['val_loss'], label='有Dropout-验证损失')
plt.xlabel('Epoch')
plt.ylabel('MSE')
plt.legend()
plt.show()
(4)优缺点
| 优点 | 缺点 |
|---|---|
| 简单有效,大幅降低神经网络过拟合 | 仅适用于神经网络 |
| 训练时相当于训练多个子模型,泛化能力强 | 需调参(失活概率p);测试时需缩放输出 |
2. Batch Normalization(批量归一化)
(1)原理
对每层神经网络的输入进行标准化(均值=0,方差=1),并引入可学习参数(缩放因子γ\gammaγ、偏移因子β\betaβ),加速训练收敛,同时降低过拟合风险(减少内部协变量偏移)。
(2)语法格式(TensorFlow/Keras)
from tensorflow.keras.layers import BatchNormalization
model = Sequential([
Dense(64, input_shape=(8,)),
BatchNormalization(), # 批量归一化层(在激活函数前/后均可,通常在激活前)
Activation('relu'),
Dense(32),
BatchNormalization(),
Activation('relu'),
Dense(1)
])
(3)优缺点
| 优点 | 缺点 |
|---|---|
| 加速训练收敛(可使用更高学习率) | 增加模型参数和计算量 |
| 降低过拟合,减少对Dropout的依赖 | 小批量数据下效果不稳定 |
| 减轻对权重初始化的敏感 |
八、常用正则化方法总结表
| 方法类别 | 具体方法 | 核心思想 | 适用模型 | 工具库/语法关键词 |
|---|---|---|---|---|
| 参数正则化 | L2(Ridge) | 惩罚权重平方和 | 线性模型、神经网络 | scikit-learn.Ridge、PyTorch.weight_decay |
| 参数正则化 | L1(Lasso) | 惩罚权重绝对值和 | 线性模型、高维数据 | scikit-learn.Lasso |
| 参数正则化 | ElasticNet | 结合L1和L2 | 高维、特征相关数据 | scikit-learn.ElasticNet |
| 训练过程 | 早停(Early Stopping) | 监控验证性能,提前停止 | 神经网络、SGD | Keras.callbacks.EarlyStopping |
| 训练过程 | 权重衰减 | 优化器中惩罚权重 | 神经网络 | PyTorch.optim.SGD(weight_decay) |
| 数据增强 | 数据扩充 | 变换原始数据生成新样本 | 图像、文本、小数据 | Keras.ImageDataGenerator |
| 数据增强 | 交叉验证 | 多折训练验证,评估稳定性 | 所有模型 | scikit-learn.cross_val_score |
| 集成学习 | 随机森林(Bagging) | 并行训练多棵树,平均结果 | 分类、回归、非线性数据 | scikit-learn.RandomForestRegressor |
| 集成学习 | XGBoost(Boosting) | 串行纠正错误,加权融合 | 分类、回归、高维数据 | xgboost.XGBRegressor |
| 集成学习 | Stacking | 基模型预测作为新特征,元模型融合 | 所有模型 | scikit-learn.StackingRegressor |
| 神经网络专用 | Dropout | 随机失活神经元 | 神经网络 | Keras.layers.Dropout |
| 神经网络专用 | BatchNormalization | 层输入标准化 | 神经网络 | Keras.layers.BatchNormalization |
九、正则化方法选择原则
-
看模型类型:
- 线性模型(回归/分类):优先L2(Ridge)→ 需特征选择用L1(Lasso)→ 特征相关用ElasticNet;
- 神经网络:Dropout + BatchNormalization + 早停 + 权重衰减;
- 非线性模型(决策树):随机森林(Bagging)→ 需更高精度用XGBoost(Boosting)→ 追求极致性能用Stacking。
-
看数据特点:
- 数据量小:数据扩充 + 交叉验证 + 简单模型(如Ridge);
- 高维稀疏数据:L1(Lasso)/ElasticNet + 随机森林;
- 特征高度相关:ElasticNet + XGBoost(colsample_bytree);
- 图像/文本数据:数据扩充 + 神经网络(Dropout/BatchNorm)。
-
看业务需求:
- 模型可解释性:L1(特征选择)→ 线性模型 → 随机森林(特征重要性);
- 训练速度:随机森林(并行)→ L2 → XGBoost(GPU加速);
- 预测精度:XGBoost → Stacking → 神经网络(调优后)。
十、常见误区
- 正则化能解决所有过拟合:错误!若数据噪声过大或特征与标签无关,正则化效果有限,需先优化数据质量;
- λ\lambdaλ 越大越好:错误!λ\lambdaλ 过大会导致欠拟合(模型过于简单),需通过交叉验证选择最优λ\lambdaλ;
- 树模型不需要正则化:错误!随机森林(max_depth)、XGBoost(reg_alpha/reg_lambda)均有正则化参数,需调参避免过拟合;
- 数据扩充对结构化数据有效:错误!结构化数据(如表格数据)的变换易改变语义,效果远不如图像/文本数据。
通过以上系统梳理,你可以根据具体场景灵活选择和组合正则化方法,核心是“平衡模型复杂度与泛化能力”,避免过度追求训练集性能而忽视实际应用效果。
2370

被折叠的 条评论
为什么被折叠?



