正则化方法:数据增强、regularization、dropout

过拟合 overfitting

  • 在训练数据不够多,或者模型过于复杂时,常常会导致模型对训练数据集过度拟合。

  • 其直观的表现如下图所示:随着训练过程的进行,在训练集上的错误率渐渐减小,但是在验证集上的错误率却反而渐渐增大。

  • 正则化技术是保证算法泛化能力的有效工具。

数据增强

数据增强是提升算法性能、满足深度学习模型对大量数据的需求的重要工具。数据增强通过向训练数据添加转换或扰动来人工增加训练数据集。数据增强技术如:水平或垂直翻转图像、裁剪、色彩变换、扩展和旋转通常应用在视觉表象和图像分类中。

正则化项

最基本的正则化方法,是在代价函数中添加惩罚项,对复杂度高的模型进行“惩罚”。正则化一般具有如下形式:

J ( w , b ) = 1 m ∑ i = 1 m L ( y ^ , y ) + λ R ( w ) J(w,b)= \frac{1}{m} \sum_{i=1}^{m}L(\hat{y},y)+\lambda R(w) J(w,b)=m1i=1mL(y^,y)+λR(w)

其中:

  • L ( y ^ , y ) L(\hat{y},y) L(y^,y) 是经验风险项

  • λ R ( w ) \lambda R(w) λR(w) 是正则项

  • λ ≥ 0 λ≥0 λ0 为调整两者之间关系的系数

  • λ λ λ 值可以使用交叉验证的方法尝试一系列可能的值,比如从 0,0.01,0.02,0.04 … 开始,一直试下去,将步长设为2倍的速度增长。

常见的正则项有 L 1 L1 L1 正则项 和 L 2 L2 L2 正则项。

范数 norm

  • L 1 L_1 L1 范数: ∣ ∣ x ∣ ∣ 1 = ∑ i = 1 N ∣ x i ∣ ||x||_1 = \sum_{i=1}^N|x_i| x1=i=1Nxi

    即向量元素绝对值之和。

  • L 2 L_2 L2 范数: ∣ ∣ x ∣ ∣ 2 = ∑ i = 1 N x i 2 ||\textbf{x}||_2 =\sqrt{\sum_{i=1}^Nx_i^2} x2=i=1Nxi2

    即 Euclid范数(欧几里得范数),常用计算向量长度。

  • L p L_p Lp 范数: ∣ ∣ x ∣ ∣ p = ( ∑ i = 1 N ∣ x i ∣ p ) 1 p ||\textbf{x}||_p = (\sum_{i=1}^N|x_i|^p)^{\frac{1}{p}} xp=(i=1Nxip)p1

    即向量元素绝对值的 p p p 次方之和的 1 / p 1/p 1/p 次幂

L1 正则 Lasso regularizer

J ( w , b ) = 1 m ∑ i = 1 m L ( y ^ , y ) + λ ∣ w ∣ J(w,b)=\frac{1}{m} \sum_{i=1}^{m}L(\hat{y},y)+\lambda|w| J(w,b)=m1i=1mL(y^,y)+λw

  • L1正则化,是一个相对常用的正则化方法。

  • 正则化目的:减少参数的绝对值总和。

L2 正则 Ridge Regularizer / Weight Decay

J ( w , b ) = 1 m ∑ i = 1 m L ( y ^ , y ) + 1 2 λ w 2 J(w,b)=\frac{1}{m} \sum_{i=1}^{m}L(\hat{y},y)+\frac{1}{2}\lambda w^2 J(w,b)=m1i=1mL(y^,y)+21λw2

  • L2 正则化,可能是最常用的正则化方法了

  • 正则化目的:减少参数的平方值总和。

  • 系数 1 2 \frac{1}{2} 21 主要是为了后面的求导操作方便,加上 1 2 \frac{1}{2} 21 后,该式子关于 w w w 梯度就是 λ w \lambda w λw 而不是 2 λ w 2\lambda w 2λw 了。

  • L2 正则化,可以直观理解为它对于大数值的权重向量进行严厉惩罚,倾向于更加分散的权重向量,使网络更倾向于使用所有输入特征,而不是严重依赖输入特征中某些小部分特征。

    举个例子,假设输入向量 x = [ 1 , 1 , 1 , 1 ] x=[1,1,1,1] x=[1,1,1,1],两个权重向量 w 1 = [ 1 , 0 , 0 , 0 ] , w 2 = [ 0.25 , 0.25 , 0.25 , 0.25 ] w_1=[1,0,0,0],w_2=[0.25,0.25,0.25,0.25] w1=[1,0,0,0]w2=[0.25,0.25,0.25,0.25]。那么 w 1 T x = w 2 T = 1 w^T_1x=w^T_2=1 w1Tx=w2T=1,两个权重向量都得到同样的内积,但是 w 1 w_1 w1 的 L2 惩罚是 1.0 1.0 1.0,而 w 2 w_2 w2 的 L2 惩罚是 0.25 0.25 0.25

    因此,根据 L2 惩罚来看, w 2 w_2 w2 更好,因为它的正则化损失更小。从直观上来看,这是因为 w 2 w_2 w2 的权重值更小且更分散。既然 L 2 L2 L2 惩罚倾向于更小更分散的权重向量,这就会鼓励分类器最终将所有维度上的特征都用起来,而不是强烈依赖其中少数几个维度。

  • 在梯度下降时,使用 L2 正则化意味着所有的权重都以 w w w += - λ ∗ w \lambda *w λw 向着 0 线性下降。

L1 与 L2 的差异

L1 与 L2 的差异

  • 假设个体 x x x 只有两个分量,则 w w w 也只有两个分量 w 1 , w 2 w1,w2 w1w2,将其作为两个坐标轴,对于目标函数:

    J ( w , b ) = 1 m ∑ i = 1 m ( y i − w T x i ) 2 + λ R ( w ) J(w,b)= \frac{1}{m} \sum_{i=1}^{m}(y_i -w^Tx_i)^2+\lambda R(w) J(w,b)=m1i=1m(yiwTxi)2+λR(w)

  • 先绘出目标函数中 ( y i − w T x i ) 2 (y_i -w^Tx_i)^2 (yiwTxi)2 的平方误差项等值线(平方误差项取值相同的点的连线)。

  • 再分别绘制出 L1 范数和 L2 范数的等值线。

  • 目标函数的,要在平方误差项与正则化项之间折中,即出现在图中的等值线交点处。

  • 可发现采用 L1 范数时,平方误差等值线与正则化等值线的交点经常出现在坐标轴上,即 w 1 w1 w1 w 2 w2 w2 0 0 0

  • 而采用 L2 范数时,交点经常出现在象限中,即 w 1 w1 w1 w 2 w2 w2 均不为 0 0 0,故采用 L1 正则化项更易得到稀疏解。

L1 与 L2 的使用

  • 由于 L1 正则化得到的是稀疏解,它会让权重向量在最优化的过程中变得稀疏(即非常接近0),使用 L1 正则化的神经元最后使用的是它们最重要的输入特征的稀疏子集。

  • 相较 L1 正则化,L2 正则化中的权重向量大多是分散的小数字。

  • 在实践中,如果不是特别关注某些明确的特征选择,一般说来 L2 正则化都会比 L1 正则化效果好。

Dropout

L1、L2 正则化是通过修改代价函数来实现的,而 Dropout 则是通过修改神经网络本身来实现的,它是在训练网络时用的一种技巧。

随机失活 (dropout)

  • 在训练网络时,对于完整的网络结构(如左图),每次迭代时,都让神经元以超参数 p p p 的概率被随机地停用(Dropout),即输出置为0,如右图。

  • 在训练时,保持输入输出层不变,数据前向传播后,对得到的损失结果进行反向传播,更新神经网络中的权值时,不更新被停用的单元。

  • 在预测时,不进行随机失活,但是神经元的输出都要乘以超参数 p p p,调整其数值范围。以 p = 0.5 p=0.5 p=0.5 为例,在预测时神经元必须把它们的输出减半,这是因为在训练的时候它们的输出只有一半。

""" 普通版随机失活: 不推荐实现 """

p = 0.5 # 激活神经元的概率. p值更高 = 随机失活更弱

def train_step(X):
  """ X中是输入数据 """
  
  # 3层neural network的前向传播
  H1 = np.maximum(0, np.dot(W1, X) + b1)
  U1 = np.random.rand(*H1.shape) < p # 第一个随机失活遮罩
  H1 *= U1 # drop!
  H2 = np.maximum(0, np.dot(W2, H1) + b2)
  U2 = np.random.rand(*H2.shape) < p # 第二个随机失活遮罩
  H2 *= U2 # drop!
  out = np.dot(W3, H2) + b3
  
  # 反向传播:计算梯度... (略)
  # 进行参数更新... (略)
  
def predict(X):
  # 前向传播时模型集成
  H1 = np.maximum(0, np.dot(W1, X) + b1) * p # 注意:激活数据要乘以p
  H2 = np.maximum(0, np.dot(W2, H1) + b2) * p # 注意:激活数据要乘以p
  out = np.dot(W3, H2) + b3

反向随机失活(inverted dropout)

  • 相对于上述的随机失活,实际应用中更倾向使用反向随机失活(inverted dropout),它是在训练时就进行数值范围调整,从而让前向传播在测试时保持不变。

  • 这样做还有一个好处,无论你决定是否使用随机失活,预测方法的代码可以保持不变。反向随机失活的代码如下:

""" 
反向随机失活: 推荐实现方式.
在训练的时候drop和调整数值范围,测试时不做任何事.
"""

p = 0.5 # 激活神经元的概率. p值更高 = 随机失活更弱

def train_step(X):
  # 3层neural network的前向传播
  H1 = np.maximum(0, np.dot(W1, X) + b1)
  U1 = (np.random.rand(*H1.shape) < p) / p # 第一个随机失活遮罩. 注意/p!
  H1 *= U1 # drop!
  H2 = np.maximum(0, np.dot(W2, H1) + b2)
  U2 = (np.random.rand(*H2.shape) < p) / p # 第二个随机失活遮罩. 注意/p!
  H2 *= U2 # drop!
  out = np.dot(W3, H2) + b3

  # 反向传播:计算梯度... (略)
  # 进行参数更新... (略)

def predict(X):
  # 前向传播时模型集成
  H1 = np.maximum(0, np.dot(W1, X) + b1) # 不用数值范围调整了
  H2 = np.maximum(0, np.dot(W2, H1) + b2)
  out = np.dot(W3, H2) + b3

Dropout 对过拟合的解决

  • 取平均的作用:

    用相同的训练数据去训练 n 个不同的神经网络,一般会得到 n 个不同的结果,此时我们可以采用 n 个结果取均值去决定最终结果。

    取均值策略通常可以有效防止过拟合问题。因为不同的网络可能产生不同的过拟合,取均值则有可能让一些 “相反的” 拟合互相抵消。

    dropout 随机停用不同的隐层神经元,导致在每次迭代时都使用了不同的网络结构,就类似在训练不同的网络,整个 dropout 过程就相当于对很多个不同的神经网络取平均。

  • 减少神经元之间复杂的共适应关系:

    因为 dropout 程序导致两个神经元不一定每次都在一个 dropout 网络中出现。这样权值的更新不再依赖于有固定关系的隐含节点的共同作用,阻止了某些特征仅仅在其它特定特征下才有效果的情况,迫使网络去学习更加鲁棒的特征。

  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在PyTorch中,可以使用正则化dropout来提高模型的泛化能力和防止过拟合。 1. 正则化(Regularization): 正则化是通过在损失函数中引入模型参数的惩罚项来减小模型的复杂度。常见的正则化方法有L1正则化和L2正则化。 - L1正则化(L1 Regularization):通过在损失函数中添加模型权重的绝对值之和作为惩罚项。这可以促使模型权重变得稀疏,即某些权重趋近于零。 ```python loss = criterion(output, target) l1_lambda = 0.01 # L1正则化系数 l1_regularization = torch.tensor(0, dtype=torch.float32) for param in model.parameters(): l1_regularization += torch.norm(param, 1) loss += l1_lambda * l1_regularization ``` - L2正则化(L2 Regularization):通过在损失函数中添加模型权重的平方和作为惩罚项。这可以使权重趋向于较小的值,但不会使其为零。 ```python loss = criterion(output, target) l2_lambda = 0.01 # L2正则化系数 l2_regularization = torch.tensor(0, dtype=torch.float32) for param in model.parameters(): l2_regularization += torch.norm(param, 2) loss += l2_lambda * l2_regularization ``` 2. Dropout: Dropout是一种在训练过程中随机丢弃一部分神经元以减少模型过拟合的技术。它在每个训练批次中以一定的概率将神经元的输出置为零,使得网络不依赖于特定的神经元,从而提高了模型的泛化能力。 在PyTorch中,可以使用`torch.nn.Dropout`来添加Dropout层到模型中: ```python import torch.nn as nn # 在模型的定义中添加Dropout层 class MyModel(nn.Module): def __init__(self): super(MyModel, self).__init__() self.dropout = nn.Dropout(p=0.5) # dropout概率为0.5 # 其他网络层的定义... def forward(self, x): x = self.dropout(x) # 其他网络层的计算... return x ``` 在训练过程中,模型会自动应用Dropout,并在评估或推理时关闭Dropout以获得更稳定的预测结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值