一、写在前面

本文是《Dive-into-Deep-Learning》一书中文Pytorch版本的3.13节drop_out实现读书笔记仅作个人备忘与记录。

二、理论介绍

除了前一节介绍的权重衰减以外,深度学习模型常常使用丢弃法(dropout)来应对过拟合问题。丢弃法有一些不同的变体。本节中提到的丢弃法特指倒置丢弃法(inverted dropout)。
方法:
回忆一下,3.8节(多层感知机)描述了一个单隐藏层的多层感知机。其中输入个数为4,隐藏单元个数为5,且隐藏单元pytorch添加dropout层 pytorch dropout用法_深度学习pytorch添加dropout层 pytorch dropout用法_算法_02)的计算表达式为

pytorch添加dropout层 pytorch dropout用法_算法_03

这里pytorch添加dropout层 pytorch dropout用法_神经网络_04是激活函数,pytorch添加dropout层 pytorch dropout用法_算法_05是输入,隐藏单元pytorch添加dropout层 pytorch dropout用法_python_06的权重参数为pytorch添加dropout层 pytorch dropout用法_python_07,偏差参数为pytorch添加dropout层 pytorch dropout用法_神经网络_08。当对该隐藏层使用丢弃法时,该层的隐藏单元将有一定概率被丢弃掉。设丢弃概率为pytorch添加dropout层 pytorch dropout用法_深度学习_09,那么有pytorch添加dropout层 pytorch dropout用法_深度学习_09的概率pytorch添加dropout层 pytorch dropout用法_深度学习会被清零,有pytorch添加dropout层 pytorch dropout用法_pytorch添加dropout层_12的概率pytorch添加dropout层 pytorch dropout用法_深度学习会除以pytorch添加dropout层 pytorch dropout用法_pytorch添加dropout层_12做拉伸。丢弃概率是丢弃法的超参数。具体来说,设随机变量pytorch添加dropout层 pytorch dropout用法_深度学习_15为0和1的概率分别为pytorch添加dropout层 pytorch dropout用法_深度学习_09pytorch添加dropout层 pytorch dropout用法_pytorch添加dropout层_12。使用丢弃法时我们计算新的隐藏单元pytorch添加dropout层 pytorch dropout用法_神经网络_18

pytorch添加dropout层 pytorch dropout用法_python_19

由于pytorch添加dropout层 pytorch dropout用法_算法_20,因此

pytorch添加dropout层 pytorch dropout用法_深度学习_21

即丢弃法不改变其输入的期望值。让我们对图3.3中的隐藏层使用丢弃法,一种可能的结果如图3.5所示,其中pytorch添加dropout层 pytorch dropout用法_python_22pytorch添加dropout层 pytorch dropout用法_神经网络_23被清零。这时输出值的计算不再依赖pytorch添加dropout层 pytorch dropout用法_python_22pytorch添加dropout层 pytorch dropout用法_神经网络_23,在反向传播时,与这两个隐藏单元相关的权重的梯度均为0。由于在训练中隐藏层神经元的丢弃是随机的,即pytorch添加dropout层 pytorch dropout用法_算法_26都有可能被清零,输出层的计算无法过度依赖pytorch添加dropout层 pytorch dropout用法_算法_26中的任一个,从而在训练模型时起到正则化的作用,并可以用来应对过拟合。在测试模型时,我们为了拿到更加确定性的结果,一般不使用丢弃法。

三、代码实现

根据丢弃法的定义,我们可以很容易地实现它。下面的dropout函数将以drop_prob的概率丢弃X中的元素。

%matplotlib inline
import torch
import torch.nn as nn
import numpy as np
import sys
sys.path.append("..") 
import d2lzh_pytorch as d2l

def dropout(X, drop_prob):
    X = X.float()
    assert 0 <= drop_prob <= 1
    keep_prob = 1 - drop_prob
    # 这种情况下把全部元素都丢弃
    if keep_prob == 0:
        return torch.zeros_like(X)
    mask = (torch.rand(X.shape) < keep_prob).float()
    
    return mask * X / keep_prob

实验中,我们依然使用3.6节(softmax回归的从零开始实现)中介绍的Fashion-MNIST数据集。我们将定义一个包含两个隐藏层的多层感知机,其中两个隐藏层的输出个数都是256。

num_inputs, num_outputs, num_hiddens1, num_hiddens2 = 784, 10, 256, 256

W1 = torch.tensor(np.random.normal(0, 0.01, size=(num_inputs, num_hiddens1)), dtype=torch.float, requires_grad=True)
b1 = torch.zeros(num_hiddens1, requires_grad=True)
W2 = torch.tensor(np.random.normal(0, 0.01, size=(num_hiddens1, num_hiddens2)), dtype=torch.float, requires_grad=True)
b2 = torch.zeros(num_hiddens2, requires_grad=True)
W3 = torch.tensor(np.random.normal(0, 0.01, size=(num_hiddens2, num_outputs)), dtype=torch.float, requires_grad=True)
b3 = torch.zeros(num_outputs, requires_grad=True)

params = [W1, b1, W2, b2, W3, b3]

下面定义的模型将全连接层和激活函数ReLU串起来,并对每个激活函数的输出使用丢弃法。我们可以分别设置各个层的丢弃概率。通常的建议是把靠近输入层的丢弃概率设得小一点。在这个实验中,我们把第一个隐藏层的丢弃概率设为0.2,把第二个隐藏层的丢弃概率设为0.5。我们可以通过参数is_training来判断运行模式为训练还是测试,并只需在训练模式下使用丢弃法。

drop_prob1, drop_prob2 = 0.2, 0.5

def net(X, is_training=True):
    X = X.view(-1, num_inputs)
    H1 = (torch.matmul(X, W1) + b1).relu()
    if is_training:  # 只在训练模型时使用丢弃法
        H1 = dropout(H1, drop_prob1)  # 在第一层全连接后添加丢弃层
    H2 = (torch.matmul(H1, W2) + b2).relu()
    if is_training:
        H2 = dropout(H2, drop_prob2)  # 在第二层全连接后添加丢弃层
    return torch.matmul(H2, W3) + b3

训练和测试模型:

num_epochs, lr, batch_size = 5, 100.0, 256
loss = torch.nn.CrossEntropyLoss()
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, params, lr)

输出:

epoch 1, loss 0.0044, train acc 0.574, test acc 0.648
epoch 2, loss 0.0023, train acc 0.786, test acc 0.786
epoch 3, loss 0.0019, train acc 0.826, test acc 0.825
epoch 4, loss 0.0017, train acc 0.839, test acc 0.831
epoch 5, loss 0.0016, train acc 0.849, test acc 0.850

四、小结

1.我们可以通过使用丢弃法应对过拟合。
2.丢弃法只在训练模型时使用。