深度学习系列(1)| Dropout VS Batch Normalization? 是时候放弃Dropout了

Dropout是过去几年非常流行的正则化技术,可有效防止过拟合的发生。但从深度学习的发展趋势看,Batch Normalizaton(简称BN)正在逐步取代Dropout技术,特别是在卷积层。本文将首先引入Dropout的原理和实现,然后观察现代深度模型Dropout的使用情况,并与BN进行实验比对,从原理和实测上来说明Dropout已是过去式,大家应尽可能使用BN技术。

一、Dropout原理

  根据wikipedia定义,dropout是指在神经网络中丢弃掉一些隐藏或可见单元。通常来说,是在神经网络的训练阶段,每一次迭代时,都会随机选择一批单元,让其被暂时忽略掉,所谓的忽略是不让这些单元参与前向推理和后向传播。

   

  上图是标准的神经网络,经过dropout后,则变成如下图:

  

  一般来说,我们在可能发生过拟合的情况下才会使用dropout等正则化技术。那什么时候可能会发生呢?比如神经网络过深,或训练时间过长,或没有足够多的数据时。那为什么dropout能有效防止过拟合呢?可以理解为,我们每次训练迭代时,随机选择一批单元不参与训练,这使得每个单元不会依赖于特定的前缀单元,因此具有一定的独立性;同样可以看成我们拿同样的数据在训练不同的网络,每个网络都有可能过拟合,但迭代多次后,这种过拟合会被抵消掉。

  要注意的是,dropout是体现在训练环节,训练完成后,我们认为所有的单元都被训练好了,在验证或测试阶段,我们是拿完整的神经网络去验证或测试。

二、Dropout具体实现

  以keras为例,其代码为:keras.backend.dropout(x, level, noise_shape=None, seed=None),其中x指的是输入参数,level则是keep-prob,也就是这个单元有多少概率会被设置为0。

import tensorflow.keras.backend as K

input = K.random_uniform_variable(shape=(3, 3), low=0, high=1)

print("dropout with keep-prob 0.5:", K.eval(K.dropout(input, 0.5)))
print("dropout with keep-prob 0.2:", K.eval(K.dropout(input, 0.2)))
print("dropout with keep-prob 0.8:", K.eval(K.dropout(input, 0.8)))

  看看输出结果:

dropout with keep-prob 0.5:
[[1.190095  0.        1.2999489]
 [0.        0.3164637 0.       ]
 [0.        0.        0.       ]]
dropout with keep-prob 0.2:
[0.74380934 0.67237484 0.81246805]
 [0.8819132  0.19778982 1.2349881 ]
 [1.0369372  0.5945368  0.        ]]
dropout with keep-prob 0.8:
[[0.        0.        0.       ]
 [0.        0.        4.9399524]
 [4.147749  2.3781471 0.       ]]

  可以看出,level值越大,每个单元成为0的概率也就越大。

  在具体的keras应用中,dropout通常放在激活函数后,比如:

model=keras.models.Sequential()
model.add(keras.layers.Dense(150, activation="relu"))
model.add(keras.layers.Dropout(0.5))

三、Dropout正在被抛弃

  随着深度学习的发展,Dropout在现代卷积架构中,已经逐步被BN取代,BN也同样拥有不亚于Dropout的正则化效果。

  至于为何Dropout不再受青睐,原因如下:

  • Dropout在卷积层的正则效果有限。相比较于全连接层,卷积层的训练参数较少,激活函数也能很好地完成特征的空间转换,因此正则化效果在卷积层不明显;
  • Dropout也过时了,能发挥其作用的地方在全连接层,可当代的深度网络中,全连接层也在慢慢被全局平均池化曾所取代,不但能减低模型尺寸,还可以提升性能。

  事实上,我们可以看看keras实现的现代经典模型,就可以窥之dropout目前的处境。打开keras的地址:https://github.com/keras-team/keras-applications

  纵观无论是VGG、ResNet、Inception、MobileNetV2等模型,都不见了Dropout踪影。唯独在MobileNetV1模型里,还可以找到Dropout,但不是在卷积层;而且在MobileNetV2后,已经不再有全连接层,而是被全局平均池化层所取代。如下图所示:

  

  其他模型也类似,纷纷抛弃了Dropout和全连接层。

四、Dropout VS BatchNormalization

  我们需要做一个简单实验来验证上述理论的成立,实验分五种测试模型:

  • 没有使用Dropout,也没有使用BN;
  • 使用了Dropout,不使用BN,使训练单元为0的概率为0.2;
  • 使用了Dropout,不使用BN,使训练单元为0的概率为0.5;
  • 使用了Dropout,不使用BN,使训练单元为0的概率为0.8;
  • 使用了BN,不使用Dropout

  代码如下:

import keras
from keras.datasets import cifar10
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten, BatchNormalization
from keras.layers import Conv2D, MaxPooling2D
from matplotlib import pyplot as plt
import numpy as np

# 为保证公平起见,使用相同的随机种子
np.random.seed(7)
batch_size = 32
num_classes = 10
epochs = 40
data_augmentation = True

# The data, split between train and test sets:
(x_train, y_train), (x_test, y_test) = cifar10.load_data()

# Convert class vectors to binary class matrices.
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

x_train = x_train.astype(‘float32‘)
x_test = x_test.astype(‘float32‘)
x_train /= 255
x_test /= 255

def model(bn=False, dropout=False, level=0.5):
    model = Sequential()
    model.add(Conv2D(32, (3, 3), padding=‘same‘, input_shape=x_train.shape[1:]))
    if bn:
        model.add(BatchNormalization())
    model.add(Activation(‘relu‘))
    model.add(Conv2D(32, (3, 3)))
    if bn:
        model.add(BatchNormalization())
    model.add(Activation(‘relu‘))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    if dropout:
        model.add(Dropout(level))

    model.add(Conv2D(64, (3, 3), padding=‘same‘))
    if bn:
        model.add(BatchNormalization())
    model.add(Activation(‘relu‘))
    model.add(Conv2D(64, (3, 3)))
    if bn:
        model.add(BatchNormalization())
    model.add(Activation(‘relu‘))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    if dropout:
        model.add(Dropout(level))

    model.add(Flatten())
    model.add(Dense(512))
    if bn:
        model.add(BatchNormalization())
    model.add(Activation(‘relu‘))
    if dropout:
        model.add(Dropout(level))
    model.add(Dense(num_classes))
    model.add(Activation(‘softmax‘))
    if bn:
        opt = keras.optimizers.rmsprop(lr=0.001, decay=1e-6)
    else:
        opt = keras.optimizers.rmsprop(lr=0.0001, decay=1e-6)

    model.compile(loss=‘categorical_crossentropy‘,
                             optimizer=opt,
                             metrics=[‘accuracy‘])

    # 使用数据增强获取更多的训练数据
    datagen = ImageDataGenerator(width_shift_range=0.1, height_shift_range=0.1, horizontal_flip=True)
    datagen.fit(x_train)
    history = model.fit_generator(datagen.flow(x_train, y_train, batch_size=batch_size), epochs=epochs,
                                  validation_data=(x_test, y_test), workers=4)
    return history

no_dropout_bn_history = model(False, False)
dropout_low_history = model(False, True, 0.2)
dropout_medium_history = model(False, True, 0.5)
dropout_high_history = model(False, True, 0.8)
bn_history = model(True, False)

# 比较多种模型的精确度
plt.plot(no_dropout_bn_history.history[‘val_acc‘])
plt.plot(dropout_low_history.history[‘val_acc‘])
plt.plot(dropout_medium_history.history[‘val_acc‘])
plt.plot(dropout_high_history.history[‘val_acc‘])
plt.plot(bn_history.history[‘val_acc‘])
plt.title(‘Model accuracy‘)
plt.ylabel(‘Validation Accuracy‘)
plt.xlabel(‘Epoch‘)
plt.legend([‘No bn and dropout‘, ‘Dropout with 0.2‘, ‘Dropout with 0.5‘, ‘Dropout with 0.8‘, ‘BN‘], loc=‘lower right‘)
plt.grid(True)
plt.show()

# 比较多种模型的损失率
plt.plot(no_dropout_bn_history.history[‘val_loss‘])
plt.plot(dropout_low_history.history[‘val_loss‘])
plt.plot(dropout_medium_history.history[‘val_loss‘])
plt.plot(dropout_high_history.history[‘val_loss‘])
plt.plot(bn_history.history[‘val_loss‘])
plt.title(‘Model loss‘)
plt.ylabel(‘Loss‘)
plt.xlabel(‘Epoch‘)
plt.legend([‘No bn and dropout‘, ‘Dropout with 0.2‘, ‘Dropout with 0.5‘, ‘Dropout with 0.8‘, ‘BN‘], loc=‘upper right‘)
plt.grid(True)
plt.show()

  各模型的验证准确率如下图:

  各模型的验证损失率如下:

  

  由上图可知,Dropout在不同概率下,其表现差异较大,相对来说,Dropout with 0.2的表现接近于 No bn and dropout(可以理解为Dropout的keep-prob为1的版本)。总体来说,BN在准确率和损失率上表现要优于Dropout,比如准确率上BN能达到85%,而Dropout接近为79%。

五、结论

  无论是理论上的分析,还是现代深度模型的演变,或者是实验的结果,BN技术已显示出其优于Dropout的正则化效果,我们也是时候放弃Dropout,投入BN的怀抱了。  

参考资料:https://www.cnblogs.com/hutao722/p/9946047.html

原文地址:https://www.cnblogs.com/SupremeBoy/p/12258424.html

时间: 2024-10-09 09:15:56

深度学习系列(1)| Dropout VS Batch Normalization? 是时候放弃Dropout了的相关文章

【深度学习系列3】 Mariana CNN并行框架与图像识别

[深度学习系列3] Mariana CNN并行框架与图像识别 本文是腾讯深度学习系列文章的第三篇,聚焦于腾讯深度学习平台Mariana中深度卷积神经网络Deep CNNs的多GPU模型并行和数据并行框架. 将深度卷积神经网络(Convolutional Neural Networks, 简称CNNs)用于图像识别在研究领域吸引着越来越多目光.由于卷积神经网络结构非常适合模型并行的训练,因此以模型并行+数据并行的方式来加速Deep CNNs训练,可预期取得较大收获.Deep CNNs的单机多GPU

【深度学习系列2】Mariana DNN多GPU数据并行框架

[深度学习系列2]Mariana DNN多GPU数据并行框架 本文是腾讯深度学习系列文章的第二篇,聚焦于腾讯深度学习平台Mariana中深度神经网络DNN的多GPU数据并行框架. 深度神经网络(Deep Neural Networks, 简称DNN)是近年来机器学习领域中的研究热点[1][2],产生了广泛的应用.DNN具有深层结构.数千万参数需要学习,导致训练非常耗时.GPU有强大的计算能力,适合于加速深度神经网络训练.DNN的单机多GPU数据并行框架是Mariana的一部分,Mariana技术

【深度学习系列】关于PaddlePaddle的一些避“坑”技巧

最近除了工作以外,业余在参加Paddle的AI比赛,在用Paddle训练的过程中遇到了一些问题,并找到了解决方法,跟大家分享一下: PaddlePaddle的Anaconda的兼容问题 之前我是在服务器上安装的PaddlePaddle的gpu版本,我想把BROAD数据拷贝到服务器上面,结果发现我们服务器的22端口没开,不能用scp传上去,非常郁闷,只能在本地训练.本机mac的显卡是A卡,所以只能装cpu版本的,安装完以后,我发现运行一下程序的时候报错了: 1 import paddle.v2 a

深度学习系列(2) | Global Average Pooling是否可以替代全连接层?

深度学习系列 | Global Average Pooling是否可以替代全连接层? Global Average Pooling(简称GAP,全局池化层)技术最早提出是在这篇论文(第3.2节)中,被认为是可以替代全连接层的一种新技术.在keras发布的经典模型中,可以看到不少模型甚至抛弃了全连接层,转而使用GAP,而在支持迁移学习方面,各个模型几乎都支持使用Global Average Pooling和Global Max Pooling(GMP). 然而,GAP是否真的可以取代全连接层?其背

使用腾讯云 GPU 学习深度学习系列之二:Tensorflow 简明原理【转】

转自:https://www.qcloud.com/community/article/598765?fromSource=gwzcw.117333.117333.117333 这是<使用腾讯云 GPU 学习深度学习>系列文章的第二篇,主要介绍了 Tensorflow 的原理,以及如何用最简单的Python代码进行功能实现.本系列文章主要介绍如何使用 腾讯云GPU服务器 进行深度学习运算,前面主要介绍原理部分,后期则以实践为主. 往期内容: 使用腾讯云 GPU 学习深度学习系列之一:传统机器学

【深度学习系列1】 深度学习在腾讯的平台化和应用实践(转载)

转载:原文链接 [深度学习系列1] 深度学习在腾讯的平台化和应用实践 引言:深度学习是近年机器学习领域的重大突破,有着广泛的应用前景.随着Google公开 Google Brain计划,业界对深度学习的热情高涨.腾讯在深度学习领域持续投入,获得了实际落地的产出.我们准备了四篇文章,阐述深度学习的原理和在腾讯的实 践,介绍腾讯深度学习平台Mariana,本文为第一篇. 深度学习(Deep Learning)是近年来机器学习领域的热点,在语音识别.图像识别等领域均取得了突破性进展.腾讯提供广泛的互联

【深度学习系列4】深度学习及并行化实现概述

[深度学习系列4]深度学习及并行化实现概述 摘要: 深度学习可以完成需要高度抽象特征的人工智能任务,如语音识别.图像识别和检索.自然语言理解等.深层模型是包含多个隐藏层的人工神经网络,多层非线性结构使其具备强大的特征表达能力和对复杂任务建模能力.训练深层模型是长期以来的难题,近年来以层次化.逐层初始化为代表的一系列方法的提出给训练深层模型带来了希望,并在多个应用领域获得了成功.深层模型的并行化框架和训练加速方法是深度学习走向实用的重要基石,已有多个针对不同深度模型的开源实现,Google.Fac

基于TensorFlow的深度学习系列教程 2——常量Constant

前面介绍过了Tensorflow的基本概念,比如如何使用tensorboard查看计算图.本篇则着重介绍和整理下Constant相关的内容. 基于TensorFlow的深度学习系列教程 1--Hello World! 常量的概念 在tensorflow中,数据分为几种类型: 常量Constant.变量Variable.占位符Placeholder.其中: 常量:用于存储一些不变的数值,在计算图创建的时候,调用初始化方法时,直接保存在计算图中 变量:模型训练的参数,比如全连接里面的W和bias 占

【深度学习系列】用PaddlePaddle和Tensorflow实现AlexNet

上周我们用PaddlePaddle和Tensorflow实现了图像分类,分别用自己手写的一个简单的CNN网络simple_cnn和LeNet-5的CNN网络识别cifar-10数据集.在上周的实验表现中,经过200次迭代后的LeNet-5的准确率为60%左右,这个结果差强人意,毕竟是二十年前写的网络结构,结果简单,层数也很少,这一节中我们讲讲在2012年的Image比赛中大放异彩的AlexNet,并用AlexNet对cifar-10数据进行分类,对比上周的LeNet-5的效果. 什么是AlexN