[转载] PyTorch踩坑指南(1)nn.BatchNorm2d()函数

参考链接: input()函数中的漏洞– Python2.x

前言 

最近在研究深度学习中图像数据处理的细节,基于的平台是PyTorch。心血来潮,总结一下,好记性不如烂笔头。 

Batch Normalization 

对于2015年出现的Batch Normalization1,2018年的文章Group Normalization2在Abstract中总结得言简意赅,我直接copy过来。 


 Batch Normalization (BN) is a milestone technique in the development of deep learning, enabling various networks to train. However, normalizing along the batch dimension introduces problems — BN’s error increases rapidly when the batch size becomes smaller, caused by inaccurate batch statistics estimation. This limits BN’s usage for training larger models and transferring features to computer vision tasks including detection, segmentation, and video, which require small batches constrained by memory consumption. 


机器学习中,进行模型训练之前,需对数据做归一化处理,使其分布一致。在深度神经网络训练过程中,通常一次训练是一个batch,而非全体数据。每个batch具有不同的分布产生了internal covarivate shift问题——在训练过程中,数据分布会发生变化,对下一层网络的学习带来困难。Batch Normalization强行将数据拉回到均值为0,方差为1的正太分布上,一方面使得数据分布一致,另一方面避免梯度消失。 

结合图1,说明Batch Normalization的原理。假设在网络中间经过某些卷积操作之后的输出的feature maps的尺寸为N×C×W×H,5为batch size(N),3为channel(C),W×H为feature map的宽高,则Batch Normalization的计算过程如下。  

 图 1


1.每个batch计算同一通道的均值





         μ




        \mu



     μ,如图取channel 0,即





         c



         =



         0




        c=0



     c=0(红色表示) 





          μ



          =






             ∑




              n



              =



              0





              N



              −



              1






             ∑




              w



              =



              0





              W



              −



              1






             ∑




              h



              =



              0





              H



              −



              1





            X



            [



            n



            ,



            c



            ,



            w



            ,



            h



            ]





            N



            ×



            W



            ×



            H






         \mu = \frac{\sum\limits_{n=0}^{N-1}\sum\limits_{w=0}^{W-1} \sum\limits_{h=0}^{H-1} X[n, c, w, h]}{N×W×H}



      μ=N×W×Hn=0∑N−1​w=0∑W−1​h=0∑H−1​X[n,c,w,h]​2.每个batch计算同一通道的方差






          σ



          2





        σ^2



     σ2 






           σ



           2




          =






             ∑




              n



              =



              0





              N



              −



              1






             ∑




              w



              =



              0





              W



              −



              1






             ∑




              h



              =



              0





              H



              −



              1





            (



            X



            [



            n



            ,



            c



            ,



            w



            ,



            h



            ]



            −



            μ




             )



             2






            N



            ×



            W



            ×



            H






         σ^2 = \frac{\sum\limits_{n=0}^{N-1}\sum\limits_{w=0}^{W-1} \sum\limits_{h=0}^{H-1} (X[n, c, w, h]-\mu)^2}{N×W×H}



      σ2=N×W×Hn=0∑N−1​w=0∑W−1​h=0∑H−1​(X[n,c,w,h]−μ)2​3.对当前channel下feature map中每个点





         x




        x



     x,索引形式





         X



         [



         n



         ,



         c



         ,



         w



         ,



         h



         ]




        X[n, c, w, h]



     X[n,c,w,h],做归一化 






           x





            ′





          =





            (



            x



            −



            μ



            )







              σ



              2




             +



             ϵ







         x^{'}=\frac{(x-\mu)}{\sqrt{σ^2+\epsilon}}



      x′=σ2+ϵ



                    ​(x−μ)​4.增加缩放和平移变量





         γ




        \gamma



     γ和





         β




        \beta



     β(可学习的仿射变换参数),归一化后的值 





          y



          =



          γ




           x





            ′





          +



          β




         y=\gamma x^{'}+\beta



      y=γx′+β 简化公式: 





          y



          =





            x



            −



            μ







              σ



              2




             +



             ϵ






          γ



          +



          β




         y=\frac{x-\mu}{\sqrt{\sigma^2+\epsilon}}\gamma +\beta



      y=σ2+ϵ



                    ​x−μ​γ+β 原文中的算法描述如下,  注:上图1所示





          m




         m



      m就是





          N



          ∗



          W



          ∗



          H




         N*W*H



      N∗W∗H 

PyTorch的nn.BatchNorm2d()函数 

理解了Batch Normalization的过程,PyTorch里面的函数就参考其文档3用就好。 BatchNorm2d()内部的参数如下: 

num_features:一般情况下输入的数据格式为batch_size * num_features * height * width,即为特征数,channel数eps:分母中添加的一个值,目的是为了计算的稳定性,默认:1e-5momentum:一个用于运行过程中均值和方差的一个估计参数,默认值为





         0.1




        0.1



     0.1;







           x



           ^





           n



           e



           w





         =



         (



         1



         −



         m



         o



         m



         e



         n



         t



         u



         m



         )



         ×




          x



          ^




         +



         m



         o



         m



         e



         n



         t



         u



         m



         ×




          x



          t





        \hat{x}_{new} =(1−momentum) × \hat{x} +momentum×x_t



     x^new​=(1−momentum)×x^+momentum×xt​,其中






          x



          ^





        \hat{x}



     x^是估计值,






          x



          t





        x_t



     xt​是新的观测值affine:当设为true时,给定可以学习的系数矩阵





         γ




        \gamma



     γ和





         β




        \beta



     β 

Show me the codes 

import torch

import torch.nn as nn

def checkBN(debug = False):

    # parameters

    N = 5 # batch size

    C = 3 # channel

    W = 2 # width of feature map

    H = 2 # height of feature map

    # batch normalization layer

    BN = nn.BatchNorm2d(C,affine=True) #gamma和beta, 其维度与channel数相同

    # input and output

    featuremaps = torch.randn(N,C,W,H)

    output = BN(featuremaps)

    # checkout

    ###########################################

    if debug:

        print("input feature maps:\n",featuremaps)

        print("normalized feature maps: \n",output)

    ###########################################


    # manually operation, the first channel

    X = featuremaps[:,0,:,:]

    firstDimenMean = torch.Tensor.mean(X)

    firstDimenVar = torch.Tensor.var(X,False) #Bessel's Correction贝塞尔校正不被使用


    BN_one = ((input[0,0,0,0] - firstDimenMean)/(torch.pow(firstDimenVar+BN.eps,0.5) )) * BN.weight[0] + BN.bias[0]

    print('+++'*15,'\n','manually operation: ', BN_one)

    print('==='*15,'\n','pytorch result: ', output[0,0,0,0])


if __name__=="__main__":

    checkBN()


可以看出手算的结果和PyTorch的nn.BatchNorm2d的计算结果一致。 

+++++++++++++++++++++++++++++++++++++++++++++

 manually operation:  tensor(-0.0327, grad_fn=<AddBackward0>)

=============================================

 pytorch result:  tensor(-0.0327, grad_fn=<SelectBackward>)


贝塞尔校正 

代码中出现,求方差时是否需要贝塞尔校正,即从样本方差到总体方差的校正。 方差公式从, 






          σ



          2




         =






            ∑




             i



             =



             0





             N



             −



             1





           (




            x



            i




           −



           m



           e



           a



           n



           (



           x



           )




            )



            2





          N





        \sigma^2 = \frac{\sum\limits_{i=0}^{N-1} (x_i-mean(x))^2}{N}



     σ2=Ni=0∑N−1​(xi​−mean(x))2​ 变成(基于样本的总体方差的有偏估计), 






          σ



          2




         =






            ∑




             i



             =



             0





             N



             −



             1





           (




            x



            i




           −



           m



           e



           a



           n



           (



           x



           )




            )



            2






           N



           −



           1






        \sigma^2 = \frac{\sum\limits_{i=0}^{N-1} (x_i-mean(x))^2}{N-1}



     σ2=N−1i=0∑N−1​(xi​−mean(x))2​ 

Reference 



 Ioffe, Sergey, and Christian Szegedy. “Batch normalization: Accelerating deep network training by reducing internal covariate shift.” arXiv preprint arXiv:1502.03167 (2015). ↩︎ ↩︎ Wu, Yuxin, and Kaiming He. "Group normalization." Proceedings of the European Conference on Computer Vision (ECCV). 2018. ↩︎ BatchNorm2d ↩︎

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容