深度学习正则化Tricks——dropout

drop Out——神经网络中的模型平均

写在前面

带我入机器学习的伟大导师Andrew Ng曾经做过一个非常好的比喻。他把深度学习比作火箭,对于一个火箭来说,最重要的一部分必然是引擎,而在这个领域,目前来看引擎的核心是神经网络。但是要让一个火箭运行,除了的有引擎还要有燃料。在深度学习领域,数据则充当了燃料的角色。

这里写图片描述

对于深度网络来说,模型的容量都很高(因为其具有很多层,每层具有很有神经元),一般来说都会大于实际问题需要的表示容量。在这样的情况下,如果训练数据不够,很容易导致模型简单的记住有限的训练数据,导致过拟合。因此,深度学习中许多Trick都是用于正则化,减小模型的泛化误差。这里主要记录下自己关于dropout的学习理解,有不正确的地方希望各位提出来。

什么是dropout

简单来说,dropout就是在神经网络训练过程中,每一个神经元(不包括输出层神经元)以一定的暂时概率被丢弃。这里丢弃是暂时性的,并不是说抛弃了,很有可能这一次被丢弃的神经元会出现在下一次训练的网络中。由于丢弃神经元的随机性,在每一次训练过程中,神经网络的结构可能都不同。训练结束以后,保留所有的节点用于测试。

这里写图片描述


为什么dropout可以提高泛化能力

  • 斯坦福CS231n课上面给出了一种形象解释:因为每次在训练过程中都会损失一些神经元,网络表达能力减小,为了保证训练结果的正确性,未被丢失的神经元不得不承担起更大的“责任”,因此在测试的时候会有更好的结果。

  • 一些神经元在训练过程中被丢失,这样会促使神经网络依赖更多的特征。

  • 训练过程中会随机丢失一些神经元,不同的过程丢失神经元不同,行程不同结构的网络。最后测试的时候,保留所有的神经元,相当于对前面所有的网络结构做了一个模型平均。
    这里解释一下为什么模型平均能够提高模型的泛化能力。
    模型平均奏效的原因是不同的模型通常不会在测试集上面产生完全相同的错误。
    考虑k个模型的例子。假设每个模型在每个例子上面的误差是 ϵi , 这个误差服从零均值方差为 E[ϵ2i]=v 且协方差是 E[ϵiϵj]=c 的多维正态分布。通过所有集成模型的平均预测的误差所得的误差是 1kiϵi 。 集成预测器平方误差的期望是:

E[(1kiϵi)2]=1k2E[i(ϵ2i+ijϵiϵj)]=1kv+k1kc

在误差完全相关,即c = v的情况下,均方误差为v,模型平均没有任何帮助,但是在误差完全不相关的,即 c= 0的情况下,均方误差个为 1kv ,这意味着模型平均的均方误差会随着模型数量增多而线性地减小。


在tensorflow中如何使用dropout

用MNIST为例,用CNN做分类器,其中使用了dropout, 直接上代码

from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

sess = tf.InteractiveSession()  #创建一个交互式的session

# 权重初始化方法
def weight_variable(shape):
    init = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(init)

# 偏置初始化方法
def bias_variable(shape):
    init = tf.constant(0.1, shape=shape)
    return tf.Variable(init)

# 构造卷积层
def conv2d(x, W):
    return tf.nn.conv2d(x, W,strides=[1, 1, 1, 1], padding='SAME')

# 构造pooling层
def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

# 创建占位符
x = tf.placeholder(tf.float32, [None, 784]) # 用于把数据喂入网络中
y_ = tf.placeholder(tf.float32, [None, 10]) # 用于把标签喂入网络中
keep_prob = tf.placeholder(tf.float32) # dropout的占位符,用于输入我们设置的dropout

x_image = tf.reshape(x, [-1, 28, 28, 1])

# 第一层,包括卷积、pooling
W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
h_conv1 = conv2d(x_image, W_conv1)
h_pool1 = max_pool_2x2(h_conv1)

# 第二层,包括卷积、pooling
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = conv2d(h_pool1, W_conv2)
h_pool2 = max_pool_2x2(h_conv2)

# 全连接层1
W_fc1 = weight_variable([7*7*64, 1000])
b_fc1 = bias_variable([1000])
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

# dropout,以keep_prob的概率随机丢弃一些神经元
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

# 全连接层2
W_fc2 = weight_variable([1000, 10])
b_fc2 = bias_variable([10])
y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2))

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y_conv), axis=1))
correct_prediction = tf.equal(tf.argmax(y_, 1), tf.argmax(y_conv, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

train = tf.train.AdamOptimizer(0.0001).minimize(cross_entropy)

tf.global_variables_initializer().run()
for i in range(1000):
    batch = mnist.train.next_batch(128)
    if i % 100 == 0:
        train_accuracy = accuracy.eval(feed_dict={x: batch[0], y_: batch[1], keep_prob:1.0})
        print("step: %d, accuracy %g" %(i, train_accuracy))
    train.run(feed_dict={x: batch[0], y_: batch[1], keep_prob:0.75})

print("test accuracy %g" %accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob:1.0}))

drop out一些小扩展

权重比例推断规则:设置drop_out = p,训练结束之后把权重乘以p,然后像平常一样使用模型。这个结论详细介绍在benjio的deep learning第七章中有更加详细的介绍。这里举一个例子帮助理解:
这里写图片描述
在上述例子中,drop_out = 0.5,根据模型平均的想法,最终使用的时候需要对最终的权重做一个乘以0.5的操作。


写在后面
Benjor在介绍完dropout后写到,另一种深度学习算法——batch normalization有时会使Dropout变得没有必要,博主在一个项目中确实尝试了一下,batch normalization 真神器,BN之后,dropout、weight_decay、learning_rate变得不关键了。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
深度学习tricks是指在深度学习模型训练过程中使用的一些技巧和策略,旨在提高模型的性能和训练效果。以下是一些常用的深度学习tricks: 1. 数据增强(Data Augmentation):通过对原始数据进行随机变换和扩充,生成更多的训练样本,以增加模型的泛化能力。 2. 批归一化(Batch Normalization):在每个小批量数据上进行归一化操作,有助于加速模型的收敛速度,提高模型的稳定性和泛化能力。 3. 学习率调整(Learning Rate Schedule):根据训练的进程动态地调整学习率,例如使用学习率衰减或者学习率预热等策略,以提高模型的收敛性能。 4. 正则化(Regularization):通过添加正则化项,如L1正则化或L2正则化,限制模型的复杂度,防止过拟合。 5. 提前停止(Early Stopping):在训练过程中监控验证集上的性能指标,当性能不再提升时停止训练,以避免过拟合。 6. 参数初始化(Parameter Initialization):合适的参数初始化可以帮助模型更快地收敛和更好地泛化,常用的初始化方法包括Xavier初始化和He初始化等。 7. 梯度裁剪(Gradient Clipping):限制梯度的范围,防止梯度爆炸或梯度消失问题,提高模型的稳定性。 8. 集成学习(Ensemble Learning):通过结合多个模型的预测结果,可以提高模型的泛化能力和鲁棒性。 9. 迁移学习(Transfer Learning):利用已经训练好的模型在新任务上进行微调,可以加快模型的训练速度和提高模型的性能。 10. 深度网络结构设计:合理设计网络结构,包括层数、宽度、卷积核大小等,可以提高模型的表达能力和学习能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值