一、前言
准备写一个系列的文章,关于BatchNorm。
本文的主要内容是对BN技术做一个汇总,默认读者已经了解BN层的主要工作原理,理解BN算法中每个参数的含义以及在训练和推理过程中的算法原理。
1. BN存在的问题以及在必须使用BN的时候,我们应该怎么进行参数调节?针对这个问题,主要通过论文《rethinking BN》这篇以实验为主导的论文讨论来进行。
2. BN和学习率的关系?
3. 针对BN技术,有什么算法技术上的改进,可以避开BN的缺点?
4. 不考虑BN技术,有什么同样可以实现输入输出归一化的技术,能够避开BN存在的问题?
本文主要针对上面的第一个问题进行分析。这部分主要参考论文《Rethinking “Batch” in BatchNorm》
后面再去针对上面的其他问题详细写。
1.1 综述一下BN的公式
在一个batch中,在每一BN层中,对每个样本的同一通道,计算它们的均值和方差,再对数据进行归一化,归一化的值具有零均值和单位方差的特点,最后使用两个可学习参数gamma和beta对归一化的数据进行缩放和移位。
1.2 实际优点:
1)与没有BN相比,可使用更大的学习率
2)防止过拟合,可去除Dropout和Local Response Normalization
3)由于dataloader打乱顺序,因此每个epoch中mini-batch都不一样,对不同mini-batch做归一化可以起到数据增强的效果。
4)明显加快收敛速度
5)避免梯度爆炸和梯度消失
1.3BN的缺点:
- 依赖batchsize尺寸,如果这个尺寸较小时,可以考虑采用layer norm,Instance Norm, Group Norm.这三者都和batchsize无关。
- 对于RNN这列的动态网络效果不明显,需要采用layer Norm。
- 在GAN领域中,style transfer和domain adaptation这类生成任务上,BN对多个样本统计均值和方差,而这多个样本的domain很可能是不一样的,相当于模型把不同domain的数据分布进行了归一化。因此需要使用Instance Norm。
- 当batch size减少时,BN退化明显,而Group Normalization始终一致,在batch size比较大的时候,略低于BN,但当batch size比较小的时候,明显优于BN。
- BN使用训练过程中每个mini-batch的均值和方差的期望作为推理过程中的均值和方差,这样做的前提是mini-batch与样本总体是独立同分布的。因此BN的第三个缺陷是当mini-batch中的样本非独立同分布时,性能比较差。
《Rethinking “Batch” in BatchNorm》这篇文章主要总结了一些batchNorm在使用的时候可能的坑,并且推荐了一些方法避开这些坑。当不得不使用BN来实现归一化的时候,当不想改变为其他的归一化方法的时候,这篇文章中提到的一些技巧,可以再实际操作的时候,帮助我们提高模型的效果。
二、BatchNorm实际应用中的问题
从数据量的角度来说,一个batch可以是整个数据集,也可以只有的2张图片构成batch。
从数据来源来说,一个batch的数据可以来自同一个域(同一个数据集),也可以混合不同域的图片(不同的数据集来源)作为一个batch。那么在训练的时候,不同的数据量和不同的域数据的组合,可能会导致模型在BN这里出现不同的训练效果。
《Rethinking “Batch” in BatchNorm》通过实验总结了如果不加选择的随意使用BN的一些现象,以及这些现象如何对模型的最终结果产生不利的影响。
这里先说一些基本的术语:
- NBS:Normalization Batch Size,表示一台GPU上的batchsize
- BS:total Batch Size或者SGD, BS,表示一次梯度更新过程中涉及到的所有图片数量。在单机训练中,NBS=BS;在分布式训练中,假设GPU数量为K,那么BS=K*NBS
- iteration和epoch:训练数据的一次反向传播的过程为一个iteration,一个epoch是所有数据都完成一轮iteration的过程。
这篇文章的主要场景可以总结为三点:
- 推理的过程中,推理使用的BN的参数主要有两个,分别是均值和方差。在torch中用running mean,running variance表示。这两个全局统计值(population statistics)是在训练过程中使用EMA(exponential moving average)的方式遍历整个训练集合和所有的epoch得到的。这种方式可能会导致不稳定的验证效果(validation performance)。本文提出了一个preciseBN的概念可以更加准确的得到均值和方差的全局统计值。
- 训练阶段和推理阶段,BN的表现存在区别。在训练时,BN的均值和方差采用的是当前mini-batch的均值和方差,而在推理的阶段则采用的是训练数据的全局统计值作为均值和方差。那么当在训练过程中采用全局统计信息会怎么样?在推理阶段采用验证数据集的当前mini-batch的均值和方差,效果有会怎么样?
- 使用来自不同域domain数据时,不恰当的BN设置会导致域迁移问题。这里的不同域可以指来自不同的训练集合,也可以是FPN中不同的特征层,这两种形式都会导致数据的分布和形态不同。
2.1-2.2章节会展开讲问题1;
2.3-2.4章节会展开讲问题2;
2.5章节会展开讲问题3.
每个问题的解决都会带有详细的实验数据,我本人是非常建议去看一下这个实验的数据和思路的,因为这对于我们自己调参过程中遇到问题该怎么解决有很好的启发意义。以及当我们在训练过程中看到损失函数发生类似的变化时,能不能想起曾经看过这样的曲线变化,由此能够快速的想到自己当前遇到的问题的可能原因,逐一排查。
2.1 EMA更新算法存在的问题
BN的全局统计值running mean和running variance主要在训练过程中被记录和更新,但是在训练过程中并不会使用;这两个参数只有在推理的时候才会被使用。主流计算方式是EMA,具体公式如下
一般
λ
\lambda
λ参数会设置的比较大,
0.9
,
0.99
,
0.999
0.9,0.99,0.999
0.9,0.99,0.999等等。
- 当 λ \lambda λ参数较大时,全局统计值更新较慢,每个迭代只会带来(1- λ \lambda λ)的贡献。当模型需要更新、局部调优、模型迁移的时候,这种缓慢的全局参数更新带来的影响尤为明显。
- 当 λ \lambda λ参数较小时,也会导致全局统计值大部分依赖于最近几轮迭代的统计数据,这样的数据并不能称为全量统计值。
2.1.1 实验一、
实验A
实验配置:在分布式环境中训练ImageNet图像分类任务,模型选择ResNet-50;采用256个GPU,每个GPU上的NBS=32,那么实际的BS=8192。
EMA的更新方式为每轮整合所有GPU上mini-batch的均值和方差来更新全局统计量,更新变量lambda为0.9;这里为了方便量化,作者只比较和绘制全局统计量中的均值mean,绘制成红色点。
作为比较,作者随机选择了100个GPU上的均值,然后绘制成蓝色点集合。100个GPU上的数据一共3200个样本,这个数据基本可以反应当前数据在该BN上的均值分布情况。
从上图可以发现,在迭代的初期(epoch较少的阶段),EMA值和该轮迭代的实际数据分布存存在较大偏移,但是到了epoch更多的时候,EMA基本可以和实际数据的分布保持一致了。
实验B:
实验配置依旧如上。
红色点为EMA算法计算得到的均值;蓝色点为当前100个GPU上的3200个图片相对于BN层的真实统计值均值。可以看到EMA方式计算得到的全局统计值变化是落后于真实的特征层的数据均值变化情况的。当然这里只给出到27epoch的观察情况,按照上面实验图的分析,后面的EMA均值应该会逐步趋于和真实统计值一致。
实验一的目的是说明EMA算法在训练前期存在的问题。
给我们的踩坑经验是:如果准备训练的epoch较少且训练数据也比较少的情况下,那么需要注意EMA得到的值并不是真实的数据分布情况。
这时候想要得到真实可靠的BN全局统计值,可以采用下面提到的PreciseBN。
2.2 PreciseBN
不同于EMA算法逐步小比率的增加当前iteration对于全局统计值的贡献。
PreciseBN的做法如下:
(1)固定除了BN之外的其他参数,将整个训练集的数据按mini batch size送入模型,然后记录每个mini batch的均值和方差。
(2)将记录的每个mini batch的均值和方差统计之后,汇总得到全局统计值。
公式化的表示如下:
对于数据量为N的训练集合,假设minibatch=B,那么需要整合k=N/B次数据,每次都可以获得每个minibatch的均值和方差
计算全局统计值公式如下
2.2.1 实验二
作者做了实验对比EMA算法和PreciseBN算法对于推理效果的影响;
- 实验A观察了在中等规模的分布式训练中,两者的验证集错误率分布情况;
- 实验B观察了在大规模的分布式训练中,两者的验证集错误率分布情况,展示了EMA在大规模数据集上的不稳定性;
- 实验C展示了在小的batchsize配置中,模型无法统计出较好的BN全局参数,无论是EMA还是preciseBN。
总之,PreciseBN这种方式除了会增加较小的时间开销外,可以给模型的稳定训练带来更多的增益。
实验A:
实验配置:实验采用ImageNet的分类任务、采用ResNet50模型,分布式环境,8GPUS,每个GPU的mini batchsize=32,那么一轮的总BNsize为256。
实验在每轮epoch结束之后,都采用EMA方法得到的全局统计值和PreciseBN得到的全局统计值,在验证集上进行推理和统计错误率,这里的验证集和训练集是同源数据。图中蓝色线是训练误差,红色虚线是采用EMA算法的验证集误差,红色实线表示preciseBN的验证集误差。可以看到采用PreciseBN的在所有epoch中效果都比较稳定,而EMA算法因为前期模型没有收敛,所以在验证集上没有那么稳定,但是在后期也达到了和preciseBN相同的效果。
这个实验证明的内容同样是EMA算法在模型训练前期不能完全表示整体数据的统计值,并且会有波动,但是随着训练epoch的继续,EMA确实的效果和preciseBN类似。preciseBN牺牲了一些统计时间,但是能保证整体训练过程中,炼丹师观察到的验证集误差是比较稳定的跟随训练集误差的。
实验B:
和实验A类似,但是这里每轮iteration的batchsize更大,采用256个GPU,每个GPU在每轮迭代中的mini batchsize=32,因此一轮迭代的batchsize=8192,按照学习率的线性共增原则,学习率也要变成实验A的32倍。
同样在每个epoch结束之后,分别采用EMA和preciseBN计算全局统计值用于推理阶段,收集不同epoch阶段的验证误差。红色为batchsize=256(也就是实验A的配置),绿色为batchsize=8192(更大的batchsize)。
可以看到对于大的batchsize来说,EMA在训练前期阶段带来的验证集合错误率的不稳定显然比小的batchsize的情况更加严重。这也很好理解,batchsize的增大导致一个eopch中包含的iteration减少了,EMA的更新策略没有改变,它需要一定的iteration的更新才能逐渐趋于真实的训练集统计值。
可以参考实验一(A),在那个实验中,配置和当前这个实验一致,EMA计算均值和该轮的统计均值在前面的30轮都无法很好的拟合。除了上面提到的一个epoch中的iteration减少之外,另一个可能是原因是前期较大的学习率使得特征的变化比较巨大,因此模型在训练前期不稳定。
这就导致了**对于大的batchsize来说,如果采用EMA更新BN的全局统计值,那么需要更多的epoch才能统计出较为真实可靠的全局统计值。显然preciseBN更加适合于大规模的Batchsize 的情况。**preciseBN只需要 1 0 3 到 1 0 4 10^3 到10^4 103到104的样本即可,并不需要全量的统计数据(来自论文实践),在这个数据量级上,采用preciseBN只会带来0.5%的额外训练开销。preciseBN可以稳定训练过程中,炼丹师观察到的验证集误差,避免炼丹师由于EMA导致的验证集误差率不稳定而做出错误的判断。(很显然,作为一个非全知的炼丹师,当看到验证集波动很大的时候,并不一定能一下子排查到是EMA算法的问题,内心肯定是慌的,会去检查数据集、检查loss,检查学习率等等细节)
实验C
小的BN配置存在的问题,按照BN在每轮iter中计算均值和方差的公式可以看出,每个样本都会影响均值和方差的计算,影响BN层的输出,这种影响会想蝴蝶效应一样,进一步影响更深层网络的BN层以及该层的统计数据。
采用preciseBN的方式计算统计值同样会受到上述影响:均值不会受到影响,但是方差公式会受到每个mini-batch的方差差异的影响。
在这个实验中,验证集推理过程中模型的BN统计值是采用preciseBN计算得到的。
其中B表示参与计算preciseBN的样本总量,NBS表示分布式单个GPU的batchsize。
下图展示了训练100个epoch之后的效果,当NBS=32的误差率明显优于NBS=2的效果;在这个ImageNet数据集上,B数量级达到
1
0
2
10^2
102~
1
0
3
10^3
103,preciseBN就可以得到稳定优于EMA的效果了。
总之,这个实验给我们的经验为,无论是分布式环境还是单机环境,无论采用EMA算法还是preciseBN算法计算BN层的统计值,尽量避免采用小的batchsize,如果无法避免small batchsize,那么尽量采用preciseBN算法。
2.2.2 总结:
可以看到preciseBN在模型训练前期,或者说模型没有收敛的时候,效果要优于EMA算法。
但是EMA之所以还是一种主流的BN全局统计量计算方法,是因为在给出足够的训练时间或者在收敛的模型上,EMA算法的效果和preciseBN的效果基本一致。
因此我们可以根据实际的应用场景来选择使用EMA或者preciseBN的计算方式。
哪些情况下必须要进行preciseBN?
- 类似SWA等深度集成网络模型,这类模型会采用多轮训练中的权重均值,因此最后生成的模型必须进行依次preciseBN操作
- 域迁移模型,当模型被迁移到其他的数据域
- 当测试数据集量化的过程中,需要进行模型的BN全局统计量重新计算
总之就是所有涉及到训练-测试过程中,模型或者数据产生不一致性的时候,都需要重新计算BN的全局统计量。
2.3 训练和测试中数据不一致性以及训练误差和BN的关系
这部分主要通过实验方式观察如下问题:
- 在分布式环境中,配置的NBS不同,会给训练带来什么影响?
- 在测试过程中,使用训练过程的preciseBN全局统计量(这个实验放在2.4中);以及在测试过程中,使用测试数据的当前iter的统计量作为BN层的均值和方差;这两个曲线趋势和差异可以表示训练和测试数据的不一致性带来的误差,这个误差影响大吗?
2.3.1 实验三
测试在分布式环境中,保持整体的BS=1024不变,从2~1024改变NBS的数值,观察NBS尺寸是如何影响训练噪声training noise和训练-测试不一致性的train-test inconsistency。
这个实验的图表和观察的结论稍微有一点难以理解。
横轴是NBS(也就是单个GPU上的batchsize的规模),纵轴是错误率。
首先观察绿色线条。绿色线条表示训练误差,训练过程中对于一个btach在BN中采用的均值和方差都是直接当前batch的特征图得到的,对于规模越小的NBS,其中的单个样例的输出强依赖于该批次中其他的随机样本,因此NBS越小,其训练的错误率越大,这就是训练噪声导致的。
蓝色线条表示采用验证集该批次样本的特征值计算得到的BN层均值和方差u_B,sigma_B,注意样本数量要和训练时采用的NBS一致。
红色线条表示采用preciseBN采集的全局特征值 μ p o p \mu_{pop} μpop, σ p o p \sigma_{pop} σpop,固定这些值,将其用于推理验证集合。
其次观察绿色线条和红色线条之间的gap,这个gap比较容易理解,这是验证集和训练集之间因为数据的差异导致的天然的gap。
最后理解一下红色和蓝色线条之间的趋势变化。在NBS较大的情况下,使用preciseBN的效果优于使用验证集局部NBS计算的均值和方差。在NBS较小的情况中,效果相反,这是因为验证集数据和训练数据集的不一致性在小的NBS上更加突出的体现。采用自身数据均值和方差的蓝色线条一直都比较稳定。因此如果NBS较小,那么有条件可以使用验证集自身的均值方差,会得到更低的误差。当然这种方式一般很难实现,因为模型使用者不一定是模型开发者,既不能确定训练者的NBS是大是小(在NBS较大的情况下,采用训练集的preciseBN得到的误差率更低,因此应该采用preciseBN的统计值),也不能保证一次推理BS>1(实际使用经常是一张图片一次推理).
但是使用测试集合的BN层均值和方差真的很香,于是作者在可以使用推理时均值方差的场景(RCNN)中进行了一些测试,再次证明了在小的BN上,使用推理时样本的均值和方差的真香过程。这里我就不记录这个实验了,有点重复了,想要了解可以看作者论文的4.2节。
总结:为了抑制训练噪声,设置的NBS不能太小;为了抑制训练集合和测试集合的不一致性,NBS也不能太小。
2.4 训练阶段采用全局统计量
一般在BN的定义中,训练过程中使用该iter的NBS数据作为当前均值和方差的计算输入,而不会在训练过程中采用全局统计量,这是因为EMA的全局统计量计算方式会导致模型无法训练,其次是因为如果固定了训练过程中的均值和方差,那么整个BN层就相当于退化成一个固定的仿射变换, BN层也失去了在训练过程中归一化当前数据的输出的功能。
在比较特殊的场合中,会用到frozenBN,将BN的参数固定下来,既不更新全局统计量,也不更新参数 β \beta β和 γ \gamma γ。这样做可能有如下的原因:
- 模型已经训练稳定或者完成了,然后需要通过小的数据进行微调,但是计算资源不够,每次训练的BS只有1或者2,索性就不更新BN了,直接用稳定的BN参数即可;
- 需要迁移到下游任务中,此时的数据基本是同源数据,不需要进行BN参数的更新。
frozenBN就是一种在训练阶段采用全局统计量的方法,将BN层退化为普通的,不参与训练过程更新的参数。
实验四:
该实验在实验三的基础上进行,实验配置基本和实验三一致。首先选择一个训练了80 epoch的checkpoint,此时模型比较稳定的,然后分别采用三种手段进行训练
- A:红色线条,继续采用原本的训练方式训练20epoch;验证集的推理过程采用训练集上BN的全局统计量作为BN的参数
- B:绿色线条,采用frozenBN的方式进行后面20epoch;验证集的推理过程采用训练集上BN的全局统计量作为BN的参数
- C: 蓝色线条,采用原本的训练方式训练20epoch;验证集的推理过程采用验证集数据当前batch的均值和方差作为BN的参数
-
观察/启迪:
- NBS较大的时候,常规训练即可实现最小的误差率,大力破奇迹
- 当资源受限,NBS比较小的时候,先用训练数据训练一个稳定的模型,然后用frozenBN的方式,可以有效抑制训练-测试的不一致性。
结合实验二的C实验和实验三可以发现,当不得已面对小的NBS的时候,我们可以做的是
- 使用preciseBN替换EMA算法,实验二C的第二行采用EMA算法得到的误差率为35.5%,但是采用preciseBN且B=N(全量数据)的时候,可以降低3.5%的误差率
- 验证集的推理过程采用验证集数据当前batch的均值和方差作为BN的参数;或者采用frozenBN进行稳定后的训练都可以进一步大量的较少误差,大约可以减少6.5%以上的误差。
- 在使用小的BS的时候,还可以采用BRN(BatchRenorm),Moving Average BatchNorm(MABN),这些都可以减少训练误差
2.5 不同数据域带来的问题
数据域可以理解为不同的数据集具有不同的数据分布域。
将有BN参与的模型的训练分为两个部分,一个部分是采用SGD等优化算法更新模型参数,另一部分为通过EMA或者preciseBN等方法计算统计数据。那么当在一个数据域进行训练,然后在另一个数据域进行推理;或者在多个数据域进行训练,但是在单一数据域进行推理;都有产生域差异问题(domain gap).
目前针对这种数据域差异的问题提出了Adaptive BatchNorm(2016)方式
2.5.1 实验五、
实验A
这个实验主要是展示在一个数据域进行训练,然后在另一个数据域进行推理过程中,BN应该如何训练或者说统计才能比较好的适应域迁移问题。
实验依旧采用ResNet50,BS=1024,NBS=32;数据集为来自ImageNet。在评估阶段采用ImageNet-C任务的三个不同域数据:contrast, gaussian noise, jpeg compression数据进行。训练过程中,计算BN的统计数据的时候,分别采用ImageNet全量数据(IN)或者采用对应验证集的1000张图片的数据(IN-C-XXXX)进行计算。为了避免训练集合和验证集合的重叠,参与计算BN统计数据的1000张验证集图片就不会参与误差率的统计了,其余对应验证集的数据作为验证数据。
第一行数据表示验证集为ImageNet-C-contrast集合,在训练过程计算BN的全局统计量,采用ImageNet的数据计算BN后,验证集的错误率有40.8%,但是如果在计算全局统计量的时候,采用了ImageNet-C-contrast的1000张数据,那么错误率可以降低为33.1%.
实验结果标明,对于存在明显域偏移的训练-测试数据集,如果能够采用测试集的数据进行BN的统计数据,那么效果会有明显的改善,需要注意的是,炼丹师需要收集足够多的验证数据域的数据来记性BN统计数据的计算,这往往不容易做到。另一个方面来说,如果需要进行模型迁移,那么对其中的BN统计数据进行额外的计算,可以带来不错的增益。
额外注意一下最后一行的实验,在这个实验中,通过对ImageNet验证集合数据计算了BN的统计数据,但是效果反而降低了0.4%,那么在分析训练数据集和验证数据集的时候,是否需要在验证推理之前进行额外的BN统计数据重计算,就需要炼丹师自己衡量了。
实验B
BN操作的特点是他的输出依赖于不仅依赖单个样本,还依赖于样本集合的组合。
X i X_i Xi表示一个输入batch。如果将一个数据域的数据表示为一个batch,公式中左边可以理解为多个数据域联合归一化的输出结果,右边为每个数据域各自归一化。
实验B实验如下,提供过RetinaNet在FPN模型过程中有五个来自不同层级的特征层(图中展示了三个),这些特征输出就可以理解为来自不同的数据域,那么究竟是采用每个特征层数据单独计算(domain-specific);还是通过将5个特征层flatten、concat之后统一计算(shared)。这两个不同的过程分别展示在上面的图a和图b中。
这两种方式分别出现在SGD training和BN population stats统计数据计算阶段和BN的仿射阶段。
SGD training阶段的Domain-specific表示在梯度下降法在主导的训练中,BN层的u_B和sigma_B是来自不同数据域的;shared表示BN层的u_B和sigma_B计算来自混合数据域的结果
Population Stats的Domain-specific表示不同域的全局统计量单独统计;shared表示全局统计量将不同域的数据统计成一个值;
Affine Parameters也是如上类似,不赘述。
实验的结果标明,对于来自不同域的数据,需要保证在SGD训练阶段、统计数据计算阶段的策略一致性,就可以得到比较满意的结果。要么都使用domain-specific,要么都采用shared方式,而BN中的仿射变换则不那么重要。当然这个实验最后两行给出了采用groupNorm和不使用BN的效果,使用GN的效果会更好一些。
三、总结
其实在BN训练过程中需要注意的事项都具体到每个实验下面的总结中了,所以这里就不再做总结了。
写到这里发现字数已经九千多了,写了好几天了,感觉自己就要写不动了。如果觉得这个小结真的有用的话,欢迎交流呀~