机器学习(ML)十三之批量归一化、RESNET、Densenet
批量归一化
批量归一化(batch normalization)层,它能让较深的神经网络的训练变得更加容易。对图像处理的输入数据做了标准化处理:处理后的任意一个特征在数据集中所有样本上的均值为0、标准差为1。标准化处理输入数据使各个特征的分布相近:这往往更容易训练出有效的模型。
通常来说,数据标准化预处理对于浅层模型就足够有效了。随着模型训练的进行,当每层中参数更新时,靠近输出层的输出较难出现剧烈变化。但对深层神经网络来说,即使输入数据已做标准化,训练中模型参数的更新依然很容易造成靠近输出层输出的剧烈变化。这种计算数值的不稳定性通常令我们难以训练出有效的深度模型。
批量归一化的提出正是为了应对深度模型训练的挑战。在模型训练时,批量归一化利用小批量上的均值和标准差,不断调整神经网络中间输出,从而使整个神经网络在各层的中间输出的数值更稳定。批量归一化和下一节将要介绍的残差网络为训练和设计深度模型提供了两类重要思路。
批量归一化层
对全连接层和卷积层做批量归一化的方法稍有不同。
对全连接层做批量归一化
对卷积层做批量归一化
对卷积层来说,批量归一化发生在卷积计算之后、应用激活函数之前。如果卷积计算输出多个通道,我们需要对这些通道的输出分别做批量归一化,且每个通道都拥有独立的拉伸和偏移参数,并均为标量。设小批量中有m个样本。在单个通道上,假设卷积计算输出的高和宽分别为p和q。需要对该通道中m×p×q个元素同时做批量归一化。对这些元素做标准化计算时,我们使用相同的均值和方差,即该通道中m×p×q个元素的均值和方差。
预测时的批量归一化
使用批量归一化训练时,我们可以将批量大小设得大一点,从而使批量内样本的均值和方差的计算都较为准确。将训练好的模型用于预测时,我们希望模型对于任意输入都有确定的输出。因此,单个样本的输出不应取决于批量归一化所需要的随机小批量中的均值和方差。一种常用的方法是通过移动平均估算整个训练数据集的样本均值和方差,并在预测时使用它们得到确定的输出。可见,和丢弃层一样,批量归一化层在训练模式和预测模式下的计算结果也是不一样的。
- 在模型训练时,批量归一化利用小批量上的均值和标准差,不断调整神经网络的中间输出,从而使整个神经网络在各层的中间输出的数值更稳定。
- 对全连接层和卷积层做批量归一化的方法稍有不同。
- 批量归一化层和丢弃层一样,在训练模式和预测模式的计算结果是不一样的。
- Gluon提供的BatchNorm类使用起来简单、方便。
批量归一化代码实现
import d2lzh as d2l
from mxnet import autograd, gluon, init, nd
from mxnet.gluon import nn net = nn.Sequential()
net.add(nn.Conv2D(6, kernel_size=5),
nn.BatchNorm(),
nn.Activation('sigmoid'),
nn.MaxPool2D(pool_size=2, strides=2),
nn.Conv2D(16, kernel_size=5),
nn.BatchNorm(),
nn.Activation('sigmoid'),
nn.MaxPool2D(pool_size=2, strides=2),
nn.Dense(120),
nn.BatchNorm(),
nn.Activation('sigmoid'),
nn.Dense(84),
nn.BatchNorm(),
nn.Activation('sigmoid'),
nn.Dense(10))
lr, num_epochs, batch_size, ctx = 1.0, 5, 256, d2l.try_gpu() net.initialize(ctx=ctx, init=init.Xavier())
trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': lr})
d2l.train_ch5(net, train_iter, test_iter, batch_size, trainer, ctx,
num_epochs)
残差网络(ResNet)
先思考一个问题:对神经网络模型添加新的层,充分训练后的模型是否只可能更有效地降低训练误差?理论上,原模型解的空间只是新模型解的空间的子空间。也就是说,如果我们能将新添加的层训练成恒等映射f(x)=x,新模型和原模型将同样有效。由于新模型可能得出更优的解来拟合训练数据集,因此添加层似乎更容易降低训练误差。然而在实践中,添加过多的层后训练误差往往不降反升。即使利用批量归一化带来的数值稳定性使训练深层模型更加容易,该问题仍然存在。针对这一问题,何恺明等人提出了残差网络(ResNet)。它在2015年的ImageNet图像识别挑战赛夺魁,并深刻影响了后来的深度神经网络的设计。
残差块
聚焦于神经网络局部。下图所示,设输入为x。假设我们希望学出的理想映射为f(x),从而作为下图上方激活函数的输入。左图虚线框中的部分需要直接拟合出该映射f(x),而右图虚线框中的部分则需要拟合出有关恒等映射的残差映射f(x)−x。残差映射在实际中往往更容易优化。以本节开头提到的恒等映射作为我们希望学出的理想映射f(x)。只需将下图中右图虚线框内上方的加权运算(如仿射)的权重和偏差参数学成0,那么f(x)即为恒等映射。实际中,当理想映射f(x)极接近于恒等映射时,残差映射也易于捕捉恒等映射的细微波动。下图右图也是ResNet的基础块,即残差块(residual block)。在残差块中,输入可通过跨层的数据线路更快地向前传播。
ResNet沿用了VGG全3×3卷积层的设计。残差块里首先有2个有相同输出通道数的3×3卷积层。每个卷积层后接一个批量归一化层和ReLU激活函数。然后我们将输入跳过这两个卷积运算后直接加在最后的ReLU激活函数前。这样的设计要求两个卷积层的输出与输入形状一样,从而可以相加。如果想改变通道数,就需要引入一个额外的1×1卷积层来将输入变换成需要的形状后再做相加运算。
ResNet模型
ResNet的前两层跟之前介绍的GoogLeNet中的一样:在输出通道数为64、步幅为2的7×7卷积层后接步幅为2的3×3的最大池化层。不同之处在于ResNet每个卷积层后增加的批量归一化层。
GoogLeNet在后面接了4个由Inception块组成的模块。ResNet则使用4个由残差块组成的模块,每个模块使用若干个同样输出通道数的残差块。第一个模块的通道数同输入通道数一致。由于之前已经使用了步幅为2的最大池化层,所以无须减小高和宽。之后的每个模块在第一个残差块里将上一个模块的通道数翻倍,并将高和宽减半。接着我们为ResNet加入所有残差块。这里每个模块使用两个残差块。最后,与GoogLeNet一样,加入全局平均池化层后接上全连接层输出。每个模块里有4个卷积层(不计算1×1卷积层),加上最开始的卷积层和最后的全连接层,共计18层。这个模型通常也被称为ResNet-18。通过配置不同的通道数和模块里的残差块数可以得到不同的ResNet模型,例如更深的含152层的ResNet-152。虽然ResNet的主体架构跟GoogLeNet的类似,但ResNet结构更简单,修改也更方便。这些因素都导致了ResNet迅速被广泛使用。
- 残差块通过跨层的数据通道从而能够训练出有效的深度神经网络。
- ResNet深刻影响了后来的深度神经网络的设计。
稠密连接网络(DenseNet)
ResNet中的跨层连接设计引申出了数个后续工作。本节我们介绍其中的一个:稠密连接网络(DenseNet)。 它与ResNet的主要区别如下图所示。

上图将部分前后相邻的运算抽象为模块A和模块B。与ResNet的主要区别在于,DenseNet里模块B的输出不是像ResNet那样和模块A的输出相加,而是在通道维上连结。这样模块A的输出可以直接传入模块B后面的层。在这个设计里,模块A直接跟模块B后面的所有层连接在了一起。这也是它被称为“稠密连接”的原因。
DenseNet的主要构建模块是稠密块(dense block)和过渡层(transition layer)。前者定义了输入和输出是如何连结的,后者则用来控制通道数,使之不过大。
稠密块
enseNet使用了ResNet改良版的“批量归一化、激活和卷积”结构。稠密块由多个conv_block
组成,每块使用相同的输出通道数。但在前向计算时,我们将每块的输入和输出在通道维上连结。
过渡层
由于每个稠密块都会带来通道数的增加,使用过多则会带来过于复杂的模型。过渡层用来控制模型复杂度。它通过1×1卷积层来减小通道数,并使用步幅为2的平均池化层减半高和宽,从而进一步降低模型复杂度。
DenseNet模型
DenseNet首先使用同ResNet一样的单卷积层和最大池化层。
类似于ResNet接下来使用的4个残差块,DenseNet使用的是4个稠密块。同ResNet一样,我们可以设置每个稠密块使用多少个卷积层。这里我们设成4,从而与上一节的ResNet-18保持一致。稠密块里的卷积层通道数(即增长率)设为32,所以每个稠密块将增加128个通道。ResNet里通过步幅为2的残差块在每个模块之间减小高和宽。这里我们则使用过渡层来减半高和宽,并减半通道数。同ResNet一样,最后接上全局池化层和全连接层来输出。
- 在跨层连接上,不同于ResNet中将输入与输出相加,DenseNet在通道维上连结输入与输出。
- DenseNet的主要构建模块是稠密块和过渡层。
机器学习(ML)十三之批量归一化、RESNET、Densenet的更多相关文章
- L18 批量归一化和残差网络
批量归一化(BatchNormalization) 对输入的标准化(浅层模型) 处理后的任意一个特征在数据集中所有样本上的均值为0.标准差为1. 标准化处理输入数据使各个特征的分布相近 批量归一化(深 ...
- [ DLPytorch ] 批量归一化与残差网络
批量归一化 通常来说,数据标准化预处理对于浅层模型就足够有效了.随着模型训练的进行,当每层中参数更新时,靠近输出层的输出较难出现剧烈变化.但对深层神经网络来说,即使输入数据已做标准化,训练中模型参数的 ...
- 第十八节,TensorFlow中使用批量归一化(BN)
在深度学习章节里,已经介绍了批量归一化的概念,详情请点击这里:第九节,改善深层神经网络:超参数调试.正则化以优化(下) 神经网络在进行训练时,主要是用来学习数据的分布规律,如果数据的训练部分和测试部分 ...
- MyBatis基础入门《十三》批量新增数据
MyBatis基础入门<十三>批量新增数据 批量新增数据方式1:(数据小于一万) xml文件 接口: 测试方法: 测试结果: =============================== ...
- [机器学习] ML重要概念:梯度(Gradient)与梯度下降法(Gradient Descent)
引言 机器学习栏目记录我在学习Machine Learning过程的一些心得笔记,涵盖线性回归.逻辑回归.Softmax回归.神经网络和SVM等等,主要学习资料来自网上的免费课程和一些经典书籍,免费课 ...
- 批量归一化batch_normalization
为了解决在深度神经网络训练初期降低梯度消失/爆炸问题,Sergey loffe和Christian Szegedy提出了使用批量归一化的技术的方案,该技术包括在每一层激活函数之前在模型里加一个操作,简 ...
- 深度学习面试题21:批量归一化(Batch Normalization,BN)
目录 BN的由来 BN的作用 BN的操作阶段 BN的操作流程 BN可以防止梯度消失吗 为什么归一化后还要放缩和平移 BN在GoogLeNet中的应用 参考资料 BN的由来 BN是由Google于201 ...
- Batch Normalization批量归一化
BN的深度理解:https://www.cnblogs.com/guoyaohua/p/8724433.html BN: BN的意义:在激活函数之前将输入归一化到高斯分布,控制到激活函数的敏感区域,避 ...
- TensorFlow——批量归一化操作
批量归一化 在对神经网络的优化方法中,有一种使用十分广泛的方法——批量归一化,使得神经网络的识别准确度得到了极大的提升. 在网络的前向计算过程中,当输出的数据不再同一分布时,可能会使得loss的值非常 ...
随机推荐
- 天梯 L2 紧急救援 (dijkstra变形+记录路径)
L2-001 紧急救援 (25 分) 作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道 ...
- TieredMergePolicy
setFloorSegmentMB多少MB一个层级,在此区间的segment分为一个floor. setMaxMergeAtOnce一次merge多少个segment. setSegmentsPerT ...
- 【转】20个简化开发任务的 JavaScript库
原文出处: codegeekz 译文出处: oschina 所谓JavaScript库就是预先写好的可以简化基于JavaScript的应用程序开发的,尤其是Ajax和其它以web为中心的技术的 J ...
- python集合的运算
& 交集 | 并集 - 差集 ^ 异或集 # 在对集合做运算时,不会影响原来的集合,而是返回一个运算结果 # 创建两个集合 s = {1,2,3,4,5} s2 = {3,4,5, ...
- 通过模拟Mybatis动态代理生成Mapper代理类,讲解Mybatis核心原理
本文将通过模拟Mybatis动态代理生成Mapper代理类,讲解Mybatis原理 1.平常我们是如何使用Mapper的 先写一个简单的UserMapper,它包含一个全表查询的方法,代码如下 pub ...
- Spring Boot2 系列教程 (十六) | 整合 WebSocket 实现广播
前言 如题,今天介绍的是 SpringBoot 整合 WebSocket 实现广播消息. 什么是 WebSocket ? WebSocket 为浏览器和服务器提供了双工异步通信的功能,即浏览器可以向服 ...
- Netty之缓冲区ByteBuf解读(一)
Netty 在数据传输过程中,会使用缓冲区设计来提高传输效率.虽然,Java 在 NIO 编程中已提供 ByteBuffer 类进行使用,但是在使用过程中,其编码方式相对来说不太友好,也存在一定的不足 ...
- React16源码解读:开篇带你搞懂几个面试考点
引言 如今,主流的前端框架React,Vue和Angular在前端领域已成三足鼎立之势,基于前端技术栈的发展现状,大大小小的公司或多或少也会使用其中某一项或者多项技术栈,那么掌握并熟练使用其中至少一种 ...
- redis简单操作
一.redis 基础操作 1.1.string 类型及操作 string 是最简单的类型,一个key对应一个value,string类型是二进制安全的.redis的string可以包含任何数据. 1. ...
- Appium自动化测试框架研究(2)——搭建IOS环境
今天的文章讲iOS的Appium环境搭建. 对于iOS而言,只能在Mac笔记本上安装Appium,以及所需要的各种组件. 也许有人会问,能否在Windows系统上使用Appium测试iOS手机,这不就 ...