3.13 丢弃法
方法
除了权重衰减以外,深度学习模型常常使用丢弃法(dropout)来应对过拟合问题。丢弃法有一些不同的变体。本节中提到的丢弃法特指倒置丢弃法(inverted dropout)。
一个单隐藏层的多层感知机,其中输入个数为4,隐藏单元个数为5,且隐藏单元\(h_i\)(\(i=1, \ldots, 5\))的计算表达式为
\[ h_i = \phi\left(x_1 w_{1i} + x_2 w_{2i} + x_3 w_{3i} + x_4 w_{4i} + b_i\right) \]
这里\(\phi\)是激活函数,\(x_1, \ldots, x_4\)是输入,隐藏单元\(i\)的权重参数为\(w_{1i}, \ldots, w_{4i}\),偏差参数为\(b_i\)。当对该隐藏层使用丢弃法时,该层的隐藏单元将有一定概率被丢弃掉。设丢弃概率为\(p\),那么有\(p\)的概率\(h_i\)会被清零,有\(1-p\)的概率\(h_i\)会除以\(1-p\)做拉伸。丢弃概率是丢弃法的超参数。具体来说,设随机变量\(\xi_i\)为0和1的概率分别为\(p\)和\(1-p\)。使用丢弃法时计算新的隐藏单元\(h_i'\)
\[ h_i' = \frac{\xi_i}{1-p} h_i \]
由于\(E(\xi_i) = 1-p\),因此
\[ E(h_i') = \frac{E(\xi_i)}{1-p}h_i = h_i \]
即丢弃法不改变其输入的期望值。对上述隐藏层使用丢弃法,一种可能的结果如下图所示,其中\(h_2\)和\(h_5\)被清零。这时输出值的计算不再依赖\(h_2\)和\(h_5\),在反向传播时,与这两个隐藏单元相关的权重的梯度均为0。由于在训练中隐藏层神经元的丢弃是随机的,即\(h_1, \ldots, h_5\)都有可能被清零,输出层的计算无法过度依赖\(h_1, \ldots, h_5\)中的任一个,从而在训练模型时起到正则化的作用,并可以用来应对过拟合。在测试模型时,为了拿到更加确定性的结果,一般不使用丢弃法。
从零开始实现
1 | import torch |
定义模型参数
使用Fashion-MNIST数据集。定义一个包含两个隐藏层的多层感知机,其中两个隐藏层的输出个数都是256。
1 | num_inputs, num_outputs, num_hiddens1, num_hiddens2 = 784, 10, 256, 256 |
定义模型
模型中将全连接层和激活函数ReLU串起来,并对每个激活函数的输出使用丢弃法。分别设置各个层的丢弃概率。通常的建议是把靠近输入层的丢弃概率设得小一点。在这个实验中,把第一个隐藏层的丢弃概率设为0.2,把第二个隐藏层的丢弃概率设为0.5。通过参数is_training
来判断运行模式为训练还是测试,并只需在训练模式下使用丢弃法。
1 | drop_prob1, drop_prob2 = 0.2, 0.5 # 丢弃概率 |
评估函数,根据模型的定义方式,进入评估模式。
1 | def evaluate_accuracy(data_iter, net): |
训练和测试模型
这部分和之前的一样
1 | def get_dataloader_workers(): |
简洁实现
在PyTorch中,只需要在全连接层后添加Dropout
层并指定丢弃概率。在训练模型时,Dropout
层将以指定的丢弃概率随机丢弃上一层的输出元素;在测试模型时(即model.eval()
后),Dropout
层并不发挥作用。
1 | from torch import nn |
训练并测试模型
1 | optimizer = torch.optim.SGD(net.parameters(), lr=0.5) |