【机器学习】正则化的基本概念以及正则化成本和梯度的示例

引言

在机器学习中,正则化(Regularization)是一种技术,用于减少模型复杂度,防止过拟合,并提高模型的泛化能力。通过在损失函数中添加一个额外的惩罚项,正则化鼓励模型学习更简单、更平滑的函数,从而在未见过的数据上表现得更好

一、正则化

1.1 正则化的形式

1.1.1 L1 正则化(Lasso 回归)

  • 惩罚项: λ ∑ j = 1 n ∣ w j ∣ \lambda \sum_{j=1}^{n} |w_j| λj=1nwj
  • 效果:不仅减少模型复杂度,还能实现特征选择,自动缩小权重

1.1.2 L2 正则化(Ridge 回归)

  • 惩罚项: λ ∑ j = 1 n w j 2 \lambda \sum_{j=1}^{n} w_j^2 λj=1nwj2
  • 效果:减少模型复杂度,但不自动缩小权重

1.1.3 Elastic Net 正则化

  • 惩罚项: λ ( α ∑ j = 1 n ∣ w j ∣ + ( 1 − α ) ∑ j = 1 n w j 2 ) \lambda \left( \alpha \sum_{j=1}^{n} |w_j| + (1 - \alpha) \sum_{j=1}^{n} w_j^2 \right) λ(αj=1nwj+(1α)j=1nwj2)
  • 效果:结合了 L1 和 L2 正则化的优点,可以实现特征选择和减少模型复杂度

1.2 正则化的优点

1.2.1 防止过拟合

通过减少模型复杂度,正则化有助于模型在未见过的数据上表现得更好

1.2.1 特征选择

某些类型的正则化(如 Lasso)可以自动缩小权重,从而实现特征选择

1.2.1 参数稳定性

正则化有助于避免模型对噪声的敏感性,提高参数的稳定性

1.3 正则化的缺点

1.3.1 增加模型复杂度

正则化需要额外的参数(如 lambda),这可能会增加模型的复杂度

1.3.2 参数选择

正则化参数(如 lambda)的选择对模型的性能有很大影响,需要通过交叉验证等方法来确定最佳值

在实际应用中,正则化是一种非常有效的技术,可以显著提高机器学习模型的性能。

二、正则化成本和梯度

2.1 目标

  • 将先前的线性回归和对数几率回归的成本函数扩展一个正则化项
  • 在添加了正则化项后,重新运行之前过拟合的示例
import numpy as np
%matplotlib widget
import matplotlib.pyplot as plt
from plt_overfit import overfit_example, output
from lab_utils_common import sigmoid
np.set_printoptions(precision=8)

2.2 添加正则化

在这里插入图片描述

上图展示了线性回归和对数几率回归的成本和梯度函数

注意:

  • 成本:线性回归和对数几率回归的成本函数有显著差异,但向方程中添加正则化的方式是相同的
  • 梯度:线性回归和对数几率回归的梯度函数非常相似。它们仅在实现 𝑓𝑤𝑏 时有所不同

2.3带有正则化的成本函数

2.3.1 正则化线性回归的成本函数

正则化线性回归的成本函数方程为:
J ( w , b ) = 1 2 m ∑ i = 0 m − 1 ( f w , b ( x ( i ) ) − y ( i ) ) 2 + λ 2 m ∑ j = 0 n − 1 w j 2 J(\mathbf{w}, b) = \frac{1}{2m} \sum_{i=0}^{m-1} (f_{\mathbf{w}, b}(\mathbf{x}^{(i)}) - y^{(i)})^2 + \frac{\lambda}{2m} \sum_{j=0}^{n-1} w_j^2 J(w,b)=2m1i=0m1(fw,b(x(i))y(i))2+2mλj=0n1wj2
其中:
f w , b ( x ( i ) ) = w ⋅ x ( i ) + b f_{\mathbf{w}, b}(\mathbf{x}^{(i)}) = \mathbf{w} \cdot \mathbf{x}^{(i)} + b fw,b(x(i))=wx(i)+b
与之前实验中实现的没有正则化的成本函数相比,该函数的形式为:
J ( w , b ) = 1 2 m ∑ i = 0 m − 1 ( f w , b ( x ( i ) ) − y ( i ) ) 2 J(\mathbf{w}, b) = \frac{1}{2m} \sum_{i=0}^{m-1} (f_{\mathbf{w}, b}(\mathbf{x}^{(i)}) - y^{(i)})^2 J(w,b)=2m1i=0m1(fw,b(x(i))y(i))2

  • 不同之处在于正则化项,即 λ 2 m ∑ j = 0 n − 1 w j 2 \frac{\lambda}{2m} \sum_{j=0}^{n-1} w_j^2 2mλj=0n1wj2

包含这个项可以激励梯度下降最小化参数的大小

注意,在这个例子中,参数 b b b没有被正则化,这是标准做法

下面是方程(1)和(2)的实现,对所有 m 个示例进行 for 循环

def compute_cost_linear_reg(X, y, w, b, lambda_ = 1):
    """
    计算所有示例的成本
    参数:
      X (ndarray (m,n)):数据,m 个示例,每个示例有 n 个特征
      y (ndarray (m,)):目标值
      w (ndarray (n,)):模型参数  
      b (scalar)       :模型参数
      lambda_ (scalar) :控制正则化量
    返回:
      total_cost (scalar):成本 
    """
    m  = X.shape[0]
    n  = len(w)
    cost = 0.
    for i in range(m):
        f_wb_i = np.dot(X[i], w) + b                                   #(n,)(n,)=scalar, see np.dot
        cost = cost + (f_wb_i - y[i])**2                               #scalar             
    cost = cost / (2 * m)                                              #scalar  
 
    reg_cost = 0
    for j in range(n):
        reg_cost += (w[j]**2)                                          #scalar
    reg_cost = (lambda_/(2*m)) * reg_cost                              #scalar
    
    total_cost = cost + reg_cost                                       #scalar
    return total_cost                                                  #scalar

运行下面的代码以查看它的效果

np.random.seed(1)
X_tmp = np.random.rand(5,6)
y_tmp = np.array([0,1,0,1,0])
w_tmp = np.random.rand(X_tmp.shape[1]).reshape(-1,)-0.5
b_tmp = 0.5
lambda_tmp = 0.7
cost_tmp = compute_cost_linear_reg(X_tmp, y_tmp, w_tmp, b_tmp, lambda_tmp)
print("Regularized cost:", cost_tmp)

输出结果:
在这里插入图片描述
预期输出:
正则化成本: 0.07917239320214275

2.3 正则化逻辑回归的成本函数

对于正则化逻辑回归,成本函数的形式为
J ( w , b ) = 1 m ∑ i = 0 m − 1 [ − y ( i ) log ⁡ ( f w , b ( x ( i ) ) ) − ( 1 − y ( i ) ) log ⁡ ( 1 − f w , b ( x ( i ) ) ) ] + λ 2 m ∑ j = 0 n − 1 w j 2 J(\mathbf{w}, b) = \frac{1}{m} \sum_{i=0}^{m-1} [-y^{(i)} \log(f_{\mathbf{w}, b}(\mathbf{x}^{(i)})) - (1 - y^{(i)}) \log(1 - f_{\mathbf{w}, b}(\mathbf{x}^{(i)}))] + \frac{\lambda}{2m} \sum_{j=0}^{n-1} w_j^2 J(w,b)=m1i=0m1[y(i)log(fw,b(x(i)))(1y(i))log(1fw,b(x(i)))]+2mλj=0n1wj2
其中:
f w , b ( x ( i ) ) = σ ( w ⋅ x ( i ) + b ) f_{\mathbf{w}, b}(\mathbf{x}^{(i)}) = \sigma(\mathbf{w} \cdot \mathbf{x}^{(i)} + b) fw,b(x(i))=σ(wx(i)+b)
与之前实验中实现的没有正则化的成本函数相比,该函数的形式为:
J ( w , b ) = 1 m ∑ i = 0 m − 1 [ − y ( i ) log ⁡ ( f w , b ( x ( i ) ) ) − ( 1 − y ( i ) ) log ⁡ ( 1 − f w , b ( x ( i ) ) J(\mathbf{w}, b) = \frac{1}{m} \sum_{i=0}^{m-1} [-y^{(i)} \log(f_{\mathbf{w}, b}(\mathbf{x}^{(i)})) - (1 - y^{(i)}) \log(1 - f_{\mathbf{w}, b}(\mathbf{x}^{(i)}) J(w,b)=m1i=0m1[y(i)log(fw,b(x(i)))(1y(i))log(1fw,b(x(i))
正如在线性回归中一样,差异在于正则化项,即 λ 2 m ∑ j = 0 n − 1 w j 2 \frac{\lambda}{2m} \sum_{j=0}^{n-1} w_j^2 2mλj=0n1wj2
包含这个项可以激励梯度下降最小化参数的大小,注意,在这个例子中,参数 b b b没有被正则化,这是标准做法

def compute_cost_logistic_reg(X, y, w, b, lambda_ = 1):
    """
    计算所有示例的成本
    参数:
      X (ndarray (m,n): 数据,m 个示例,每个示例有 n 个特征
      y (ndarray (m,)): 目标值
      w (ndarray (n,)): 模型参数  
      b (scalar)      : 模型参数
      lambda_ (scalar): 控制正则化量
    返回:
      total_cost (scalar): 成本 
    """
    m,n  = X.shape
    cost = 0.
    for i in range(m):
        z_i = np.dot(X[i], w) + b                                      #(n,)(n,)=scalar, see np.dot
        f_wb_i = sigmoid(z_i)                                          #scalar
        cost +=  -y[i]*np.log(f_wb_i) - (1-y[i])*np.log(1-f_wb_i)      #scalar
             
    cost = cost/m                                                      #scalar
    reg_cost = 0
    for j in range(n):
        reg_cost += (w[j]**2)                                          #scalar
    reg_cost = (lambda_/(2*m)) * reg_cost                              #scalar
    
    total_cost = cost + reg_cost                                       #scalar
    return total_cost                                                  #scalar

运行下面的代码以查看它的效果

np.random.seed(1)
X_tmp = np.random.rand(5,6)
y_tmp = np.array([0,1,0,1,0])
w_tmp = np.random.rand(X_tmp.shape[1]).reshape(-1,)-0.5
b_tmp = 0.5
lambda_tmp = 0.7
cost_tmp = compute_cost_logistic_reg(X_tmp, y_tmp, w_tmp, b_tmp, lambda_tmp)
print("正则化成本:", cost_tmp)

结果输出:
在这里插入图片描述
预期输出:
正则化成本: 0.6850849138741673

2.4 带有正则化的梯度下降

运行梯度下降的基本算法在正则化后并没有改变,它是:
repeat until convergence:    {        w j = w j − α ∂ J ( w , b ) ∂ w j    for j := 0..n-1            b = b − α ∂ J ( w , b ) ∂ b } \begin{align*} &\text{repeat until convergence:} \; \lbrace \\ & \; \; \;w_j = w_j - \alpha \frac{\partial J(\mathbf{w},b)}{\partial w_j} \tag{1} \; & \text{for j := 0..n-1} \\ & \; \; \; \; \;b = b - \alpha \frac{\partial J(\mathbf{w},b)}{\partial b} \\ &\rbrace \end{align*} repeat until convergence:{wj=wjαwjJ(w,b)b=bαbJ(w,b)}for j := 0..n-1(1)
在每次迭代中,对所有 w j w_j wj 进行同时更新。
正则化后,变化的是计算梯度的方法。

2.5 带有正则化的梯度计算(线性/逻辑回归)

对于线性回归和逻辑回归,梯度计算几乎相同,仅在计算 f w , b ( x ) f_{\mathbf{w}, b}(\mathbf{x}) fw,b(x) 时有所不同
∂ J ( w , b ) ∂ w j = 1 m ∑ i = 0 m − 1 ( f w , b ( x ( i ) ) − y ( i ) ) x j ( i ) + λ m w j ∂ J ( w , b ) ∂ b = 1 m ∑ i = 0 m − 1 ( f w , b ( x ( i ) ) − y ( i ) ) \begin{align*} \frac{\partial J(\mathbf{w},b)}{\partial w_j} &= \frac{1}{m} \sum\limits_{i = 0}^{m-1} (f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)})x_{j}^{(i)} + \frac{\lambda}{m} w_j \tag{2} \\ \frac{\partial J(\mathbf{w},b)}{\partial b} &= \frac{1}{m} \sum\limits_{i = 0}^{m-1} (f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)}) \tag{3} \end{align*} wjJ(w,b)bJ(w,b)=m1i=0m1(fw,b(x(i))y(i))xj(i)+mλwj=m1i=0m1(fw,b(x(i))y(i))(2)(3)
其中:

  • m m m 是数据集中的训练示例数

f w , b ( x ) f_{\mathbf{w}, b}(\mathbf{x}) fw,b(x) 是模型的预测,而 y y y是目标

  • 对于线性回归模型: f w , b ( x ) = w ⋅ x + b f_{\mathbf{w}, b}(\mathbf{x}) = \mathbf{w} \cdot \mathbf{x} + b fw,b(x)=wx+b
  • 对于逻辑回归模型: z = w ⋅ x + b z = \mathbf{w} \cdot \mathbf{x} + b z=wx+b f w , b ( x ) = σ ( z ) f_{\mathbf{w}, b}(\mathbf{x}) = \sigma(z) fw,b(x)=σ(z)
    其中 σ ( z ) \sigma(z) σ(z)sigmoid函数: σ ( z ) = 1 1 + e − z \sigma(z) = \frac{1}{1 + e^{-z}} σ(z)=1+ez1
    添加正则化的项是 λ m w j \frac{\lambda}{m} w_j mλwj

2.6 正则化逻辑回归的梯度函数

def compute_gradient_logistic_reg(X, y, w, b, lambda_): 
    """
    计算逻辑回归的梯度
    
    参数:
      X (ndarray (m,n): 数据,m 个示例,每个示例有 n 个特征
      y (ndarray (m,)): 目标值
      w (ndarray (n,)): 模型参数  
      b (scalar)      : 模型参数
      lambda_ (scalar): 控制正则化量
    返回:
      dj_dw (ndarray Shape (n,)): 成本相对于参数 w 的梯度。 
      dj_db (scalar)            : 成本相对于参数 b 的梯度。 
    """
    m,n = X.shape
    dj_dw = np.zeros((n,))                            #(n,)
    dj_db = 0.0                                       #scalar
    for i in range(m):
        f_wb_i = sigmoid(np.dot(X[i],w) + b)          #(n,)(n,)=scalar
        err_i  = f_wb_i  - y[i]                       #scalar
        for j in range(n):
            dj_dw[j] = dj_dw[j] + err_i * X[i,j]      #scalar
        dj_db = dj_db + err_i
    dj_dw = dj_dw/m                                   #(n,)
    dj_db = dj_db/m                                   #scalar
    for j in range(n):
        dj_dw[j] = dj_dw[j] + (lambda_/m) * w[j]
    return dj_db, dj_dw  

运行下面的代码以查看它的效果

np.random.seed(1)
X_tmp = np.random.rand(5,3)
y_tmp = np.array([0,1,0,1,0])
w_tmp = np.random.rand(X_tmp.shape[1])
b_tmp = 0.5
lambda_tmp = 0.7
dj_db_tmp, dj_dw_tmp =  compute_gradient_logistic_reg(X_tmp, y_tmp, w_tmp, b_tmp, lambda_tmp)
print(f"dj_db: {dj_db_tmp}", )
print(f"Regularized dj_dw:\n {dj_dw_tmp.tolist()}", )

输出结果:
在这里插入图片描述

预期输出

dj_db: 0.6648774569425726
正则化 dj_dw:
 [0.29653214748822276, 0.4911679625918033, 0.21645877535865857]

2.7 正则化逻辑回归的梯度函数


def compute_gradient_logistic_reg(X, y, w, b, lambda_): 
    """
    计算线性回归的梯度
    参数:
      X (ndarray (m,n)): 数据,m个示例,每个示例有n个特征
      y (ndarray (m,)): 目标值
      w (ndarray (n,)): 模型参数  
      b (标量)        : 模型参数
      lambda_ (标量) : 控制正则化的程度
    返回
      dj_dw (ndarray 形状 (n,)): 成本关于参数w的梯度。
      dj_db (标量)            : 成本关于参数b的梯度。
    """
    m, n = X.shape
    dj_dw = np.zeros((n,))                            #(n,)
    dj_db = 0.0                                       #标量
    for i in range(m):
        f_wb_i = sigmoid(np.dot(X[i], w) + b)        #(n,)(n,)=标量
        err_i = f_wb_i - y[i]                         #标量
        for j in range(n):
            dj_dw[j] = dj_dw[j] + err_i * X[i, j]     #标量
        dj_db = dj_db + err_i
    dj_dw = dj_dw / m                                 #(n,)
    dj_db = dj_db / m                                 #标量
    for j in range(n):
        dj_dw[j] = dj_dw[j] + (lambda_ / m) * w[j]
    return dj_db, dj_dw

运行以下代码以查看效果

np.random.seed(1)
X_tmp = np.random.rand(5, 3)
y_tmp = np.array([0, 1, 0, 1, 0])
w_tmp = np.random.rand(X_tmp.shape[1])
b_tmp = 0.5
lambda_tmp = 0.7
dj_db_tmp, dj_dw_tmp = compute_gradient_logistic_reg(X_tmp, y_tmp, w_tmp, b_tmp, lambda_tmp)
print(f"dj_db: {dj_db_tmp}")
print(f"Regularized dj_dw:\n {dj_dw_tmp.tolist()}")

输出结果:
在这里插入图片描述

预期输出:

dj_db: 0.341798994972791
正则化后的dj_dw:
 [0.17380012933994293, 0.32007507881566943, 0.10776313396851499]

2.8 重新运行过拟合示例:

plt.close("all")
display(output)
ofit = overfit_example(True)

在上面的图表中,尝试对之前的示例使用正则化。特别是:
分类(逻辑回归):

  • 将多项式次数设置为6,正则化参数lambda设置为0(无正则化),拟合数据
    输出结果:
    在这里插入图片描述

  • 现在将lambda设置为1(增加正则化),拟合数据,注意差异
    输出结果:
    在这里插入图片描述

回归(线性回归):

  • 将多项式次数设置为6,正则化参数lambda设置为0(无正则化),拟合数据
    输出结果:
    在这里插入图片描述

  • 现在将lambda设置为1(增加正则化),拟合数据,注意差异
    输出结果:
    在这里插入图片描述

2.10 总结

  • 为线性回归和逻辑回归添加了成本和梯度例程的示例
  • 发展出一些关于正则化如何减少过拟合的直觉
  • 18
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值