目录
- 一、Dropout出现的原因
- 二、什么是Dropout?
- 三、为什么Dropout解决过拟合?
- 3.1 取平均的作用
- 3.2 减少神经元间复杂的共适应关系
- 四、实现Dropout—— pytorch
- example 1
- example 2
- example 3
- 设置dropout参数技巧
一、Dropout出现的原因
在机器学习的模型中
- 如果模型的参数太多,而训练样本又太少,训练出来的模型很容易产生过拟合的现象
- 在训练神经网络的时候经常会遇到过拟合的问题
- 过拟合具体表现在:
- 模型在训练数据上损失函数较小,预测准确率较高;
- 但是在测试数据上损失函数比较大,预测准确率较低。
过拟合是很多机器学习的通病。
- 如果模型过拟合,那么得到的模型几乎不能用。
- 为了解决过拟合问题,一般会采用模型集成的方法,即训练多个模型进行组合。
- 此时,训练模型费时就成为一个很大的问题,不仅训练多个模型费时,测试多个模型也是很费时。
综上所述,训练深度神经网络的时候,总是会遇到两大缺点:
- 容易过拟合
- 费时
Dropout可以比较有效的缓解过拟合的发生,在一定程度上达到正则化的效果。
二、什么是Dropout?
Dropout
- 用来解决overfitting的,如果在训练集上实验效果就不理想,那么加了dropout也救不了
- Dropout常作用在多层感知机的隐藏层输出上(CNN类用得不多)
Dropout说简单一点就是:
- 在前向传播的时候,让某个神经元的激活值以一定的概率p停止工作
- 这样可以使模型泛化性更强
- 因为它不会太依赖某些局部的特征
- 如图所示
三、为什么Dropout解决过拟合?
3.1 取平均的作用
标准的模型, 即没有dropout
-
用相同的训练数据去训练5个不同的神经网络,一般会得到5个不同的结果
-
此时可以采用 “5个结果取均值”或者“多数取胜的投票策略”去决定最终结果
-
这种“综合起来取平均”的策略通常可以有效防止过拟合问题
-
因为不同的网络可能产生不同的过拟合,取平均则有可能让一些“相反的”拟合互相抵消。
dropout掉不同的隐藏神经元就类似在训练不同的网络
- 随机删掉一半隐藏神经元导致网络结构已经不同
- 整个dropout过程就相当于对很多个不同的神经网络取平均
- 而不同的网络产生不同的过拟合,一些互为“反向”的拟合相互抵消就可以达到整体上减少过拟合
3.2 减少神经元间复杂的共适应关系
因为dropout程序导致两个神经元不一定每次都在一个dropout网络中出现
- 这样权值的更新不再依赖于有固定关系的隐含节点的共同作用
- 阻止了某些特征仅仅在其它特定特征下才有效果的情况
- 迫使网络去学习更加鲁棒的特征 ,这些特征在其它的神经元的随机子集中也存在
换句话说假如神经网络是在做出某种预测,它不应该对一些特定的线索片段太过敏感
- 即使丢失特定的线索,它也应该可以从众多其它线索中学习一些共同的特征
- 从这个角度看
dropout
就有点像L1,L2
正则 - 减少权重使得网络对丢失特定神经元连接的鲁棒性提高
四、实现Dropout—— pytorch
Dropout
- 训练的时候
- 需要声明
model.train()
(不声明也行,因为默认是train状态)
- 需要声明
- 测试的时候
- 需要声明
model.eval()
- 如果不希望开启dropout进行训练,所有的神经元都参与前向传播和反向传播的话,在训练阶段开启前声明
model.eval()
即可
- 需要声明
example 1
#导入库
import torch
#神经网络结构声明
net=torch.nn.Sequential(
torch.nn.Linear(1,16),
torch.nn.Dropout(p=0.5),
torch.nn.ReLU(),
torch.nn.Linear(16,2)
)
net.train()
net.eval()
example 2
Sequential(
(0): Linear(in_features=1, out_features=16, bias=True)
(1): Dropout(p=0.5, inplace=False)
(2): ReLU()
(3): Linear(in_features=16, out_features=2, bias=True)
)
example 3
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
设置dropout参数技巧
决定Dropout之前
- 需要先判断是否模型过拟合
先dropout=0
, 训练后得到模型的一些指标(比如: F1, Accuracy, AP
)
比较train
数据集和test
数据集的指标。
- 过拟合:尝试下面的步骤。
- 欠拟合:尝试调整模型的结构,暂时忽略下面步骤。
Dropout设置成0.4-0.6
之间, 再次训练得到模型的一些指标。
- 如果过拟合明显好转,但指标也下降明显,可以尝试减少dropout(0.2)
- 如果过拟合还是严重,增加dropout(0.2)
- 重复上面的步骤多次,就可以找到理想的dropout值