0%

dropout

背景

通常,在深度学习任务中,我们可以通过在损失函数中添加正则化项来避免过拟合,L2正则化项是通常使用的正则化项,L2正则化项使得模型最终的权重值分布比较均匀,使用L2正则化项时,我们就假设了我们的模型的对于样本的每个特征都相似的看重,而不只是看重某几个可能是关键特征的特征。

对于线形模型,在样本特征多样本数量少的情况下,线形模型很有可能会过拟合,但是只要增加样本数量,线形模型大概率就能摆脱过拟合的风险。但是线形这种可靠的特性也是有代价的,线形模型不关系样本特征之间的关系。对于每个样本特征,线形模型就只是要么给一个正的权重或者负的权重,而不会考虑任何背景信息。 不同于线形模型,神经网络通常不会独立对待每个样本特征,神经网络能够学习样本之间的关系,但是,对于深度神经网络来说,即使样本数量远远多于样本特征,深度神经网络仍然会有过拟合的风险。

同时来说,使用简单的模型可以避免过拟合。使用更少纬度的特征、使用正则化项让权重值分布比较均匀都可以让模型变得简单。另外还有一种让模型变得简单的方法叫做光滑(smoothness),即模型不会对输入的细微改变而敏感。

在神经网络中,训练时,对于每层网络向后传播的过程中,引入噪声就能让神经网络变得`光滑`,这种方法被叫做dropout。这种方法已经成为了一种训练神经网络的标准方法。叫做dropout的原因是因为在训练时对于每层网络我们都会随机丢弃一些神经元。在丢弃神经元的时候,我们要保证丢弃后的该层网络神经元的期望值和丢弃前的值是一致的。

dropout函数

在标准的dropout中,其定义为:对于每层的每个神经元,都有$p$的概率丢弃掉(置零),如果没有丢弃,则值变为$\frac{x}{1-p}$,$x$为该神经元的原始输出值。即:

可以证明$E(x) = x$

drop out 代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def dropout_layer(one_layer: tf.tensor, dropout_probability: float):
assert 0 <= dropout_probability <= 1
if dropout_probability == 1:
# in this case, all elements are dropped out
return tf.zeros_like(one_layer) # tf.zeros_like: create a tensor with all elements set to zero

if dropout_probability == 0:
# in this case, all elements are kept
return one_layer

# tf.random.uniform: outputs random values from a uniform distribution.
# with (1-p)'s probability that value will become x / (1-p)
mask = tf.random.uniform(shape=tf.shape(one_layer), minval=0, maxval=1) < (1 - dropout_probability)

return tf.cast(mask, dtype=tf.float32) * one_layer / (1.0 - dropout_probability)


# 在框架中使用快速调用drop out
net = tf.keras.models.Sequential([tf.keras.layers.Dense(256, activation=tf.nn.relu,
kernel_regularizer=tf.keras.regularizers.l2(0.3)),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Dense(256, activation=tf.nn.relu,
kernel_regularizer=tf.keras.regularizers.l2(0.3)),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10)])