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

【PyTorch】详解pytorch中nn模块的BatchNorm2d()函数基本原理在卷积神经网络的卷积层之后总会添加BatchNorm2d进行数据的归一化处理,这使得数据在进行Relu之前不会因为数据过大而导致网络性能的不稳定,BatchNorm2d()函数数学原理如下:BatchNorm2d()内部的参数如下:1.num_features:一般输…

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

基本原理

在卷积神经网络的卷积层之后总会添加BatchNorm2d进行数据的归一化处理,这使得数据在进行Relu之前不会因为数据过大而导致网络性能的不稳定,BatchNorm2d()函数数学原理如下:

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

BatchNorm2d()内部的参数如下:

1.num_features:一般输入参数为batch_size*num_features*height*width,即为其中特征的数量

2.eps:分母中添加的一个值,目的是为了计算的稳定性,默认为:1e-5

3.momentum:一个用于运行过程中均值和方差的一个估计参数(我的理解是一个稳定系数,类似于SGD中的momentum的系数)

4.affine:当设为true时,会给定可以学习的系数矩阵gamma和beta

上面的讲解还不够形象,我们具体通过如下的代码进行讲解:

代码演示

#encoding:utf-8
import torch
import torch.nn as nn
#num_features - num_features from an expected input of size:batch_size*num_features*height*width
#eps:default:1e-5 (公式中为数值稳定性加到分母上的值)
#momentum:动量参数,用于running_mean and running_var计算的值,default:0.1
m=nn.BatchNorm2d(2,affine=True) #affine参数设为True表示weight和bias将被使用
input=torch.randn(1,2,3,4)
output=m(input)

print(input)
print(m.weight)
print(m.bias)
print(output)
print(output.size())

具体的输出如下:

tensor([[[[ 1.4174, -1.9512, -0.4910, -0.5675],
          [ 1.2095,  1.0312,  0.8652, -0.1177],
          [-0.5964,  0.5000, -1.4704,  2.3610]],

         [[-0.8312, -0.8122, -0.3876,  0.1245],
          [ 0.5627, -0.1876, -1.6413, -1.8722],
          [-0.0636,  0.7284,  2.1816,  0.4933]]]])
Parameter containing:
tensor([0.2837, 0.1493], requires_grad=True)
Parameter containing:
tensor([0., 0.], requires_grad=True)
tensor([[[[ 0.2892, -0.4996, -0.1577, -0.1756],
          [ 0.2405,  0.1987,  0.1599, -0.0703],
          [-0.1824,  0.0743, -0.3871,  0.5101]],

         [[-0.0975, -0.0948, -0.0347,  0.0377],
          [ 0.0997, -0.0064, -0.2121, -0.2448],
          [ 0.0111,  0.1232,  0.3287,  0.0899]]]],
       grad_fn=<NativeBatchNormBackward>)
torch.Size([1, 2, 3, 4])

分析:输入是一个1*2*3*4 四维矩阵,gamma和beta为一维数组,是针对input[0][0],input[0][1]两个3*4的二维矩阵分别进行处理的,我们不妨将input[0][0]的按照上面介绍的基本公式来运算,看是否能对的上output[0][0]中的数据。首先我们将input[0][0]中的数据输出,并计算其中的均值和方差。

print("输入的第一个维度:")
print(input[0][0]) #这个数据是第一个3*4的二维数据
#求第一个维度的均值和方差
firstDimenMean=torch.Tensor.mean(input[0][0])
firstDimenVar=torch.Tensor.var(input[0][0],False)   #false表示贝塞尔校正不会被使用
print(m)
print('m.eps=',m.eps)
print(firstDimenMean)
print(firstDimenVar)

输出结果如下:

输入的第一个维度:
tensor([[ 1.4174, -1.9512, -0.4910, -0.5675],
        [ 1.2095,  1.0312,  0.8652, -0.1177],
        [-0.5964,  0.5000, -1.4704,  2.3610]])
BatchNorm2d(2, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
m.eps= 1e-05
tensor(0.1825)
tensor(1.4675)

我们可以通过计算器计算出均值和方差均正确计算。最后通过公式计算input[0][0][0][0]的值,代码如下:

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

输出结果如下:

tensor(0.2892, grad_fn=<AddBackward0>)

结果值等于output[0][0][0][0]。ok,代码和公式完美的对应起来了。

ps:上面计算方差时有一个贝塞尔校正系数,具体可以通过如下链接参考:https://www.jianshu.com/p/8dbb2535407e 

从公式上理解即在计算方差时一般的计算方式如下:

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

通过贝塞尔校正的样本方差如下:

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

目的是在总体中选取样本时能够防止边缘数据不被选到。详细的理解可以参考上面的链接。

 

 

 

 

 

 

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

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

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


相关推荐

  • android开机动画 制作工具,android开机动画制作

    android开机动画 制作工具,android开机动画制作本帖最后由nihao200823于2017-1-1220:38编辑android开机动画制作与播放原理简介谁都想拥有一个华丽漂亮的开机动画,这让人心情舒畅,android是怎么来实现的?怎么制作一个自己的开机动画?这里揭开android开机动画的神秘面纱。1、制作开关机动画1.1开机动画的位置system/media/bootanimation.zip,要修改开机动画就是修改boota…

    2022年5月14日
    46
  • 数据结构 图的邻接表

    数据结构 图的邻接表呃,下面该写邻接表了…….邻接表的出现是因为图若是稀疏图,用邻接矩阵会造成空间的浪费,毕竟你要开辟一个一维数组和一个二维数组嘛,而且还是大开小用的那种。邻接表为了避免内存的浪费引入了链式存储,它的处理办法是:1.用一个一维数组存储顶点,当然你也可以用单链表存储,2.用单链表存储顶点的邻接点,可以将顶点改为结构体数组,结构体中存放邻接点的指针,邻接点也创建一个结构体,定义指针…

    2022年6月28日
    22
  • nextline函数_在JAVA中Scanner中的next()和nextLine()为什么不能一起使用?

    nextline函数_在JAVA中Scanner中的next()和nextLine()为什么不能一起使用?Java输入一直是一个坑,本来一直用Scanner,但一直搞不懂换行符啥的,就用BufferReader,但前不久大疆笔试需要持续输入,早忘了Scanner怎么写,而那个场景用Scanner很好实现……就继续在这里记录一下Scanner的坑吧一、next&nextLine区别next不能得到带有空格的字符串一定要读到有效字符后才可以结束,结束条件是碰到空格…

    2022年6月2日
    40
  • python初级:基础知识-字符串

    python初级:基础知识-字符串

    2021年10月6日
    39
  • Python—数据类型之float类型

    Python—数据类型之float类型浮点类型 Python 提供了 3 种浮点值 内置的 float 与 complex 类型 以及标准的 decimal Decimal 类型 Python 支持混合模式的算术运算 int 与 float 运算 生成 float float 与 complex 运算 生成 complex decimal Decimal 与 intS 运算 生成 decimal Decimal 注意 不兼容的数据类型进行运算 会产生 TypeEr

    2025年9月14日
    3
  • 数据预处理无量纲化处理_统计数据的预处理

    数据预处理无量纲化处理_统计数据的预处理1.无量纲化定义无量纲化,也称为数据的规范化,是指不同指标之间由于存在量纲不同致其不具可比性,故首先需将指标进行无量纲化,消除量纲影响后再进行接下来的分析。2.无量纲化方法无量纲化方法有很多,但

    2022年8月5日
    10

发表回复

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

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