dropout.md 5.4 KB
Newer Older
A
Aston Zhang 已提交
1
# 丢弃法
2

A
Aston Zhang 已提交
3
除了前两节介绍的权重衰减以外,深度学习模型常常使用丢弃法(dropout)来应对过拟合问题。丢弃法有一些不同的变体。本节中提到的丢弃法特指倒置丢弃法(inverted dropout)。它被广泛使用于深度学习。
4 5


A
Aston Zhang 已提交
6
## 方法和原理
7

A
Aston Zhang 已提交
8
为了确保测试模型的确定性,丢弃法的使用只发生在训练模型时,并非测试模型时。当神经网络中的某一层使用丢弃法时,该层的神经元将有一定概率被丢弃掉。设丢弃概率为$p$。具体来说,该层任一神经元在应用激活函数后,有$p$的概率自乘0,有$1-p$的概率自除以$1-p$做拉伸。丢弃概率是丢弃法的超参数。
9

A
Aston Zhang 已提交
10
我们在[“多层神经网络”](multi-layer.md)一节的图3.3中描述了一个未使用丢弃法的多层感知机。假设其中隐藏单元$h_i$($i=1, \ldots, 5$)的计算表达式为
11

A
Aston Zhang 已提交
12
$$h_i = \phi(x_1 w_1^{(i)} + x_2 w_2^{(i)} + x_3 w_3^{(i)} + x_4 w_4^{(i)} + b^{(i)}),$$
13

A
Aston Zhang 已提交
14
其中$\phi$是激活函数,$x_1, \ldots, x_4$是输入,$w_1^{(i)}, \ldots, w_4^{(i)}$是权重参数,$b^{(i)}$是偏差参数。设丢弃概率为$p$,并设随机变量$\xi_i$有$p$概率为0,有$1-p$概率为1。那么,使用丢弃法的隐藏单元$h_i$的计算表达式变为
15

A
Aston Zhang 已提交
16
$$h_i = \frac{\xi_i}{1-p} \phi(x_1 w_1^{(i)} + x_2 w_2^{(i)} + x_3 w_3^{(i)} + x_4 w_4^{(i)} + b^{(i)}).$$
17

A
Aston Zhang 已提交
18
注意到测试模型时不使用丢弃法。由于$\mathbb{E} (\xi_i) = 1-p$,同一神经元在模型训练和测试时的输出值的期望不变。
A
Aston Zhang 已提交
19 20 21

让我们对图3.3中的隐藏层使用丢弃法,一种可能的结果如图3.5所示。

A
Aston Zhang 已提交
22
![隐藏层使用了丢弃法的多层感知机。](../img/dropout.svg)
A
Aston Zhang 已提交
23 24 25 26 27 28

以图3.5为例,每次训练迭代时,隐藏层中每个神经元都有可能被丢弃,即$h_i$($i=1, \ldots, 5$)都有可能为0。因此,输出层每个单元的计算,例如$o_1 = \phi(h_1 w_1^\prime + h_2 w_2^\prime + h_3 w_3^\prime + h_4 w_4^\prime + h_5 w_5^\prime  + b^\prime)$,都无法过分依赖$h_1, \ldots, h_5$中的任一个。这样通常会造成$o_1$表达式中的权重参数$w_1^\prime, \ldots ,w_5^\prime$都接近0。因此,丢弃法可以起到正则化的作用,并可以用来应对过拟合。

## 实现丢弃法

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

```{.python .input}
A
Aston Zhang 已提交
31 32 33 34 35
import sys
sys.path.append('..')
import gluonbook as gb
from mxnet import autograd, gluon, nd
from mxnet.gluon import loss as gloss
M
Mu Li 已提交
36

A
Aston Zhang 已提交
37 38 39
def dropout(X, drop_prob):
    assert 0 <= drop_prob <= 1
    keep_prob = 1 - drop_prob
40
    # 这种情况下把全部元素都丢弃。
A
Aston Zhang 已提交
41
    if keep_prob == 0:
42
        return X.zeros_like()
A
Aston Zhang 已提交
43
    mask = nd.random.uniform(0, 1, X.shape) < keep_prob
A
Aston Zhang 已提交
44
    return mask * X / keep_prob
45 46
```

A
Aston Zhang 已提交
47
我们运行几个例子来验证一下`dropout`函数。
48 49

```{.python .input}
A
Aston Zhang 已提交
50 51
X = nd.arange(20).reshape((5, 4))
dropout(X, 0)
52 53 54
```

```{.python .input}
A
Aston Zhang 已提交
55
dropout(X, 0.5)
56 57 58
```

```{.python .input}
A
Aston Zhang 已提交
59
dropout(X, 1)
60 61
```

A
Aston Zhang 已提交
62
## 定义模型参数
63

A
use  
Aston Zhang 已提交
64
实验中,我们依然使用[“Softmax回归——从零开始”](softmax-regression-scratch.md)一节中介绍的Fashion-MNIST数据集。我们将定义一个包含两个隐藏层的多层感知机。其中两个隐藏层的输出个数都是256。
65 66

```{.python .input  n=2}
A
Aston Zhang 已提交
67
num_inputs = 784
68
num_outputs = 10
A
Aston Zhang 已提交
69 70
num_hiddens1 = 256
num_hiddens2 = 256
71

A
Aston Zhang 已提交
72
W1 = nd.random.normal(scale=0.01, shape=(num_inputs, num_hiddens1))
A
Aston Zhang 已提交
73
b1 = nd.zeros(num_hiddens1)
A
Aston Zhang 已提交
74
W2 = nd.random.normal(scale=0.01, shape=(num_hiddens1, num_hiddens2))
A
Aston Zhang 已提交
75
b2 = nd.zeros(num_hiddens2)
A
Aston Zhang 已提交
76
W3 = nd.random.normal(scale=0.01, shape=(num_hiddens2, num_outputs))
77 78 79 80 81 82 83
b3 = nd.zeros(num_outputs)

params = [W1, b1, W2, b2, W3, b3]
for param in params:
    param.attach_grad()
```

A
Aston Zhang 已提交
84
## 定义模型
85

A
Aston Zhang 已提交
86
我们的模型就是将全连接层和激活函数ReLU串起来,并对激活函数的输出使用丢弃法。我们可以分别设置各个层的丢弃概率。通常,建议把靠近输入层的丢弃概率设的小一点。在这个实验中,我们把第一个隐藏层的丢弃概率设为0.2,把第二个隐藏层的丢弃概率设为0.5。我们只需在训练模型时使用丢弃法。
87 88 89 90 91 92 93

```{.python .input  n=4}
drop_prob1 = 0.2
drop_prob2 = 0.5

def net(X):
    X = X.reshape((-1, num_inputs))
A
Aston Zhang 已提交
94
    H1 = (nd.dot(X, W1) + b1).relu()
A
Aston Zhang 已提交
95
    # 只在训练模型时使用丢弃法。
A
Aston Zhang 已提交
96 97 98 99 100 101 102 103
    if autograd.is_training():
        # 在第一层全连接后添加丢弃层。
        H1 = dropout(H1, drop_prob1)
    H2 = (nd.dot(H1, W2) + b2).relu()
    if autograd.is_training():
        # 在第二层全连接后添加丢弃层。
        H2 = dropout(H2, drop_prob2)
    return nd.dot(H2, W3) + b3
104 105
```

A
Aston Zhang 已提交
106
## 训练和测试模型
107

A
Aston Zhang 已提交
108
这部分和之前多层感知机的训练与测试类似。
109 110

```{.python .input  n=8}
111 112
num_epochs = 5
lr = 0.5
A
Aston Zhang 已提交
113 114 115
batch_size = 256
loss = gloss.SoftmaxCrossEntropyLoss()
train_iter, test_iter = gb.load_data_fashion_mnist(batch_size)
A
Aston Zhang 已提交
116 117
gb.train_cpu(net, train_iter, test_iter, loss, num_epochs, batch_size, params,
             lr)
118 119
```

A
Aston Zhang 已提交
120
## 小结
121

A
Aston Zhang 已提交
122 123
* 我们可以通过使用丢弃法应对过拟合。
* 只需在训练模型时使用丢弃法。
124 125 126

## 练习

A
Aston Zhang 已提交
127 128
- 尝试不使用丢弃法,看看这个包含两个隐藏层的多层感知机可以得到什么结果。
- 如果把本节中的两个丢弃概率超参数对调,会有什么结果?
S
Sheng Zha 已提交
129

A
Aston Zhang 已提交
130 131 132
## 扫码直达[讨论区](https://discuss.gluon.ai/t/topic/1278)

![](../img/qr_dropout-scratch.svg)