PyTorch踩坑指南(1)nn.BatchNorm2d()函数

PyTorch踩坑指南(1)nn.BatchNorm2d()函数前言最近在研究深度学习中图像数据处理的细节,基于的平台是PyTorch。心血来潮,总结一下,好记性不如烂笔头。BatchNormalization对于2015年出现的BatchNormalization1,2018年的文章GroupNormalization2在Abstract中总结得言简意赅,我直接copy过来。BatchNormalization(BN)isamile…

大家好,又见面了,我是你们的朋友全栈君。

前言

最近在研究深度学习中图像数据处理的细节,基于的平台是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=0N1w=0W1h=0H1X[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=0N1w=0W1h=0H1(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 NWH

PyTorch的nn.BatchNorm2d()函数

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

  • num_features:一般情况下输入的数据格式为batch_size * num_features * height * width,即为特征数,channel数
  • eps:分母中添加的一个值,目的是为了计算的稳定性,默认:1e-5
  • momentum:一个用于运行过程中均值和方差的一个估计参数,默认值为 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=(1momentum)×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=0N1(ximean(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=N1i=0N1(ximean(x))2

Reference


  1. Ioffe, Sergey, and Christian Szegedy. “Batch normalization: Accelerating deep network training by reducing internal covariate shift.” arXiv preprint arXiv:1502.03167 (2015). ↩︎ ↩︎

  2. Wu, Yuxin, and Kaiming He. “Group normalization.” Proceedings of the European Conference on Computer Vision (ECCV). 2018. ↩︎

  3. BatchNorm2d ↩︎

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/134016.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 向量与矩阵范数_矩阵范数与谱半径的关系

    向量与矩阵范数_矩阵范数与谱半径的关系范数(norm),是具有“长度”概念的函数。在线性代数、泛函分析及相关的数学领域,范函是一个函数,其为矢量空间内的所有矢量赋予非零的正长度或大小。半范数反而可以为非零的矢量赋予零长度。举一个简单的例子,在二维的欧氏几何空间R就可定义欧氏范数。在这个矢量空间中的元素常常在笛卡儿坐标系统中被画成一个从原点出发的带有箭头的有向线段。每一个矢量的欧氏范数就是有向线段的长度。其中定义范数的矢量空间就是赋范矢

    2022年9月19日
    2
  • 给你的wordpress博客中加入喜欢的鼠标指针

    想给你的博客加个喜欢的鼠标指针吗?其实很简单的,wordpress中要加入只需修改皮肤中的css。在body中插入cursor:url(‘鼠标指针网址’)}就可以了,如果想修改鼠标指针接触到链接的鼠标样式,那只要在a中插入cursor:url(‘鼠标指针网址’),我用的是个企鹅,挺好玩的。我也发上来,喜欢的可以用用。鼠标指针转载于:https://www.cnblogs.com/joyp…

    2022年4月12日
    51
  • elementUI 时间格式化

    elementUI 时间格式化1.html:<el-table-columnprop=”dateTime”:formatter=”dateFormat”label=”日期”></el-table-column>2.vue的methods里面//方法methods:{//时间格式化dateFormat(row,colum…

    2022年5月20日
    48
  • 使用 vsphere-automation-sdk-python 自动创建虚拟机

    使用 vsphere-automation-sdk-python 自动创建虚拟机

    2021年7月9日
    280
  • 程序员常用的十一种算法

    程序员常用的十一种算法程序员常用的十一种算法1.二分查找算法2.分治法3.动态规划4.字符串暴力匹配算法5.KMP算法6.贪心算法7.普里姆算法介绍(找点)8.克鲁斯卡尔(Kruskal)算法(找边)9.迪杰斯特拉算法10.弗洛伊德算法11.骑士周游回溯算法……

    2022年10月19日
    2
  • 页面处理指令中的AutoEventWireup

    页面处理指令中的AutoEventWireup   在页面处理指令中有个AutoEventWireup,当时不知什么原因就删了,接着就除了问题.后来才知道它是指页面的事件是否自动连网。如果启用事件自动连网,则为true;否则为false。如果页面处理指令的AutoEventWireup属性被设置为true(默认为true),该页框架将自动调用页事件。所以如果是使用code-behind技术,就要把AutoEventWireu

    2022年5月26日
    45

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号