如何使用Dropout去防止过拟合

本文深入解析深度学习中Dropout技术,通过随机丢弃神经元防止过拟合,提升模型泛化能力。并提供了在二层神经网络中实现Dropout的详细代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Dropout的介绍
dropout是指在深度学习网络的训练过程中,对于神经网络单元,按照一定的概率将其暂时从网络中丢弃。注意是暂时,对于随机梯度下降来说,由于是随机丢弃,故而每一个mini-batch都在训练不同的网络。dropout是CNN中防止过拟合提高效果的一个大杀器,但对于其为何有效,却众说纷纭。
Dropout的思想是训练整体DNN,并平均整个集合的结果,而不是训练单个DNN。DNNs是以概率P舍弃部分神经元,其它神经元以概率q=1-p被保留,舍去的神经元的输出都被设置为零。
Dropout的出现很好的可以解决这个问题,每次做完dropout,相当于从原始的网络中找到一个更瘦的网络,如下图所示:
这里写图片描述
上图为Dropout的可视化表示,左边是应用Dropout之前的网络,右边是应用了Dropout的同一个网络。因而,对于一个有N个节点的神经网络,有了dropout后,就可以看做是2n个模型的集合了,但此时要训练的参数数目却是不变的,这就解脱了费时的问题。
更详细介绍请参考:
https://blog.youkuaiyun.com/stdcoutzyx/article/details/49022443
https://yq.aliyun.com/articles/68901

二、在二层NN网络中使用Dropout功能
具体代码如下:

#-*-coding:utf-8-*-
import tensorflow as tf
from sklearn.datasets import load_digits
from sklearn.cross_validation import train_test_split
from sklearn.preprocessing import LabelBinarizer

# load data
D = load_digits()
#print(D)   #data;target;target_names
X = D.data           #(1797,64)
Y = D.target         #(1797,)
Z = D.target_names   #[0 1 2 3 4 5 6 7 8 9] (10,)
print(X,X.shape)
print(Z,Z.shape)
y = LabelBinarizer().fit_transform(Y)  #变为01向量,大小=(1797, 10)
print(y,y.shape)

train_x,test_x,train_y,test_y = train_test_split(X,y,test_size=.3)

def add_layer(inputs,in_size,out_size,layer_name,activation_function=None):
    Weights = tf.Variable(tf.random_normal([in_size, out_size]), name='W')
    biases = tf.Variable(tf.zeros([1, out_size]) + 0.1, name='b')
    Wx_plus_b = tf.matmul(inputs, Weights) + biases
    Wx_plus_b = tf.nn.dropout(Wx_plus_b,keep_prob)  #dropout掉50%的结果

    if activation_function is None:  # 如何激活函数为空,则是线性函数
        outputs = Wx_plus_b
    else:
        outputs = activation_function(Wx_plus_b)
    tf.summary.histogram(layer_name+'/outputs',outputs)
    return outputs

# define placeholder for inputs to network
keep_prob = tf.placeholder(tf.float32)
xs = tf.placeholder(tf.float32,[None,64]) #8*8
ys = tf.placeholder(tf.float32,[None,10])

# add output layer【2层网络input——hidden——output】
hidden_layer = add_layer(xs,64,50,'L1',activation_function=tf.nn.tanh)
Op = add_layer(hidden_layer,50,10,'L2',activation_function=tf.nn.softmax)

# the loss between prediction and real data
loss = tf.reduce_mean(-tf.reduce_sum(ys*tf.log(Op),
                                     reduction_indices=[1]))
tf.summary.scalar('loss',loss)
train_step = tf.train.GradientDescentOptimizer(0.6).minimize(loss)

# summary writer goes in here
sess = tf.Session()
merged = tf.summary.merge_all()
train_writer = tf.summary.FileWriter("logsDO/train",sess.graph)
test_writer = tf.summary.FileWriter("logsDO/test",sess.graph)

sess.run(tf.global_variables_initializer())

for i in range(1000):
    sess.run(train_step,feed_dict={xs:train_x,ys:train_y,keep_prob:0.3})  #Dropout保留50%的神经元
    if i%50==0:
        # record loss
        train_result = sess.run(merged, feed_dict={xs: train_x, ys: train_y,keep_prob:1}) #不dropout任务东西
        test_result = sess.run(merged,feed_dict={xs:test_x,ys:test_y,keep_prob:1})

        train_writer.add_summary(train_result,i)
        test_writer.add_summary(test_result,i)

上述代码中,我们主要在:
1)add_layer()函数中把W*x+b进行dropout;

Wx_plus_b = tf.matmul(inputs, Weights) + biases
    Wx_plus_b = tf.nn.dropout(Wx_plus_b,keep_prob)  #dropout掉keep_prob=50%的结果

2)在定义变量时定义一个keep_prob值

keep_prob = tf.placeholder(tf.float32)
xs = tf.placeholder(tf.float32,[None,64]) #8*8
ys = tf.placeholder(tf.float32,[None,10])

3)在模型训练过程中修改输入值

for i in range(1000):
    sess.run(train_step,feed_dict={xs:train_x,ys:train_y,keep_prob:0.3})  #Dropout保留50%的神经元
    if i%50==0:
        # record loss
        train_result = sess.run(merged, feed_dict={xs: train_x, ys: train_y,keep_prob:1}) #不dropout任务东西
        test_result = sess.run(merged,feed_dict={xs:test_x,ys:test_y,keep_prob:1})

        train_writer.add_summary(train_result,i)
        test_writer.add_summary(test_result,i)

keep_prob:0.3(也可以取其他值,如0.5,0.6,…),在本实验中,取0.3时结果较好。

三、查看loss结果图
在代码中将其graph保存在当前目录下的logsDO/文件夹中。

train_writer = tf.summary.FileWriter("logsDO/train",sess.graph)
test_writer = tf.summary.FileWriter("logsDO/test",sess.graph)

查看步骤:
1)运行代码;
2)代码“运行”——cmd;
3) 在命令窗口中输入d:回车;(即将其定位到D盘)
4)输入命令
tensorboard –logdir=ProgramFiles64\Python364\WorkSpaces\logsDO
然后回车,等待结果如下:
TensorBoard 0.4.0rc3 at http://DESKTOP-PAF8N1L:6006 (Press CTRL+C to quit)
5)将其网址http://DESKTOP-PAF8N1L:6006复制到谷歌(我试了360浏览器不能打开)浏览器中,即可打开graph。如下图所示
这里写图片描述
这里写图片描述
图1 没有Dropout的结果
这里写图片描述
图2 Dropout之后的结果图

它们的区别,可以看图中两条线的重合程度,有Dropout的训练loss和test的loss几乎重合。

### Dropout 技术防止过拟合的工作原理 Dropout 是一种用于深度学习中的正则化技术,其主要目的是通过改变神经网络训练过程来减少过拟合现象的发生。具体来说,在训练过程中,Dropout 方法会以一定概率 \( p \) (通常设置为 0.5)随机地将某些隐藏层神经元的输出置零[^1]。这意味着在每一次前向传播和反向传播的过程中,只有部分神经元参与计算。 #### 训练阶段的行为 在训练阶段,Dropout 的核心机制在于动态调整网络结构。由于每次迭代都会随机丢弃一部分神经元,因此实际上是在训练多个不同的子网络。这些子网络共享权重参数,并且最终的预测结果是由所有可能的子网络共同决定的。这种方法类似于集成学习中的 Bagging 思想——通过对多个模型进行平均从而提高泛化能力[^3]。 此外,当某个特定神经元被禁用时,其他未被禁用的神经元就需要承担起补偿责任,这样就减少了单个神经元对整体性能的影响程度。换句话说,它降低了特征检测器之间的相互依赖关系,促使每一个单独的单元更加鲁棒地提取有用的信息而不是仅仅依靠邻居节点的支持[^2]。 #### 测试阶段的行为 到了测试或者推理阶段,则不再应用 dropout 操作。此时所有的神经元都将重新启用,不过为了保持一致性(即保证训练与推断期间期望一致),每个激活值会被缩放至原来的比例因子 \( (1-p) \) 。这一操作确保了即使没有继续执行 dropout ,整个系统的响应仍然能够反映之前所学到的知识模式而不会发生突变。 ```python import torch.nn as nn class NeuralNetwork(nn.Module): def __init__(self, input_size, hidden_size, output_size, drop_prob=0.5): super(NeuralNetwork, self).__init__() self.fc1 = nn.Linear(input_size, hidden_size) self.relu = nn.ReLU() self.dropout = nn.Dropout(p=drop_prob) self.fc2 = nn.Linear(hidden_size, output_size) def forward(self, x): out = self.fc1(x) out = self.relu(out) out = self.dropout(out) # Apply dropout during training only. out = self.fc2(out) return out ``` 上述代码展示了如何在一个简单的全连接神经网络中实现 Dropout 层的功能。注意 `nn.Dropout` 类会在训练模式下自动按照指定的概率屏蔽输入张量的部分元素;而在评估模式 (`model.eval()`) 下,默认情况下该功能会被关闭并仅保留必要的校准步骤。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值