syncbn在TensorFlow中的实现

在syncbn之前我们先简单介绍一下BN层以及多卡机制

  1. BN层介绍
    BN层中有两个可训练参数(beta, gamma),以及两个统计参数(moving mean, moving variance)。训练过程和测试过程,BN层计算方式是不同的。训练过程,beta和gamma与卷积层中的weight是一样参与训练的,然后moving mean与moving variance由当前的batch mean和batch variance统计的,可以在训练过程的BN层可以用下列公式表示:
    y = γ × x − m e a n b a t c h v a r i a n c e b a t c h + ε + β y = \gamma \times \frac{x- mean_{batch}}{\sqrt{variance_{batch} + \varepsilon}} + \beta y=γ×variancebatch+ε xmeanbatch+β
    m e a n m o v i n g = d e c a y × m e a n m o v i n g + ( 1 − d e c a y ) × m e a n b a t c h mean_{moving}=decay \times mean_{moving} + (1-decay) \times mean_{batch} meanmoving=decay×meanmoving+(1decay)×meanbatch
    v a r i a n c e m o v i n g = d e c a y × v a r i a n c e m o v i n g + ( 1 − d e c a y ) × v a r i a n c e b a t c h variance_{moving} = decay \times variance_{moving} + (1-decay) \times variance_{batch} variancemoving=decay×variancemoving+(1decay)×variancebatch
    测试过程(以及BN层不参与训练时),beta和gamma采用跟weight相同的使用方式,然而使用moving mean和moving variance替代batch mean和batch variance,所以测试过程中的BN层可以用下列公式表示:
    y = γ × x − m e a n m o v i n g v a r i a n c e m o v i n g + ε + β y = \gamma \times \frac{x- mean_{moving}}{\sqrt{variance_{moving} + \varepsilon}} + \beta y=γ×variancemoving+ε xmeanmoving+β

  2. 多卡机制
    目前的多卡训练可以分成异步式和同步式。我们这里讲同步式,同步式是指将模型复制到各个GPU上,数据切分分发到各个GPU上,如resnet50模型复制到8个GPU上,如果batch size=256, 那么每个GPU上的batch size=256/8=32。由于tensorflow, pytorch, caffe, caffe2等开源网络框架对于效率的考虑,且在传统图像分类任务中,单卡的batch size就能设置的很大对于BN层的统计影响不大,所以各大网络框架都没有做BN的同步(moving mean和moving variance的同步)。然而对于semantic segmentaion,object detection等任务来说,单卡统计的数量很小甚至为1,所以BN层中moving mean, mean variance存在很大的扰动,这便造成了BN层的失效。通过以上的分析可以看出BN的同步很有必要。对于BN层的更多实验结果可以参照旷视的文章《MegDet:A Large Mini-Batch Object Detector》

  3. 多卡同步
    对于pytorch的多卡BN层同步已经有了一些解决方案,如 syncbn-pytorch 。对于MXNet的多卡同步已经被整合到了官方的API中。对于TensorFlow也有一些方法,如将每个操作均同步如:

def relu(list_input):
    assert type(list_input) == list
    list_output = []
    for i in range(len(list_input)):
        with tf.device('/gpu:%d' % i):
            output = tf.nn.relu(list_input[i], name='relu')
            list_output.append(output)
    return list_output

但是这种方式代码量略大。tensorpack大神也提出了他们的方法,但是他们的方法也需要依赖tensorpack。我实现了一下syncbn-tensorflow,具体实现可以看 syncbn-tensorflow, 这种方式可以对原来的代码进行非常小的改动,就能实现多卡同步了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值