PyTorch入门精简资料(五)PyTorch实现L1,L2正则化以及Dropout

 

Datawhale_Task5  PyTorch实现L1,L2正则化以及Dropout

  1. 了解知道Dropout原理
  2. 用代码实现正则化(L1、L2、Dropout)
  3. Dropout的numpy实现
  4. PyTorch中实现dropout
  5. 参考资料:PyTorch 中文文档

1.Dropout原理

(1)Dropout

       实际是在前向传播的时候,让某个神经元的激活值以一定的概率P停止工作,这样可以使模型泛化性更强,一定程度上起到正则化的作用,可以防止网络拟合。P一般取0.5。

对于某层的每个神经元,

在训练阶段,每个神经元以概率P,随机将该神经元权重置0;

在测试阶段,所有神经元均呈现激活状态,但所有权重要乘以(1-P);

以保证训练和测试阶段各自权重有相同的期望。

(2)Dropout为什么能防止过拟合?

  1.  具有取平均的作用
  2. 减少神经元之间复杂的共适关系
  3. Dropout类似于性别在生物进化中的角色:性别的出现可以繁衍出适应新环境的变种,有效的阻止过拟合,即避免环境改变时物种可能面临的灭绝

2.用代码实现正则化(L1、L2、Dropout)

正则化:在原来的loss function的基础上,加上了一些正则化项或者称为模型复杂度惩罚项

(1)L1正则化

L1,又称为LASSO。L1范数,是参数矩阵W中元素的绝对值之和。

regularization_loss1 = 0
for param in model.parameters():
    regularization_loss1 += torch.sum(abs(param))

(2)L2正则化

L2,又称为Rigde。L2范数,是参数矩阵W中元素的平方之和。

regularization_loss2 = 0
for param in model.parameters():
    regularization_loss2 += torch.norm(param,2)

以线性回归为例,

PyTorch入门精简资料(五)PyTorch实现L1,L2正则化以及Dropout_第1张图片

PyTorch入门精简资料(五)PyTorch实现L1,L2正则化以及Dropout_第2张图片

                                                                                 加入L1和L2正则的等高线

L1:我们经过观察可以看到,几乎对于很多原函数等高曲线,和某个菱形相交的时候及其容易相交在坐标轴(比如上图),也就是说最终的结果,解的某些维度及其容易是0,这也就是我们所说的L1更容易得到稀疏解(解向量中0比较多)的原因。

L2:从图上来看,不容易交在坐标轴上,但是仍然比较靠近坐标轴因此这也就是我们老说的,L2范数能让解比较小(靠近0),但是比较平滑(不等于0)。

3.Dropout的numpy实现

  1. 建立一个维度与本层神经元数目相同的矩阵D.
  2. 根据概率(这里用变量keep_prob代表)将矩阵D中的元素设置为0或1。
  3. 将本层激活函数的输出与D相乘作为新的输出。
  4. 新的输出除以keep_prob,这一步是为了保证得到的代价与未进行Dropout前一致,想像一下,你有5个1,求和等于5,现在随机删除了1/5的数字,为了保证结果还是5,需要对剩下来的每一个数字都除以1/5。
import numpy as np
def dropout(X, keep_prob = 0.5):
    """
    :param X: input
    :param keep_prob:
    :return:
    """

    D = np.random.rand(X.shape[0], X.shape[1]) # step1: initialize matrix d
    D = D < keep_prob # step2: convert entries of d
    X = X * D # step3: shut down some neuron
    X = X/keep_prob #step4: scale the value of neuron

    return X

4.PyTorch中实现dropout

import torch
import torch.nn.functional as F
import torch.nn as nn


class Model1(nn.Module):
    # Model 1 using functional dropout
    def __init__(self, p=0.0):
        super(Model1,self).__init__()
        self.p = p

    def forward(self, inputs):
        return F.dropout(inputs, p=self.p, training=True)

#建议选择这种,因为dropout在训练和测试阶段使用不同
class Model2(nn.Module):
    # Model 2 using dropout module
    def __init__(self, p=0.0):
        super(Model2,self).__init__()
        self.drop_layer = nn.Dropout(p=p)

    def forward(self, inputs):
        return self.drop_layer(inputs)
model1 = Model1(p=0.5) # functional dropout
model2 = Model2(p=0.5) # dropout module

# creating inputs
inputs = torch.rand(10)
print("inputs", inputs)
# forwarding inputs in train mode
print('Normal (train) model:')
print('Model 1', model1(inputs))
print('Model 2', model2(inputs))
print()

# switching to eval mode
model1.eval()
model2.eval()

# forwarding inputs in evaluation mode
print('Evaluation mode:')
print('Model 1', model1(inputs))
print('Model 2', model2(inputs))
# show model summary
print('Print summary:')
print(model1)
print(model2)

可以看到,如果使用的是F.dropout,那么在model.eval的时候,测试时如果没有对dropout函数进行调整的话,还是会对输入进行dropout的操作,但是nn.dropout就不存在这样的问题。修改F.dropout,就跟nn.dropout效果一样

F.dropout(inputs, p=self.p, training=self.training)

参考:PyTorch的dropout设置训练和测试模式

          pytorch中torch.nn.dropout和torch.nn.F.dropout区别

         L2正则化(L2 Regularization)、Dropout原理及其python实现

        L1正则化与L2正则化

你可能感兴趣的:(深度学习)