【机器学习】4.正则化

机器学习正则化完全指南:方法、语法、案例与表格

一、正则化核心基础

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=1nwi2wiw_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=1nwi

(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=λ1wi+λ2wi2
或等价形式(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+(1l1_ratio)×0.5wi2]

  • 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\sumw_i$部分权重=0
ElasticNet$\alpha[l1_ratio\sumw_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 LL 损失梯度)

(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-1k1个子集训练,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-p1p缩放(或训练时用“倒置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)监控验证性能,提前停止神经网络、SGDKeras.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

九、正则化方法选择原则

  1. 看模型类型

    • 线性模型(回归/分类):优先L2(Ridge)→ 需特征选择用L1(Lasso)→ 特征相关用ElasticNet;
    • 神经网络:Dropout + BatchNormalization + 早停 + 权重衰减;
    • 非线性模型(决策树):随机森林(Bagging)→ 需更高精度用XGBoost(Boosting)→ 追求极致性能用Stacking。
  2. 看数据特点

    • 数据量小:数据扩充 + 交叉验证 + 简单模型(如Ridge);
    • 高维稀疏数据:L1(Lasso)/ElasticNet + 随机森林;
    • 特征高度相关:ElasticNet + XGBoost(colsample_bytree);
    • 图像/文本数据:数据扩充 + 神经网络(Dropout/BatchNorm)。
  3. 看业务需求

    • 模型可解释性:L1(特征选择)→ 线性模型 → 随机森林(特征重要性);
    • 训练速度:随机森林(并行)→ L2 → XGBoost(GPU加速);
    • 预测精度:XGBoost → Stacking → 神经网络(调优后)。

十、常见误区

  1. 正则化能解决所有过拟合:错误!若数据噪声过大或特征与标签无关,正则化效果有限,需先优化数据质量;
  2. λ\lambdaλ 越大越好:错误!λ\lambdaλ 过大会导致欠拟合(模型过于简单),需通过交叉验证选择最优λ\lambdaλ
  3. 树模型不需要正则化:错误!随机森林(max_depth)、XGBoost(reg_alpha/reg_lambda)均有正则化参数,需调参避免过拟合;
  4. 数据扩充对结构化数据有效:错误!结构化数据(如表格数据)的变换易改变语义,效果远不如图像/文本数据。

通过以上系统梳理,你可以根据具体场景灵活选择和组合正则化方法,核心是“平衡模型复杂度与泛化能力”,避免过度追求训练集性能而忽视实际应用效果。

正则化技术是机器学习和深度学习中的关键方法之一,旨在通过控制模型的复杂度来提升其泛化能力。具体来说,正则化通常通过在损失函数中引入惩罚项来限制模型参数的大小或结构,从而防止过拟合现象的发生[^1]。 ### 正则化的基本概念 正则化的核心思想是遵循奥卡姆剃刀定律,即“最简单的模型是最好的”。这意味着在满足数据拟合需求的同时,应尽可能保持模型的简洁性。这种技术不仅有助于减少模型对训练数据的过度依赖,还能增强模型对新数据的适应能力[^2]。 ### 常见的正则化方法 #### L1正则化(Lasso) L1正则化通过向损失函数添加一个与权重绝对值成比例的项来实现正则化效果。这种方法能够产生稀疏的权重矩阵,使得许多权重接近于零,从而实现了特征选择的功能。L1正则化适用于高维稀疏数据集,例如文本分类任务中[^4]。 #### L2正则化(Ridge) L2正则化则是通过向损失函数中加入与权重平方成比例的一项来进行调整。这种方式可以得到非零但趋近于零的平滑权重分布,对于特征之间存在多重共线性的场景特别有效,比如经济指标预测或者基因数据分析等场景[^4]。 #### 弹性网络(Elastic Net) 弹性网络结合了L1和L2正则化的优点,它同时包含了两种类型的惩罚项。这种方法尤其适合于特征维度远大于样本量的情况,并且能够在进行特征选择的同时保留一些重要但弱相关的特征[^4]。 #### Dropout Dropout是一种专门针对神经网络设计的技术,在训练过程中随机忽略一部分神经元连接,以此降低模型的复杂度并提高其泛化性能。这种方法简单有效,已成为现代深度学习架构的标准组件之一[^1]。 #### Batch Normalization Batch Normalization通过对每一层输入进行标准化处理来加速训练过程并改善梯度传播问题。虽然主要目的是加快收敛速度,但它也具有一定的正则化作用,因为它减少了内部协变量偏移的影响。 ### 应用场景 - **优先选择L1的场景**:当特征维度远超过样本数量时,如自然语言处理中的词向量表示;需要明确了解每个特征贡献度的应用领域,如金融风险评估。 - **优先选择L2的场景**:特征间存在显著相关性的案例,如医疗诊断中的血液指标分析;要求模型输出结果连续稳定的场合,例如图像超分辨率重建任务[^4]。 综上所述,正则化技术不仅解决了过拟合问题,还促进了更稳健、更具解释性的模型构建。根据实际问题的特点合理选用合适的正则化策略,可以极大地提升模型的表现力和实用性。 ```python # 示例代码展示如何使用Scikit-Learn库中的Lasso回归 from sklearn.linear_model import Lasso # 初始化Lasso回归模型,alpha为正则化强度参数 lasso = Lasso(alpha=0.1) # 假设X_train, y_train分别为训练数据及其标签 # lasso.fit(X_train, y_train) # 注释掉以避免执行真实的数据拟合操作 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值