pytorch中nn模块的BatchNorm2d()函数

本文深入解析了PyTorch中BatchNorm2d层的工作原理,包括其在卷积神经网络中的作用,以及如何通过设置参数eps和momentum来稳定计算。通过实例代码展示了BatchNorm2d层的使用,并通过计算验证了其内部运算的正确性,加深了对BatchNorm2d的理解。
摘要由CSDN通过智能技术生成

 基本原理

class torch.nn.BatchNorm2d(num_features,eps=1e-5,momentum=0.1,affine=Ture)

在卷积神经网络的卷积层之后总会添加BatchNorm2d进行数据的归一化处理,这使得数据在进行Relu之前不会因为数据过大而导致网络性能的不稳定,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.7750, -0.1111, -0.1195,  0.4326],
          [ 0.1045, -0.6765,  2.1103,  0.1525],
          [-0.6954, -0.5788, -0.0701,  0.0449]],

         [[-0.2792,  1.2866, -0.8721, -0.6230],
          [-1.2168, -0.0202,  0.6909, -0.1642],
          [ 0.6963, -0.1544, -0.6271, -0.9726]]]])# m[1,2,3,4]:通道数为1,2个三行四列的矩阵
Parameter containing:
tensor([1., 1.], requires_grad=True) # weight
Parameter containing:
tensor([0., 0.], requires_grad=True) # bias
tensor([[[[-1.9338, -0.0145, -0.0243,  0.6125],
          [ 0.2341, -0.6667,  2.5478,  0.2894],
          [-0.6886, -0.5541,  0.0327,  0.1654]],

         [[-0.1260,  2.0365, -0.9449, -0.6008],
          [-1.4209,  0.2318,  1.2138,  0.0328],
          [ 1.2213,  0.0464, -0.6064, -1.0836]]]],
       grad_fn=<NativeBatchNormBackward0>)
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.7750, -0.1111, -0.1195,  0.4326],
        [ 0.1045, -0.6765,  2.1103,  0.1525],
        [-0.6954, -0.5788, -0.0701,  0.0449]])
BatchNorm2d(2, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
m.eps= 1e-05
tensor(-0.0985)
tensor(0.7516)

我们可以通过计算器计算出均值和方差均正确计算。最后通过公式计算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(-1.9338, grad_fn=<AddBackward0>)

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

ps:上面计算方差时有一个贝塞尔校正系数,具体可以通过如下链接参考:贝塞尔校正(Bessel's Correction) - 简书

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

                                                   

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

                                                   

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值