1. 什么是L1正则化和L2正则化?
1.1. L1正则化
1.2. L2正则化
2. 正则化在训练过程中的作用
2.1 适用的问题和数据类型
2.1.1. L1正则化
2.1.2. L2正则化
3. L1正则化和L2正则化的数学原理
3.1. 带L1正则化的损失函数
3.2. 带L2正则化的损失函数
4. L1正则化和L2正则化的Python实现
4.1. L1正则化的Python实现
4.2. L2正则化的Python实现
5. 比较L1正则化和L2正则化
在机器学习中,过拟合是一个常见的问题。过拟合指的是模型在训练数据上表现良好,但在新数据上的表现较差。为了防止过拟合,我们通常会使用正则化技术。正则化通过向损失函数中添加一个惩罚项,迫使模型参数保持较小的值,从而减少过拟合。最常见的两种正则化技术是L1正则化和L2正则化。
什么是L1正则化和L2正则化?
L1正则化
L1正则化,又称为Lasso正则化,其惩罚项是模型参数的绝对值之和。数学上,可以表示为:
L1 Regularization term = λ ∑ i ∣ w i ∣ \text{L1 Regularization term} = \lambda \sum_{i} |w_i| L1 Regularization term=λ∑i∣wi∣
其中, λ \lambda λ 是正则化强度的超参数, w i w_i wi 是模型的参数。L1正则化的一个重要特性是它会产生稀疏模型,即一些权重参数会被驱动为零,这对于特征选择非常有用。
L2正则化
L2正则化,又称为Ridge正则化,其惩罚项是模型参数的平方和。数学上,可以表示为:
L2 Regularization term = λ ∑ i w i 2 \text{L2 Regularization term} = \lambda \sum_{i} w_i^2 L2 Regularization term=λ∑iwi2
同样地, λ \lambda λ是正则化强度的超参数, w i w_i wi 是模型的参数。L2正则化的一个重要特性是它会产生平滑的模型,使得所有权重参数都尽可能小,但不会完全为零。
正则化在训练过程中的作用
正则化发生在模型的训练阶段。具体来说,当我们最小化损失函数时,会同时最小化正则化项。这样可以控制模型的复杂度,防止过拟合。我们通过调整正则化强度参数 λ \lambda λ 来平衡数据拟合程度和正则化惩罚项。
适用的问题和数据类型
L1正则化
L1正则化适用于以下情况:
- 特征选择:由于L1正则化会产生稀疏模型,它能自动选择特征,将不重要的特征权重变为零。
- 高维数据:在特征数量远多于样本数量的情况下,L1正则化可以帮助筛选出重要特征。
L2正则化
L2正则化适用于以下情况:
- 多重共线性:当特征之间存在高度相关性时,L2正则化可以通过平滑权重来减小这种影响。
- 一般回归问题:在特征数量与样本数量差不多时,L2正则化可以有效地控制模型复杂度。
L1正则化和L2正则化的数学原理
假设我们有一个线性回归模型,损失函数是均方误差(MSE)。
不加入正则化项前的损失函数比可以表示为:
y ^ ( i ) = w i ∗ x i + b \hat{y}^{(i)} = w_i*x_i+b y^(i)=wi∗xi+b
J ( w ) = 1 2 m ∑ i = 1 m ( y ( i ) − y ^ ( i ) ) 2 J(w) = \frac{1}{2m} \sum_{i=1}^{m} (y^{(i)} - \hat{y}^{(i)})^2 J(w)=2m1∑i=1m(y(i)−y^(i))2
加入正则化项后的损失函数可以表示为:
带L1正则化的损失函数
J ( w ) = 1 2 m ∑ i = 1 m ( y ( i ) − y ^ ( i ) ) 2 + λ ∑ j = 1 n ∣ w j ∣ J(w) = \frac{1}{2m} \sum_{i=1}^{m} (y^{(i)} - \hat{y}^{(i)})^2 + \lambda \sum_{j=1}^{n} |w_j| J(w)=2m1∑i=1m(y(i)−y^(i))2+λ∑j=1n∣wj∣
带L2正则化的损失函数
J ( w ) = 1 2 m ∑ i = 1 m ( y ( i ) − y ^ ( i ) ) 2 + λ ∑ j = 1 n w j 2 J(w) = \frac{1}{2m} \sum_{i=1}^{m} (y^{(i)} - \hat{y}^{(i)})^2 + \lambda \sum_{j=1}^{n} w_j^2 J(w)=2m1∑i=1m(y(i)−y^(i))2+λ∑j=1nwj2
其中, m m m 是样本数量, y ( i ) y^{(i)} y(i) 是第 i i i个样本的真实值, y ^ ( i ) \hat{y}^{(i)} y^(i)是第 i i i个样本的预测值, w j w_j wj是第 j j j个特征的权重参数, λ \lambda λ 是正则化强度。
L1正则化和L2正则化的Python实现
接下来,我们将通过Python代码展示如何在实际中应用L1正则化和L2正则化。我们将使用常见的机器学习库 scikit-learn
。
4.1 L1正则化的Python实现
我们以线性回归为例,展示如何使用L1正则化。
import numpy as np
from sklearn.linear_model import Lasso
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
# 生成示例数据
np.random.seed(42)
X = np.random.randn(100, 10)
y = X @ np.random.randn(10) + np.random.randn(100)
# @表示矩阵乘法,这段的意思是X乘以初始化权重np.random.randn(10)然后再加上噪音
# 拆分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建Lasso回归模型
lasso = Lasso(alpha=0.1)
# 训练模型
lasso.fit(X_train, y_train)
# 预测
y_pred_train = lasso.predict(X_train)
y_pred_test = lasso.predict(X_test)
# 计算训练误差和测试误差
train_mse = mean_squared_error(y_train, y_pred_train)
test_mse = mean_squared_error(y_test, y_pred_test)
print(f'Train MSE: {train_mse}')
print(f'Test MSE: {test_mse}')
print(f'Lasso coefficients: {lasso.coef_}')
手写L1正则化
class LassoRegression:
def __init__(self, learning_rate=0.01, n_iterations=1000, lambda_=0.1):
self.learning_rate = learning_rate
self.n_iterations = n_iterations
self.lambda_ = lambda_
def fit(self, X, y):
self.m, self.n = X.shape
self.weights = np.zeros(self.n)
self.bias = 0
for _ in range(self.n_iterations):
y_pred = self.predict(X)
dw = (-2 * X.T @ (y - y_pred) + self.lambda_ * np.sign(self.weights)) / self.m
db = -2 * np.sum(y - y_pred) / self.m
self.weights -= self.learning_rate * dw
self.bias -= self.learning_rate * db
def predict(self, X):
return X @ self.weights + self.bias
4.2. L2正则化的Python实现
我们同样以线性回归为例,展示如何使用L2正则化(岭回归)。
import numpy as np
from sklearn.linear_model import Ridge
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
# 生成示例数据
np.random.seed(42)
X = np.random.randn(100, 10)
y = X @ np.random.randn(10) + np.random.randn(100)
# 拆分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建Ridge回归模型
ridge = Ridge(alpha=0.1)
# 训练模型
ridge.fit(X_train, y_train)
# 预测
y_pred_train = ridge.predict(X_train)
y_pred_test = ridge.predict(X_test)
# 计算训练误差和测试误差
train_mse = mean_squared_error(y_train, y_pred_train)
test_mse = mean_squared_error(y_test, y_pred_test)
print(f'Train MSE: {train_mse}')
print(f'Test MSE: {test_mse}')
print(f'Ridge coefficients: {ridge.coef_}')
手写L2正则化
class RidgeRegression:
def __init__(self, learning_rate=0.01, n_iterations=1000, lambda_=0.1):
self.learning_rate = learning_rate
self.n_iterations = n_iterations
self.lambda_ = lambda_
def fit(self, X, y):
self.m, self.n = X.shape
self.weights = np.zeros(self.n)
self.bias = 0
for _ in range(self.n_iterations):
y_pred = self.predict(X)
dw = (-2 * X.T @ (y - y_pred) + 2 * self.lambda_ * self.weights) / self.m
db = -2 * np.sum(y - y_pred) / self.m
self.weights -= self.learning_rate * dw
self.bias -= self.learning_rate * db
def predict(self, X):
return X @ self.weights + self.bias
5. 比较L1正则化和L2正则化
L1正则化和L2正则化各有优缺点:
-
L1正则化:
- 优点:产生稀疏模型,有助于特征选择。
- 缺点:当相关特征较多时,Lasso选择其中一个而忽略其他的。
-
L2正则化:
- 优点:权重分布更平滑,适合处理特征之间有相似性。
- 缺点:不能产生稀疏模型。
在实际应用中,可以通过交叉验证选择最合适的正则化方法和超参数。