此系列是记录DL、ML相关的一些基础概念,便于理解和回顾!一天两道!哈哈哈~~,水滴石穿!小白水平,若有错误,欢迎指正!
文章目录
深度学习之Dropout
Dropout 来自于文章: 《 D r o p o u t : A S i m p l e W a y t o P r e v e n t N e u r a l N e t w o r k s f r o m O v e r f i t t i n g 》 《Dropout: A \ Simple \ Way \ to \ Prevent \ Neural \ Networks \ from \ Overfitting》 《Dropout:A Simple Way to Prevent Neural Networks from Overfitting》
推荐和参考链接:dropout的理解
提出的目的:
阻止神经网络过拟合。
什么是过拟合?
- 左边为:欠拟合,模型没有学到东西;
- 中间为:刚刚好,不大不小;
- 右边为:过拟合,学的太狠了,断章取义;
过拟合产生的原因:
- 有脏数据,也就是数据有噪声;
- 训练数据不足;
- 训练模型很复杂,学的太狠;
如何避免过拟合?
- 早停止,ML中为 early stopping;
- 扩增数据集;
- 控制模型参数大小(正则化:L1,L2);
- Dropout正则化;
① early stopping:在模型对训练数据集迭代收敛之前停止迭代防止过拟合。
可以看到模型的error是随着训练时间是呈曲线下降的.这里包括train error和cross validation error,如果它在训练过程中在某个最低点之后cross validation error开始上升,说明模型可能存在过拟合了。一般的做法是,在训练的过程中,记录到目前为止最好的validation accuracy,当连续10次Epoch(或者更多次)没达到最佳accuracy时,则可以认为accuracy不再提高了。此时便可以停止迭代了(Early Stopping)。
② 扩增数据集
- 从数据源头采集更多数据
- 复制原有的数据并加上随机噪声
- 重采样
- 根据当前数据集估计数据分布参数,使用该分布产生更多的数据等
③ 正则化
L1、L2正则化,后面系列会介绍;
④ Dropout
在训练的时候让神经元以一定的概率不工作。
Dropout
Dropout说的简单一点就是在前向传导的时候,让某个神经元的激活值以一定的概率p,让其停止工作。Dropout的出现很好的可以解决这个问题,每次做完dropout,相当于从原始的网络中找到一个更瘦的网络。
前向传播:
z
i
(
l
+
1
)
=
w
i
(
l
+
1
)
y
l
+
b
i
(
l
+
1
)
z_{i}^{(l+1)}=\mathbf{w}_{i}^{(l+1)} \mathbf{y}^{l}+b_{i}^{(l+1)}
zi(l+1)=wi(l+1)yl+bi(l+1)
y
i
(
l
+
1
)
=
f
(
z
i
(
l
+
1
)
)
y_{i}^{(l+1)}=f\left(z_{i}^{(l+1)}\right)
yi(l+1)=f(zi(l+1))采用 Dropout 之后,
r
j
(
l
)
∼
y
(
p
)
y
~
(
l
)
=
r
(
l
)
∗
y
(
l
)
z
i
(
l
+
1
)
=
w
i
(
l
+
1
)
y
~
l
+
+
b
i
(
l
+
1
)
y
i
(
l
+
1
)
=
f
(
z
i
(
l
+
1
)
)
\begin{aligned} r_{j}^{(l)} & \sim \operatorname{y}(p) \\ \widetilde{\mathbf{y}}^{(l)} &=\mathbf{r}^{(l)} * \mathbf{y}^{(l)} \\ z_{i}^{(l+1)} &=\mathbf{w}_{i}^{(l+1)} \widetilde{\mathbf{y}}^{l+}+b_{i}^{(l+1)} \\ y_{i}^{(l+1)} &=f\left(z_{i}^{(l+1)}\right) \end{aligned}
rj(l)y
(l)zi(l+1)yi(l+1)∼y(p)=r(l)∗y(l)=wi(l+1)y
l++bi(l+1)=f(zi(l+1))
y
(
p
)
y(p)
y(p)是为了以概率p,随机生成一个0、1的向量。
注意的是:
经过上面屏蔽掉某些神经元,使其激活值为0以后,我们还需要对余下的非0的向量
x
1
…
…
x
t
x_1……x_t
x1……xt进行 rescale(扩大倍数),也就是乘以1/
p
p
p。如果你在训练的时候,经过置0后,没有对
x
1
…
…
x
t
x_1……x_t
x1……xt 进行rescale,那么你在测试的时候,就需要对权重进行rescale:
简单地总结为:
在训练时,每个神经单元都可能以概率 p 去除;
在测试阶段,每个神经单元都是存在的,权重参数w要乘以p,成为:p*w。
为什么呢?
既不想在训练的时候,对x进行放大,也不愿意在测试的时候,对权重进行缩小(乘以概率p)。那么可以测试n次,这n次都采用了dropout,然后对预测结果取平均值,这样当n趋近于无穷大的时候,就是我们需要的结果了。
Dropout代码实现:
import numpy as np
# dropout函数的实现
def dropout(x, level):
if level < 0. or level >= 1: # level是概率值,必须在0~1之间
raise Exception('Dropout level must be in interval [0, 1[.')
retain_prob = 1. - level
# 我们通过binomial函数,生成与x(x表示输入数据,要对其dropout)一样的维数向量。
# binomial函数就像抛硬币一样,我们可以把每个神经元当做抛硬币一样
# 硬币正面的概率为p,n表示每个神经元试验的次数
# 因为我们每个神经元只需要抛一次就可以了所以n=1,size参数是我们有多少个硬币。
# 即将生成一个0、1分布的向量,0表示这个神经元被屏蔽,不工作了,也就是dropout了
sample = np.random.binomial(n=1, p=retain_prob, size=x.shape)
print(sample) # 【0,1,0,1。。。】有点像独热
# 0、1与x相乘,我们就可以屏蔽某些神经元,让它们的值变为0。1则不影响
x *= sample
print(x)
# 对余下的非0的进行扩大倍数,因为p<0。0/x=0,所以0不影响
x /= retain_prob
return x
# 对dropout的测试,大家可以跑一下上面的函数,了解一个输入x向量,经过dropout的结果
x = np.asarray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], dtype=np.float32)
dropout(x, 0.5)
参考的链接