文章目录
Dropout
dropout 主要用于解决训练过程中模型出现过拟合的问题。在模型训练过程中,当训练集上的正确率很高,但验证集上的正确率很低时,即发生了过拟合。解决过拟合的方法有很多,例如利用集成学习的方法,训练多个模型进行组合;减少网络训练的层数;提前终止训练等。此外,Dropout可以比较有效的缓解过拟合的发生,在一定程度上达到正则化的效果。
dropout 简介
(以下参考深度学习中Dropout原理解析)
dropout可解决模型的过拟合问题,其原理是在模型训练的每个批次中,随机的让一半的隐层节点值变为0,这种做法可以让隐层节点之间的相互作用变弱(隐层之间的相互作用是指 某些检测器依赖其他检测器才能发挥作用)。
总而言之,就是在前向传播的过程中,以概率P让某个神经元失活,这样可以使模型泛化性更强,因为它不会太依赖某些局部的特征,用图片表示上述过程:
dropout具体工作流程
首先,定义一个标准的神经网络模型;
使用dropout之后,过程变成如下:
1.随机删掉网络中的一半的隐藏神经元(备份被删除的神经元参数);
2.将输入的x通过修改后的网络做前向传播,得到的损失函数做反向传播;一小批训练样本执行这个过程之后,利用梯度下降法更新没有被删除的神经元参数。
3.恢复被删除的神经元,即被删除的神经元参数保持原样(回复备份的参数);
4.重复上述过程
dropout 数学表达
由于dropout在训练时是随机将隐藏层节点设置为0的,所以在前向计算时需要添加一个概率流程。
上述为标准网络和dropout网络前向计算的流程,其中
为这一隐藏层的输入,
是权重向量,
是偏倚项,
服从伯努利分布,以概率p生成1,最终生成0-1向量,表明以概率p选择留下的隐藏层节点。
- 正常网络计算:
,
- dropout计算公式
,
,
由于我们在dropout过程中增加了一个概率过程实现随机drop隐藏层节点,所以在训练过程中计算出的参数 是基于概率转换后的输入值,所以在训练过程中需要做一个rescale,即 ;若在训练阶段未对模型参数做rescale,那么在测试阶段就得对每个神经元参数乘以p,这是因为在训练过程中隐层参数是可以随机丢弃的,但在测试集是无法drop的,那么这里就以期望输出作为最终输出,如一个神经元的输出是x,那么在训练的时候它有p的概率参与训练,(1-p)的概率丢弃,那么它输出的期望是px+(1-p)0=px。因此测试的时候把这个神经元的权重乘以p可以得到同样的期望。
dropout如何解决过拟合
(1)取平均
dropout掉不同的隐藏神经元就类似在训练不同的网络,随机删掉一半隐藏神经元导致网络结构已经不同,整个dropout过程就相当于对很多个不同的神经网络取平均。而不同的网络产生不同的过拟合,一些互为“反向”的拟合相互抵消就可以达到整体上减少过拟合。
(2)减少神经元之间的共线关系
因为dropout程序导致两个神经元不一定每次都在一个dropout网络中出现。这样权值的更新不再依赖于有固定关系的隐含节点的共同作用,阻止了某些特征仅仅在其它特定特征下才有效果的情况 。迫使网络去学习更加鲁棒的特征 ,这些特征在其它的神经元的随机子集中也存在。换句话说假如我们的神经网络是在做出某种预测,它不应该对一些特定的线索片段太过敏感,即使丢失特定的线索,它也应该可以从众多其它线索中学习一些共同的特征。从这个角度看dropout就有点像L1,L2正则,减少权重使得网络对丢失特定神经元连接的鲁棒性提高。
dropout 使用场景
dropout 常用于全连接网络,一般设置为0.5或03,而在卷积网络中由于卷积自身的稀疏化以及大量使用ReLU函数等原因,dropout在卷积网络中使用较少。
Dropout的numpy实现
import numpy as np
# 此处定义的dropout的参数level表示drop掉参数的比例
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
# 通过伯努利函数生成0-1向量,p表示生成1的概率,即保留神经元的概率
sample=np.random.binomial(n=1,p=retain_prob,size=x.shape) # n表示每个神经元需生成的次数;size表示总共需要调用函数的次数,即0-1向量的长度;
print (sample)
x *=sample # 利用0-1向量与输入的内积决定屏蔽哪些神经元
print(x)
x /= retain_prob #此处是rescale
return x
PyTorch中实现dropout
pytorch包内有封装好的dropout 函数,在torch.nn.functional函数中。
dropout(input, p=0.5, training=True, inplace=False)
- 其中p是随机置零的概率
import troch
import torch.nn.functional as F
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
# 定义多层神经网络
self.fc1 = torch.nn.Linear(8,6)
self.fc2 = torch.nn.Linear(6,4)
self.fc3 = torch.nn.Linear(4,1)
def forward(self,x):
x = F.relu(self.fc1(x)) # 8->6
x = F.dropout(x,p=0.5) #dropout 1 此处为dropout
x = F.relu(self.fc2(x)) #-6->4
x = F.dropout(x,p=0.5) # dropout 2 #此处为drouout
y_pred = torch.sigmoid(self.fc3(x)) # 4->1 ->sigmoid
# warnings.warn("nn.functional.sigmoid is deprecated. Use torch.sigmoid instead."
return y_pred
L1及L2正则化
参考资料
1) https://blog.csdn.net/program_developer/article/details/80737724
2)https://blog.csdn.net/wehung/article/details/89283583