Batch Normalization推理验证

Batch Normalization

使数据分布为均值为0方差为1
批量归一化、批量标准化『https://baike.baidu.com/item/%E6%89%B9%E6%A0%87%E5%87%86%E5%8C%96/22778547』
Standardization(标准化) ???这里不确定

ref

Batch Normalization原理

提出前提

Batch Normalization原理

随着网络深度的加深,在参数更新的时候,每层的输入值的数据分布会发生变化,导致ICS(Internal Covariate Shift)问题。

ICS问题会:

  • 上层网络需要不停调整来适应输入数据分布的变化,导致网络学习速度的降低
  • 网络的训练过程容易陷入梯度饱和区,减缓网络收敛速度

反正,网络的训练过程容易陷入梯度饱和区,减缓网络收敛速度

解决上面的问题

一、白化(whitening)

主要是PCA白化与ZCA白化。白化是对输入数据分布进行变换,进而达到以下两个目的:

  • 使得输入特征分布具有相同的均值与方差。

    其中PCA白化保证了所有特征分布均值为0,方差为1;而ZCA白化则保证了所有特征分布均值为0,方差相同;

  • 去除特征之间的相关性。

白化带来的问题:不理解

  • 计算成本大
  • 改变了网络每一层的分布,丢失了数据的表达能力。就是学到的参数信息会被白话操作丢失。

提出Batch Normalization

Batch Normalization原理

整体解释
n o r m a l i z a i t o n = x − μ σ 2 + ϵ normalizaiton = {x - \mu \over \sqrt{\sigma^2+\epsilon}} normalizaiton=σ2+ϵ xμ
( ϵ \epsilon ϵ防止方差是0而计算出错)

每个batch下,单独对该批量样本的每种特征进行normalizaiton,控制每种特征的特征值分布是均值为0,方差为1的分布

Batch就是mini-batch,因为有时候内存不能一次全装下

计算步骤

  • 假设batch的值为 m m m,即每次输入 m m m个样本参与训练

  • 计算这个batch的第 j j j个特征(即对应当前关注层的第 j j j个神经元)的均值 μ j \mu_j μj
    μ j = 1 m ∑ i = 1 m Z j ( i ) \mu_j={1\over m}\sum^m_{i=1}Z_j^{(i)} μj=m1i=1mZj(i)

  • 计算这个batch的第 j j j个特征(即对应当前关注层的第 j j j个神经元)的方差 σ j 2 \sigma^2_j σj2
    σ j 2 = 1 m ∑ i = 1 m ( Z j ( i ) − μ j ) 2 \sigma^2_j = {1\over m}\sum^m_{i=1}(Z^{(i)}_j-\mu_j)^2 σj2=m1i=1m(Zj(i)μj)2

  • Z j ( i ) Z_j^{(i)} Zj(i)是该batch的第 i i i个样本在当前关注层的第 j − 1 j-1 j1个神经元的输出值,也即当前关注层的第 j j j个神经元的输入值

  • 更新
    Z ^ j = Z j − μ j σ j 2 + ϵ \hat{Z}_j={Z_j-\mu_j \over \sqrt{\sigma^2_j+\epsilon}} Z^j=σj2+ϵ Zjμj

以上只是解决了分布的问题还有数据表达能力的缺失的问题

引入可学习机制(做线性变换)

增加参数 γ \gamma γ β \beta β
Z ~ j = γ j Z ^ j + β j \tilde{Z}_j = \gamma_j\hat{Z}_j+\beta_j Z~j=γjZ^j+βj
γ \gamma γ β \beta β对应方差 σ 2 \sigma^2 σ2和均值 μ \mu μ时,得到最初的原始特征 Z j Z_j Zj

测试阶段如何使用BN

Batch Normalization原理

以训练数据的整体方差和均值来作为测试阶段中BN的均值和方差,具体说:

训练时,记录每个batch的方差和均值,使用**均值和方差的无偏估计**:
μ t e s t = E ( μ b a t c h ) \mu_{test}=E(\mu_{batch}) μtest=E(μbatch)

σ t e s t 2 = m m − 1 E ( σ b a t c h 2 ) \sigma^2_{test}={m \over m-1}E(\sigma^2_{batch}) σtest2=m1mE(σbatch2)

这个最后的结果,对应的应该就是running_meanrunning_var

然后对测试数据做归一化:
B N ( X t e s t ) = γ X t e s t − μ t e s t σ t e s t 2 + ϵ + β BN(X_{test}) = \gamma{X_{test}-\mu_{test}\over\sqrt{\sigma^2_{test}+\epsilon}}+\beta BN(Xtest)=γσtest2+ϵ Xtestμtest+β
另外,除了采用整体样本的无偏估计外。吴恩达在Coursera上的Deep Learning课程指出可以对train阶段每个batch计算的mean/variance采用指数加权平均来得到test阶段mean/variance的估计。指数加权

计算实例

Batch Normalization原理

BN公式总结

x u p d a t e = x − E ( x ) V a r ( x ) + e p s ∗ γ + β x_{update} = {x-E(x)\over\sqrt{Var(x)+eps}}*\gamma+\beta xupdate=Var(x)+eps xE(x)γ+β

拉平成一维来计算均值和方差

pytorch BN

ref

pytorch中BatchNorm1d、BatchNorm2d、BatchNorm3d

【PyTorch】详解pytorch中nn模块的BatchNorm2d()函数

使用说明

pytorch中BatchNorm1d、BatchNorm2d、BatchNorm3d

  • BN的参数num_features都是和输入数据的C相对应
  • BN不改变数据维度
BN输入维度num_features
(等于E、Var个数)
1d(N, C)或者(N, C, L)C
2d(N, C, H, W)C
3d(N, C, D, H, W)C

计算和验证实例

PyTorch基础——torch.nn.BatchNorm2d

  • batch大于1的情况

  • E ( x ) E(x) E(x)就是把 H × W H\times W H×W维的特征==拉直成一维==再计算

  • V a r ( x ) Var(x) Var(x)也是一样

  • t = torch.tensor([[[1,2,3.0],[2,3,5]],[[1,2,3.0],[1,4,5]]])
    q = t.view(-1)
    print(t)
    print(q)
    print(torch.mean(t),torch.mean(q))
    print(torch.var(t, unbiased=False),torch.var(q, unbiased=False))# unbiased参数需要设置为False,否则
                                                  # 计算出方差为无偏估计,与当前结果不同
                                                  # 第二、第三通道相同设置
    
    

pytorch之BatchNorm2d

  • 有图示说明,图上的feature1,2应该是sample1,2

【PyTorch】详解pytorch中nn模块的BatchNorm2d()函数

  • 一个计算和验证BN2d的例子,batch=1的情况

  • C后面的被认定为特征,输出BN的权重就可以发现

    • 在2d中, ( H × W ) (H\times W) (H×W)代表特征,拥有 H W HW HW个数值来表征这个特征

      解释:(1)对于第 j j j个特征 C j C_j Cj来说,假设在该batch中包含 m m m个样本,所以需要统计 m m m份的维度为 ( H × W ) (H\times W) (H×W)的数据的均值和方差。(2)怎么算这个方差和均值?就是对 ( H × W ) (H\times W) (H×W)维度的数据拉成一维的,再像BN1d那样作计算。因此,求得的均值和方差的个数,分别等于C的值。

详细过程

Pytorch BN(BatchNormal)计算过程与源码分析和train与eval的区别

  • BN层的输出将作为下一层激活层的输入

  • PyTorch 源码解读之 BN,『四种Norm的图示

  • running_var = running_var * (1 - eaf) + eaf * inputs_var * n / (n - 1)
    running_mean = running_mean * (1 - eaf) + eaf * inputs_mean
    
  • 方差的计算,做的是有偏估计

BN2d验证代码

import torch.nn as nn
import torch

torch.random.manual_seed(0)
input = torch.randn(2, 3, 3, 4)
# With Learnable Parameters
m = nn.BatchNorm2d(3)
# Without Learnable Parameters
# m = nn.BatchNorm1d(100, affine=False)
output = m(input)
print(input)
print(m.weight)
print(m.bias)
print(m.running_mean)
print(output)
##########################################################################################################
## wrong
##########################################################################################################
print('=' * 100)
"""
使用先在`C`上求和再求均值和方差,均值是对的,但是方差是错误的
"""
input_c = (input[0][0] + input[1][0]) / 2
# input_c = input[0][0]
print(input_c)
firstDimenMean = torch.Tensor.mean(input_c)
firstDimenVar = torch.Tensor.var(input_c, False)  # false表示贝塞尔校正不会被使用
print(firstDimenMean)
print(firstDimenVar)
batchnormone = ((input_c[0][0] - firstDimenMean) / (torch.pow(firstDimenVar, 0.5) + m.eps)) \
               * m.weight[0] + m.bias[0]
print(batchnormone)
#######################################################################################################
## the computation is correct!!!
#######################################################################################################
print('=' * 100)
input_c1 = input[:, 0, :, :]
print(input_c1)
"""
注意: `torch.Tensor.var(input_c1, Ture)`和`torch.var(input_c1)`
本质是展平后作计算
"""
firstDimenMean = torch.Tensor.mean(input_c1)
firstDimenVar = torch.Tensor.var(input_c1, False)  # false表示贝塞尔校正不会被使用

print(firstDimenMean)
print(firstDimenVar)
batchnormone = ((input_c1 - firstDimenMean) / (torch.pow(firstDimenVar, 0.5) + m.eps)) \
               * m.weight[0] + m.bias[0]
print(batchnormone)

########################################################################################################
"""
验证均值和方差的计算,是否是通过展平后计算的
"""
print('=' * 100)
print(input_c1.flatten())
print(torch.mean(input_c1.flatten()))
print(torch.var(input_c1.flatten()))
print(torch.mean(input_c1))
print(torch.var(input_c1))

torch.Tensor.var(input_c1, Ture)torch.var(input_c1)的区别

# t = torch.tensor([[[1,2,3.0],[2,3,5]],[[1,2,3.0],[1,4,5]]])
t = torch.tensor([[[-1.1258, -1.1524, -0.2506, -0.4339],
                   [0.8487, 0.6920, -0.3160, -2.1152],
                   [0.3223, -1.2633, 0.3500, 0.3081]],
                  [[0.4397, 0.1124, 0.6408, 0.4412],
                   [-0.1023, 0.7924, -0.2897, 0.0525],
                   [0.5229, 2.3022, -1.4689, -1.5867]]])
q = t.view(-1)
print(t)
print(q)
print(torch.mean(t), torch.mean(q))
print(torch.var(t), torch.var(q))
print(torch.Tensor.mean(t),torch.Tensor.mean(q))
print(torch.Tensor.var(t, False),torch.Tensor.var(q, False)) # BN的方式
print(torch.Tensor.var(t, True),torch.Tensor.var(q, True))

分析torch.Tensor.var(input_c1, Ture)==torch.var(input_c1)

# 运行结果
tensor([[[-1.1258, -1.1524, -0.2506, -0.4339],
         [ 0.8487,  0.6920, -0.3160, -2.1152],
         [ 0.3223, -1.2633,  0.3500,  0.3081]],

        [[ 0.4397,  0.1124,  0.6408,  0.4412],
         [-0.1023,  0.7924, -0.2897,  0.0525],
         [ 0.5229,  2.3022, -1.4689, -1.5867]]])
tensor([-1.1258, -1.1524, -0.2506, -0.4339,  0.8487,  0.6920, -0.3160, -2.1152,
         0.3223, -1.2633,  0.3500,  0.3081,  0.4397,  0.1124,  0.6408,  0.4412,
        -0.1023,  0.7924, -0.2897,  0.0525,  0.5229,  2.3022, -1.4689, -1.5867])
tensor(-0.0950) tensor(-0.0950)
tensor(0.9611) tensor(0.9611)
tensor(-0.0950) tensor(-0.0950)
tensor(0.9211) tensor(0.9211)
tensor(0.9611) tensor(0.9611)

解释

关键在与var()unbiased这个参数,在Batch Normalization原理中有提到。

总结

训练阶段,用的是有偏估计,unbiased设置为True

测试阶段,用的有偏估计,在『测试阶段如何使用BN』有写,这部分不想验证了,搞了两天,累了

有偏估计、无偏估计

在数学上,方差的有偏估计和无偏估计

样本总体方差有偏估计和无偏估计的理解

[机器学习] 无偏估计和有偏估计及公式证明

通俗的说,就是我们拿不到所有的样本来做统计,所以只是用手上现有的数据的分布来替代整体数据分布,当手上数据无限多时,等价于整体数据。

从现有数据分布做统计,就是有偏的。

在这里插入图片描述

<think>好的,我现在要比较Batch Normalization(BN)和Layer Normalization(LN)的区别、适用场景以及在深度学习中的对比。首先,我需要回忆这两种标准化方法的基本概念和原理。 Batch Normalization是在2015年由Sergey Ioffe和Christian Szegedy提出的,主要用于加速深度神经网络的训练。它的核心思想是对每个小批量(mini-batch)的数据进行标准化处理,即对每个神经元的输入进行归一化,使其均值接近0,方差接近1。这样可以减少内部协变量移(Internal Covariate Shift),从而加快训练速度,并允许使用更高的学习率。BN通常在卷积神经网络(CNN)中应用广泛,特别是在图像处理任务中,比如ResNet等模型就大量使用了BN层[^1]。不过,BN的一个缺点是当batch size较小时,效果会变差,因为均值方差的估计不准确。比如,在训练TurboAE时,需要非常大的batch size(超过500)才能有效平均噪声影响。 接下来是Layer Normalization,由Jimmy Lei Ba等人在2016年提出。与BN不同,LN是对同一层内所有神经元的输出进行标准化,即对每个样本的所有特征进行归一化。这种方法不依赖于batch size的大小,因此在batch size较小或动态变化的情况下表现更好。LN在循环神经网络(RNN)和Transformer模型中应用较多,比如在自然语言处理任务中,由于序列长度可变,使用LN可以更好地处理不同长度的输入。例如,DeepDR-Transformer模块在处理眼底图像分类任务时,可能使用了类似LN的结构来保持稳定性[^2]。 两者的主要区别在于归一化的维度不同。BN在batch维度和特征维度上进行归一化,而LN是在特征维度和层维度上进行。因此,BN的效果受batch size影响较大,而LN则不受此限制。此外,BN在训练和推理时的行为不同,需要维护移动平均的均值方差,而LN在训练和推理时计算方式一致,不需要额外参数。 适用场景方面,BN适合固定深度的模型和较大的batch size,比如图像分类任务中的CNN。LN则适合变长序列或小batch size的情况,如NLP中的Transformer或RNN。此外,在强化学习或生成对抗网络(GAN)中,由于batch size可能不稳定,LN也更适合。 需要进一步验证的是,LN是否真的在Transformer中被广泛使用,以及BN在batch size较小时的具体表现。根据引用[1],TurboAE需要大batch size才能有效,这说明BN对batch size敏感,而LN可能更适合小batch场景。同时,引用[2]提到的DeepDR-Transformer使用了全局平均池化和全连接层,可能未明确提到LN,但Transformer架构通常使用LN,如原始论文中的设计。 总结下来,BN和LN的主要区别在于归一化的维度和对batch size的依赖,适用场景则根据模型类型和任务需求来选择。</think>### Batch Normalization vs Layer Normalization: 区别与适用场景 #### 1. **核心区别** - **Batch Normalization (BN)** 对每个神经元的输入按 **批次维度** 进行标准化。假设输入维度为 $[B, C, H, W]$(如CNN中的图像数据),BN会对每个通道(Channel)的所有样本、空间位置计算均值方差,公式为: $$ \mu_c = \frac{1}{B \cdot H \cdot W} \sum_{b=1}^B \sum_{h=1}^H \sum_{w=1}^W x_{b,c,h,w} \\ \sigma_c^2 = \frac{1}{B \cdot H \cdot W} \sum_{b=1}^B \sum_{h=1}^H \sum_{w=1}^W (x_{b,c,h,w} - \mu_c)^2 $$ 适用于 **固定输入结构** 的任务(如图像分类)。 - **Layer Normalization (LN)** 对每个样本的所有神经元输出按 **特征维度** 进行标准化。假设输入维度为 $[B, L, D]$(如Transformer中的序列数据),LN会对每个样本的所有位置和特征计算均值方差: $$ \mu_b = \frac{1}{L \cdot D} \sum_{l=1}^L \sum_{d=1}^D x_{b,l,d} \\ \sigma_b^2 = \frac{1}{L \cdot D} \sum_{l=1}^L \sum_{d=1}^D (x_{b,l,d} - \mu_b)^2 $$ 适用于 **变长序列** 或 **小批量数据** 的场景(如NLP、强化学习)。 --- #### 2. **适用场景对比** | **特性** | **Batch Normalization** | **Layer Normalization** | |------------------------|--------------------------------------|--------------------------------------| | **数据依赖** | 依赖批次统计,需要较大batch size | 单样本统计,与batch size无关 | | **任务类型** | 图像处理(CNN)、固定输入长度的任务 | NLP(Transformer)、RNN、强化学习 | | **训练稳定性** | 对batch size敏感,小批次效果下降 | 对batch size鲁棒 | | **推理行为** | 使用移动平均统计量 | 直接计算当前样本统计量 | --- #### 3. **性能影响** - **BN的优势与局限** 在图像任务中显著加速收敛,但受限于batch size。例如,在TurboAE训练中,batch size需大于500才能有效平均噪声影响。 - **LN的优势与局限** 更适合动态输入或小batch场景。例如,Transformer通过LN处理变长序列,而DeepDR-Transformer在医学图像分类中可能依赖类似结构[^2]。 --- #### 4. **代码示例对比** ```python # Batch Normalization (PyTorch) import torch.nn as nn bn = nn.BatchNorm2d(num_features=64) # 用于CNN # Layer Normalization (PyTorch) ln = nn.LayerNorm(normalized_shape=512) # 用于Transformer ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值