batch norm、relu、dropout 等的相对顺序和BN、dropout的几个问题和思考

2023-05-16

总结:BN和dropout一般不同时使用,如果一定要同时使用,可以将dropout放置于BN后面。

 1.batch norm、relu、dropout 等的相对顺序

Ordering of batch normalization and dropout in TensorFlow?

在 Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift 一文中,作者指出,“we would like to ensure that for any parameter values, the network always produces activations with the desired distribution”(produces activations with the desired distribution,为激活层提供期望的分布,即先让分布标准化,然后再激活)。

因此 Batch Normalization 层恰恰插入在 Conv 层或全连接层之后,而在 ReLU等激活层之前。而对于 dropout 则应当置于 activation layer 之后。

-> CONV/FC -> BatchNorm -> ReLu(or other activation) -> Dropout -> CONV/FC ->;

 

1、BN的scale初始化

scale一般初始化为1.0。

联想到权重初始化时,使用relu激活函数时若采用随机正太分布初始化权重的公式是sqrt(2.0/Nin),其中Nin是输入节点数。即比一般的方法大了2的平方根(原因是relu之后一半的数据变成了0,所以应乘以根号2)。

那么relu前的BN,是否将scale初始化为根号2也会加速训练?

这里主要有个疑点:BN的其中一个目的是统一各层的方差,以适用一个统一的学习率。那么若同时存在sigmoid、relu等多种网络,以上方法会不会使得统一方差以适应不同学习率的效果打了折扣?

没来得及试验效果,如果有试过的朋友请告知下效果。

2、dropout后的标准差改变问题

实践发现droput之后改变了数据的标准差(令标准差变大,若数据均值非0时,甚至均值也会产生改变)。

如果同时又使用了BN归一化,由于BN在训练时保存了训练集的均值与标准差。dropout影响了所保存的均值与标准差的准确性(不能适应未来预测数据的需要),那么将影响网络的准确性。

若输入数据为正太分布,只需要在dropout后乘以sqrt(0.5)即可恢复原来的标准差。但是对于非0的均值改变、以及非正太分布的数据数据,又有什么好的办法解决呢?

3、稀疏自编码的稀疏系数

稀疏自编码使用一个接近0的额外惩罚因子来使得隐层大部分节点大多数时候是抑制的,本质上使隐层输出均值为负数(激活前),例如惩罚因子为0.05,对应sigmoid的输入为-3.5,即要求隐层激活前的输出中间值为-3.5,那么,是不是可以在激活前加一层BN,beta设为-3.5,这样学起来比较快?

经过测试,的确将BN的beta设为负数可加快训练速度。因为网络初始化时就是稀疏的。

但是是不是有什么副作用,没有理论上的研究。

4、max pooling是非线性的,avg pooling是线性的

5.Dropout VS Batch Normalization使用效果对比

结论:无论是理论上的分析,还是现代深度模型的演变,或者是实验的结果,BN技术已显示出其优于Dropout的正则化效果。

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

 5.1、Dropout原理

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

   

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

  

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

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

    5.2、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))

5.3、Dropout正在被抛弃

  随着深度学习的发展,Dropout在现代卷积架构中,已经逐步被BN(想要了解BN,大家可以参见我之前写的 深度学习基础系列(七)| Batch Normalization 一文,这里不再赘述)取代,BN也同样拥有不亚于Dropout的正则化效果。

  “We presented an algorithm for constructing, training, and performing inference with batch-normalized networks. The resulting networks can be trained with saturating nonlinearities, are more tolerant to increased training rates, and often do not require Dropout for regularization.” -Ioffe and Svegedy 2015

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

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

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

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

  

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

5.4、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%。

5.5、结论

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

 

参考:

https://blog.csdn.net/weixin_30819085/article/details/95617900

https://blog.csdn.net/lecturekeke/article/details/78963022

https://www.cnblogs.com/hutao722/p/9946047.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

batch norm、relu、dropout 等的相对顺序和BN、dropout的几个问题和思考 的相关文章

  • 运维大镖客:Linux 合规配置脚本第一版

    还在为Linux合规配置检查不过关而发愁吗 xff1f 最新的配置合规脚本来啦 xff01 20220609 作者注 xff1a 之后的脚本将会在新的网络空间安全付费专栏发布 xff0c 如需要更新的版本 xff0c 请移步专栏观看 spa
  • MongoDB 4.2 数据迁移与备份指南

    MongoDB 4 2 数据迁移与备份指南 来源于MongoDB Manual 4 2 https docs mongodb com v4 2 tutorial restore replica set from backup 原文 xff1
  • Minio 代理 Alibaba Cloud OSS

    Minio 代理 Alibaba Cloud OSS 在2017年12月份Minio引入Aliyun OSS 支持到master分支 xff0c 但是在2020年4月因为License问题导致阿里云OSS支持被移除 xff0c 后来2020
  • Rancher 2.4.x 单容器证书过期&证书轮换方法

    Rancher 2 4 x 官方文档之证书轮换 https rancher2 docs rancher cn docs rancher2 cluster admin certificate rotation index 错误现象 xff1a
  • Docker与Firewalld冲突怎么办?教你几招搞定docker网络

    docker ce默认会采用桥接网络 xff0c 它会通过iptables来管理它的容器之间的通信和容器与宿主机的通信 xff0c 如果同时启用了firewalld服务 xff0c 他们都会对iptables里面的转发链写入规则 xff0c
  • 当ChatGPT遇上StableDiffusion ChatGPT指导StableDiffusion绘画

    ChatGPT指导StableDiffusion 前言开始使用场景1 xff1a 繁华的街道场景2 xff1a 桥上的女生 项目及教程地址 xff0c 附GPT访问地址安装教程及安装包地址 xff1a 点我下载开源项目 xff1a 点我下载
  • CentOS7 使用RPMBUILD 编译 Openssh rpm包并安装

    若要进行生产环境的操作 xff0c 请务必看完整篇文档 实验环境 xff1a Centos7 4 离线系统 目前已经成功完成了openssh 9 1p1的编译 1 准备openssh源码包 在home目录开始 xff0c 设置工作目录 sp
  • Linus工作室 2021年 PB级存储方案

    来自于加拿大Linux 工作室 本文章仅整理内容 xff0c 另外还有一些本人的理解 实际上这已经是Linux PB计划第二代了 xff0c 比第一代更加NB 原视频地址 xff1a https www bilibili com video
  • 搭建本地yum repo

    在一些离线环境中无法使用在线的yum repo xff0c 只能使用本地的yum仓库 搭建的方式有如下几种 xff1a 使用本地meida使用本地media搭建远程服务器自建repo mirror xff08 施工中 xff09 1 使用本
  • Linux 系统安全加固篇之安全加固脚本

    该专栏内的脚本都会定期更新 xff0c 请注意变化 脚本适用于Centos 7 x系列 xff0c 同样支持Redhat 7 x系列 使用之前建议通读脚本注释 xff0c 并确认不会影响你现在在用的业务 注意脚本内部包含一定的参数 xff0
  • Docker导出正在使用中的镜像

    Docker 导出正在使用中的容器镜像 span class token comment xff01 bin sh span span class token assign left variable IMAGE DIR span span
  • Windows 10 数据恢复与预防数据丢失指南

    Windows 数据恢复与预防数据丢失指南 这个思路适合所有的windows版本 xff0c 但是有些数据恢复软件只能兼容新版系统 xff0c 这些不在我们的讨论范围内 如果你在使用电脑时不慎删除了一个重要的文件 xff0c 那么你可以在你
  • Flask SqlAlchemy Postgres 场景下如何使用右连接(Right Join)

    在Sqlalchemy中只有左连接 xff0c 而没有设计右连接 虽然说左右连接可以相互转换 xff0c 但是有些特定的场景下还是没有办法交换位置 所以我们选择了替代方案 xff0c 使用SqlAlchemy的全连接 FULL JOIN F
  • Nexus 3 清理docker镜像

    该文章提供了一种清理nexus3中存储的docker镜像的一种新思路 查看docker repo 比如你的docker repo名字叫做test repo xff0c 然后在nexus3首页的seatch下面找到docker xff0c 点
  • CentOS 7通过RPMbuild方式离线安装Openssl

    对于Centos7 最大兼容版本为1 1 1x 这里的x指代最新的版本标签 截止到文档编写时 最新的版本号为1 1 1t 编译流程 安装编译工具 yum y span class token function install span sp
  • vmware CentOS7图形界面与命令行界面切换

    在图形界面使用 ctrl 43 alt 43 F2切换到dos界面 dos界面 ctrl 43 alt 43 F2切换回图形界面 在命令上 输入 init 3 命令 切换到dos界面 输入 init 5命令 切换到图形界面 如果想系统默认以
  • AI Stable Diffusion Prompt参数【一】

    AI Stable Diffusion Prompt参数 一 配置场景1 草丛里的女性promptNegative Prompt结果 场景2 雨中披头散发的女孩promptNegative Prompt结果 场景3 一个女孩和她的朋友在逛街
  • Android Studio配置优化最全详解

    适合第一次安装AS的新手 xff0c 感谢网上的资源 是不是很多同学已经有烦恼出现了 xff1f 电脑配置已经很高了 xff0c 但是每次运行Android程序的时候就很卡 xff0c 而且每次安装运行程序都要等待很长时间 xff0c 如果
  • 解决Centos firewalld导致的docker容器内无法访问外网,无法访问其他容器(host没办法解析)

    开启 NAT 转发 firewall cmd permanent zone 61 public add masquerade 检查是否允许 NAT 转发 firewall cmd query masquerade 禁止防火墙 NAT 转发
  • 在JVM中多个应用程序共享jvm内存吗

    每运行一次main 函数 xff0c 就生成一个jvm内存模型实例 xff0c 他们互不相干 xff0c 互不干扰 xff0c 不共享内存和数据 验证方法 xff1a 本地创建两个带main方法的测试类 xff0c 在程序中打断点 xff0

随机推荐