在介绍正则化之前,先介绍几个概念:
1. 过拟合(Overfitting)
过拟合是指模型在训练集上表现得非常好,但在测试集上表现不佳。这通常是因为模型学习到了训练数据中的噪声和不必要的细节,导致模型在新数据上的泛化能力下降。
主要表现:
- 训练误差低,但测试误差高。
- 预测结果对训练数据的微小变化非常敏感。
解决过拟合的方法:
- 正则化:使用 L1、L2 正则化或 Dropout 降低模型复杂度。
- 增加数据量:使用数据增强或收集更多样本。
- 简化模型:减少模型的层数、神经元数或选择更简单的模型。
2. 欠拟合(Underfitting)
欠拟合是指模型在训练集和测试集上都表现不佳,无法很好地捕捉数据的模式或趋势。这通常是因为模型的复杂度不够,无法学习到数据中的有效特征。
主要表现:
- 训练误差和测试误差都较高。
- 模型无法充分捕捉数据特征,预测结果较为简单,无法反映数据的实际趋势。
解决欠拟合的方法:
- 增加模型复杂度:增加模型层数、神经元数,或选择更复杂的模型。
- 增加特征:从数据中提取更多有效特征(如多项式特征)。
- 增加训练轮数:多训练几轮,确保模型充分学习到数据模式。
下图展示一个简单的回归问题,欠拟合、适度拟合和过拟合三种模型在数据上的表现:
- Degree=1(欠拟合):模型的复杂度过低,无法很好地捕捉数据的非线性特征。
- Degree=3(适度拟合):模型较好地拟合了数据的趋势,误差较低。
- Degree=15(过拟合):模型在训练数据上拟合得很好,但曲线波动大,对新数据的泛化能力差。
接下来介绍正则化。
正则化是一种用于防止机器学习模型过拟合的技术。正则化通过在损失函数中加入额外的惩罚项,使得模型更简单且泛化能力更强,避免在训练集上表现很好而在测试集上表现不佳的情况。常见的正则化方法有 L1 正则化、L2 正则化 和 Dropout。
1. L1 正则化
L1 正则化(也叫 Lasso 正则化)会在损失函数中增加一个与权重绝对值成正比的惩罚项,使得模型倾向于让某些权重变为零,从而实现特征选择的效果。
优点:
使部分权重变为零,达到稀疏特征选择的效果。
可以用来理解哪些特征对模型预测最重要。
Python 实现:
from sklearn.linear_model import Lasso
lasso_model = Lasso(alpha=0.1) # alpha 代表 λ
lasso_model.fit(X_train, y_train)
2. L2 正则化
L2 正则化(也叫 Ridge 正则化)在损失函数中加入权重平方的惩罚项。这种方法不会将权重变成零,但会使其尽可能接近零,从而使模型更平滑。
优点:
有效减少模型的复杂度。
对于多重共线性的特征有良好的控制效果。
Python 实现:
from sklearn.linear_model import Ridge
ridge_model = Ridge(alpha=0.1) # alpha 代表 λ
ridge_model.fit(X_train, y_train)
3. Elastic Net
Elastic Net 是 L1 和 L2 正则化的结合,可以根据需要平衡稀疏性和稳定性。Elastic Net 的损失函数包含了 L1 和 L2 惩罚项,公式如下:
Python 实现:
from sklearn.linear_model import ElasticNet
elastic_net_model = ElasticNet(alpha=0.1, l1_ratio=0.5) # l1_ratio 代表 ρ
elastic_net_model.fit(X_train, y_train)
4. Dropout 正则化
Dropout是一种适用于神经网络的正则化方法,它通过在训练过程中随机“丢弃”一部分神经元(即将其输出设置为零)来防止过拟合。测试时将所有神经元的输出乘以一个比例因子,以保持训练和测试的一致性。这样模型不会过于依赖某些特定的神经元,提高了模型的泛化能力。
Python 实现:
from tensorflow.keras.models import Sequential
# 从tensorflow.keras.layers导入Dense和Dropout层
from tensorflow.keras.layers import Dense, Dropout
# 创建一个Sequential模型实例
model = Sequential([
# 添加第一个全连接层(Dense层),有64个神经元,激活函数为ReLU,input_shape代表输入数据的形状 例如(784,)对于28x28的图像数据
Dense(64, activation='relu', input_shape=(input_shape,)),
# 添加Dropout层,用于减少过拟合,丢弃率为50%,即在训练过程中随机丢弃一半的神经元
Dropout(0.5),
# 添加第二个全连接层,有64个神经元,激活函数同样为ReLU
Dense(64, activation='relu'),
# 再次添加Dropout层,丢弃率仍为50%
Dropout(0.5),
# 添加输出层,这是一个全连接层,但只有1个神经元,通常用于回归任务 对于回归问题,默认是线性激活
Dense(1)
])
# 编译模型,指定优化器为Adam,损失函数为均方误差(MSE),这通常用于回归任务
model.compile(optimizer='adam', loss='mse')
5. 数据正则化
虽然严格来说不属于正则化项,但标准化或归一化数据可以减少模型过拟合的可能性,帮助模型更稳定地收敛。常用的包括 标准化(Standardization) 和 归一化(Normalization)。标准化将数据缩放为均值为 0、标准差为 1,归一化则将数据缩放到特定区间(通常是 [0, 1] 或 [-1, 1])。
Python 实现:
# 从sklearn.preprocessing模块导入StandardScaler和MinMaxScaler类
from sklearn.preprocessing import StandardScaler, MinMaxScaler
# 标准化
scaler = StandardScaler() # StandardScaler用于将特征缩放到均值为0,标准差为1的分布上
X_train_scaled = scaler.fit_transform(X_train) # 使用fit_transform方法对训练数据X_train进行拟合和转换
# 归一化
scaler = MinMaxScaler() # MinMaxScaler用于将特征缩放到给定的最小值和最大值之间(通常是0和1)
X_train_normalized = scaler.fit_transform(X_train)
6.早停法 (Early Stopping)
早停法在训练过程中监测验证集误差,当验证误差不再减少时提前停止训练。这样可以防止模型在训练集上过度拟合,帮助模型达到更好的泛化效果。
优点:
实现简单,只需在验证集上检测误差变化。
不增加额外的惩罚项,直接通过优化训练步骤控制过拟合。
Python 实现:
from tensorflow.keras.callbacks import EarlyStopping
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
# 构建简单神经网络
model = Sequential([
Dense(64, activation='relu', input_shape=(input_shape,)),
Dense(64, activation='relu'),
Dense(1)
])
model.compile(optimizer='adam', loss='mse', metrics=['mae'])
# 使用早停法
early_stopping = EarlyStopping(
monitor='val_loss', # 监测验证集损失
patience=5, # 容忍验证集损失连续5次无改善
restore_best_weights=True
)
# 训练模型
history = model.fit(
X_train, y_train,
epochs=100,
validation_data=(X_val, y_val),
callbacks=[early_stopping]
)
7. 数据增强 (Data Augmentation)
数据增强通过生成新的数据样本来扩大数据集的大小,帮助模型提升泛化能力。例如,在图像分类中可以通过旋转、翻转、缩放等操作生成新的图像样本,从而减少模型的过拟合风险。通常用于计算机视觉任务。
优点:
增加数据集多样性,有助于模型学习更丰富的特征。
不依赖于模型结构,可与其他正则化方法组合使用。
Python 实现:
from tensorflow.keras.preprocessing.image import ImageDataGenerator
# 定义数据增强参数
datagen = ImageDataGenerator(
rotation_range=40, # 随机旋转角度
width_shift_range=0.2, # 随机水平平移
height_shift_range=0.2, # 随机竖直平移
shear_range=0.2, # 随机错切变换
zoom_range=0.2, # 随机缩放
horizontal_flip=True, # 随机水平翻转
fill_mode='nearest' # 填充方式
)
# 将增强的数据传入模型
train_generator = datagen.flow(X_train, y_train, batch_size=32)
model.fit(train_generator, epochs=50)
8. 批量归一化(Batch Normalization)
批量归一化通过在网络的每一层加入一个归一化步骤,将数据标准化为均值为0、方差为1的分布。公式如下:
Python 实现:
from tensorflow.keras.layers import BatchNormalization
model = Sequential([
Dense(64, input_shape=(input_shape,), activation='relu'),
BatchNormalization(), # 添加批量归一化层
Dense(64, activation='relu'),
BatchNormalization(),
Dense(1)
])
model.compile(optimizer='adam', loss='mse')
最后,用一个多项式回归模型来拟合带有噪声的二次函数。为了展示过拟合和正则化的效果,用 15 阶多项式拟合数据并对比无正则化与正则化模型的结果。以下是代码:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.metrics import mean_squared_error
# 生成示例数据:二次曲线加噪声
np.random.seed(42)
X = np.sort(5 * np.random.rand(20, 1), axis=0) # 输入范围为 [0, 5] 的随机点
y = 2 * X**2 + X + 3 + np.random.randn(20, 1) # y = 2x^2 + x + 3 加上噪声
# 创建高阶多项式特征
poly_features = PolynomialFeatures(degree=15) # 15阶多项式会导致过拟合
X_poly = poly_features.fit_transform(X)
# 普通回归模型(容易过拟合)
model_no_reg = LinearRegression()
model_no_reg.fit(X_poly, y)
# 带 L2 正则化的回归模型(Ridge 回归)
model_with_reg = Ridge(alpha=1) # alpha 是正则化强度,值越大正则化越强
model_with_reg.fit(X_poly, y)
# 生成测试数据
X_test = np.linspace(0, 5, 100).reshape(-1, 1)
X_test_poly = poly_features.transform(X_test) # 将测试数据转换为多项式特征
y_pred_no_reg = model_no_reg.predict(X_test_poly) # 无正则化模型的预测结果
y_pred_with_reg = model_with_reg.predict(X_test_poly) # 正则化模型的预测结果
# 绘制结果
plt.figure(figsize=(12, 6))
# 绘制训练数据和真实曲线
plt.scatter(X, y, color="blue", label="Training data")
plt.plot(X_test, 2 * X_test**2 + X_test + 3, color="green", linestyle="--", label="True function")
# 绘制无正则化模型预测曲线(容易过拟合)
plt.plot(X_test, y_pred_no_reg, color="red", label="Prediction without Regularization")
# 绘制带 L2 正则化模型预测曲线(缓解过拟合)
plt.plot(X_test, y_pred_with_reg, color="purple", label="Prediction with L2 Regularization")
# 图例和标题
plt.xlabel("X")
plt.ylabel("y")
plt.title("Overfitting and Regularization in Polynomial Regression")
plt.legend()
plt.show()
# 计算和输出训练误差(均方误差)
mse_no_reg = mean_squared_error(y, model_no_reg.predict(X_poly))
mse_with_reg = mean_squared_error(y, model_with_reg.predict(X_poly))
print("Mean Squared Error without Regularization:", mse_no_reg)
print("Mean Squared Error with L2 Regularization:", mse_with_reg)
输出结果
结果分析
在图中,可以看到:
- 红色曲线(无正则化)在训练数据上完全拟合,表现出过拟合特性。
- 紫色曲线(带正则化)更平滑,避免了过度拟合,符合数据的真实趋势。
别忘了给这篇文章点个赞哦,非常感谢。我也正处于学习的过程,如果有问题,欢迎在评论区留言讨论,一起学习!
标签:模型,正则,train,拟合,序列,model,reg From: https://blog.csdn.net/qq_47885795/article/details/142984261