BN问题说明

Batch Normalization(BN)是深度学习中非常好用的一个算法,加入BN层的网络往往更加稳定并且BN还起到了一定的正则化的作用。在这篇文章中,我们将详细介绍BN的技术细节[1]以及其能工作的原因[2]。

在提出BN的文章中[1],作者BN能工作的原因是BN解决了普通网络的内部协变量偏移(Internel Covariate Shift, ICS)的问题,所谓ICS是指网络各层的分布不一致,网络需要适应这种不一致从而增加了学习的难度。而在[2]中,作者通过实验验证了BN其实和ICS的关系并不大,其能工作的原因是使损失平面更加平滑,并给出了其结论的数学证明。


1. BN详解

1.1 内部协变量偏移

BN的提出是基于小批量随机梯度下降(mini-batch SGD)的,mini-batch SGD是介于one-example SGD和full-batch SGD的一个折中方案,其优点是比full-batch SGD有更小的硬件需求,比one-example SGD有更好的收敛速度和并行能力。随机梯度下降的缺点是对参数比较敏感,较大的学习率和不合适的初始化值均有可能导致训练过程中发生梯度消失或者梯度爆炸的现象的出现。BN的出现则有效的解决了这个问题。

在Sergey Ioffe的文章中,他们认为BN的主要贡献是减弱了内部协变量偏移(ICS)的问题,论文中对ICS的定义是:as the change in the distribution of network activations due to the change in network parameters during training。作者认为ICS是导致网络收敛的慢的罪魁祸首,因为模型需要学习在训练过程中会不断变化的隐层输入分布。作者提出BN的动机是企图在训练过程中将每一层的隐层节点的输入固定下来,这样就可以避免ICS的问题了。

在深度学习训练中,白化(Whiten)是加速收敛的一个小Trick,所谓白化是指将图像像素点变化到均值为0,方差为1的正态分布。我们知道在深度学习中,第 i 层的输出会直接作为第 i+1层的输入,所以我们能不能对神经网络的每一层的输入都做一次白化呢?其实BN就是这么做的。

1.2 梯度饱和

我们知道sigmoid激活函数和tanh激活函数存在梯度饱和的区域,其原因是激活函数的输入值过大或者过小,其得到的激活函数的梯度值会非常接近于0,使得网络的收敛速度减慢。传统的方法是使用不存在梯度饱和区域的激活函数,例如ReLU等。BN也可以缓解梯度饱和的问题,它的策略是在调用激活函数之前将 WX+b 的值归一化到梯度值比较大的区域。假设激活函数为  ,BN应在  之前使用:

 

 

1.3 BN的训练过程

如果按照传统白化的方法,整个数据集都会参与归一化的计算,但是这种过程无疑是非常耗时的。BN的归一化过程是以批量为单位的。如图1所示,假设一个批量有 n 个样本 \beta ={x_{0},x_{1},...,x_{m}} ,每个样本有d 个特征,那么这个批量的每个样本第  k个特征的归一化后的值为

其中 E 和  Var分别表示在第 k 个特征上这个批量中所有的样本的均值和方差。

                                                         图1:神经网络的BN示意图

这种表示会对模型的收敛有帮助,但是也可能破坏已经学习到的特征。为了解决这个问题,BN添加了两个可以学习的变量  \gamma和 \beta 用于控制网络能够表达直接映射,也就是能够还原BN之前学习到的特征。

 


 

总结

BN是深度学习调参中非常好用的策略之一(另外一个可能就是Dropout),当你的模型发生梯度消失/爆炸或者损失值震荡比较严重的时候,在BN中加入网络往往能取得非常好的效果。

BN也有一些不是非常适用的场景,在遇见这些场景时要谨慎的使用BN:

  • 受制于硬件限制,每个Batch的尺寸比较小,这时候谨慎使用BN;
  • 在类似于RNN的动态网络中谨慎使用BN;
  • 训练数据集和测试数据集方差较大的时候。

在Ioffe的论文中,他们认为BN能work的原因是因为减轻了ICS的问题,而在Santurkar的论文中则对其进行了否定。它们结论的得出非常依赖他们自己给出的ICS的数学定义,这个定义是否不能说不对,但是感觉不够精确,BN真的和ICS没有一点关系吗?我是觉得不一定。

参考:

[1] Ioffe S, Szegedy C. Batch normalization: Accelerating deep network training by reducing internal covariate shift[J]. arXiv preprint arXiv:1502.03167, 2015.

[2] Santurkar S, Tsipras D, Ilyas A, et al. How Does Batch Normalization Help Optimization?(No, It Is Not About Internal Covariate Shift)[J]. arXiv preprint arXiv:1805.11604, 2018.

[3] Hao Li, Zheng Xu, Gavin Taylor, and Tom Goldstein. Visualizing the loss landscape of neural nets. arXiv preprint arXiv:1712.09913, 2017.

[4] 模型优化之Batch Normalization - 知乎

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: BN_bn2binpad 是 OpenSSL 库中的一个函数,用于将大整数 BIGNUM 转换为二进制字符串,并在左侧填充零字节以达到指定的长度。函数原型如下: ```c int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen); ``` 参数说明: - a:要转换的 BIGNUM 对象。 - to:输出的二进制字符串。 - tolen:输出字符串的长度,如果 a 转换后的字符串长度小于 tolen,则在左侧填充零字节。 函数返回值为输出字符串的实际长度。如果 tolen 小于 a 转换后的字符串长度,则函数会返回 0。 ### 回答2: bn_bn2binpad是一个函数,主要用于将一个bignum对象转换为带有固定长度的二进制字符串。在加密算法中,bignum对象常用于存储大整数,而二进制字符串是一种常用的数据表达方式。 该函数的具体用法是将一个bignum对象转换为二进制字符串,如果转换后的二进制字符串长度小于指定的目标长度,则会在左侧填充0,使得最终的二进制字符串长度达到指定的目标长度。如果转换后的二进制字符串长度大于等于指定的目标长度,则会返回转换后的二进制字符串。 这个函数的目的是为了满足一些特定的加密算法或者协议的需求,例如密钥派生函数中,需要将一个bignum对象转换为指定长度的二进制字符串。通过指定的目标长度以及填充方式,可以方便地将bignum对象转换为符合要求的二进制字符串。 总结而言,bn_bn2binpad函数是一个用于将bignum对象转换为带有固定长度的二进制字符串的函数,可以满足加密算法和协议对数据表达形式的特定要求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值