【深度学习】Batch Normalization原理及其python实现

IID独立同分布假设:假设训练数据和测试数据是满足相同分布的,这是通过训练数据获得的模型能够在测试集获得好的效果的一个基本保障。

Internal Covariate Shift

Covariate Shift:训练集和测试集数据分布不一致

Internal:指网络的隐藏层

Internal Covariate Shift:当前层输入分布受之前层参数变化的影响。在训练过程中,网络中的参数在不断变化,每一层的输入分布也在不断变化。网络越深影响越大

因此训练过程中学习率不能太大,另外对网络参数的初始化要求也更高。

BatchNorm

Mini-Batch SGD相对于One Example SGD的两个优势:梯度更新方向更准确;并行计算速度快;

BN是基于Mini-Batch SGD,在batch维度操作的

BN使每一层的输入服从0~1正态分布

For a layer with d-dimensional input x = (x(1) . . . x(d)), BN will normalize each dimension

x ^ ( k ) = x ( k ) − E [ x ( k ) ] Var ⁡ [ x ( k ) ] \widehat{x}^{(k)}=\frac{x^{(k)}-\mathrm{E}\left[x^{(k)}\right]}{\sqrt{\operatorname{Var}\left[x^{(k)}\right]}} x (k)=Var[x(k)] x(k)E[x(k)]

训练过程

在这里插入图片描述
通过前三步简单归一化后每一层的输入服从0~1正态分布,但同时可能改变每一层学习到的特征。为解决此问题,BN使用重构变换(transformation inserted),从而恢复学习到的特征。

测试过程

测试过程每次只有一张数据,其均值和方差分别为训练时所有均值的平均值和方差的无偏估计,论文称其为moving averages

E [ x ] ← E B [ μ B ] \mathrm{E}[x] \leftarrow \mathrm{E}_{\mathcal{B}}\left[\mu_{\mathcal{B}}\right] E[x]EB[μB] Var ⁡ [ x ] ← m m − 1 E B [ σ B 2 ] \operatorname{Var}[x] \leftarrow \frac{m}{m-1} \mathrm{E}_{\mathcal{B}}\left[\sigma_{\mathcal{B}}^{2}\right] Var[x]m1mEB[σB2] y = γ Var ⁡ [ x ] + ϵ ⋅ x + ( β − γ E [ x ] Var ⁡ [ x ] + ϵ ) y=\frac{\gamma}{\sqrt{\operatorname{Var}[x]+\epsilon}} \cdot x+\left(\beta-\frac{\gamma \mathrm{E}[x]}{\sqrt{\operatorname{Var}[x]+\epsilon}}\right) y=Var[x]+ϵ γx+(βVar[x]+ϵ γE[x])

BatchNorm总结
优点

1、BN可以防止梯度消失和梯度爆炸,收敛速度快

2、加入BN后,模型可以使用更大的学习率,同时减少模型对参数初始化的依赖

3、BN可以正则化模型(SGD算法引入随机性),从而减小模型对dropout以及l2正则化的需求

缺点

https://www.zhihu.com/question/62599196

1、BN依赖于batch_size,batch_size太小(小于32)模型效果不佳。batch_size减小模型效果急剧下降。

2、对于图片生成任务如:图片超分辨率和风格迁移,效果不佳。因为此类任务更加关注单张图片本身特有的一些细节信息。

而BN更加关注数据整体的分布,在判别模型如图像分类识别方面效果较好。

3、RNN 、LSTM等动态网络使用 BN 效果不佳(应该选择Instance Normalization)

4、BN的测试过程和训练过程不连续。测试过程使用的均值和方差来自于训练集,若测试集与训练集分布不一致,测试集以此均值和方差进行归一化,并不合理。

另外,将加BN的模型作为预训练模型进行迁移学习,后续过程的均值和方差使用的依然是预训练模型训练集中的均值和方差。

python实现

def bn_forward(x, gamma, beta, eps, momentum, bn_param, mode):
    # # eps: 除以方差时为了防止方差太小而导致数值计算不稳定
    running_mean = bn_param['running_mean']  # shape = [B]
    running_var = bn_param['running_var']  # shape = [B]

    if mode == 'train':
        sample_mean = np.mean(x, axis=0)
        sample_var = np.var(x, axis=0)
        x_normalized = (x - sample_mean) / np.sqrt(sample_var + eps)
        out = gamma * x_normalized + beta

        # 滑动平均的方式计算新的均值和方差,训练时计算,为测试数据做准备
        running_mean = momentum * running_mean + (1 - momentum) * sample_mean
        running_var = momentum * running_var + (1 - momentum) * sample_var
        bn_param['running_mean'] = running_mean
        bn_param['running_var'] = running_var
    else:
        x_normalized = (x - running_mean) / np.sqrt(running_var + eps)
        out = gamma * x_normalized + beta

    return out

参考:
Batch Normalization 学习笔记
深度学习中的Normalization模型
cs231n学习笔记-激活函数-BN-参数优化

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值