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

本文详细介绍了卷积神经网络中BatchNorm2d的作用和原理,包括其数学公式以及在PyTorch中的实现。通过示例代码展示了BatchNorm2d如何对输入数据进行归一化处理,解释了参数如num_features、eps、momentum和affine的含义,并通过实际计算验证了 BatchNorm2d 的运算过程。文章还提到了贝塞尔校正的概念及其在计算样本方差中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本原理

在卷积神经网络的卷积层之后总会添加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

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

代码演示


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

具体的输出如下:


    
  1. tensor([[[[ 1.4174 , -1.9512 , -0.4910 , -0.5675 ],
  2. [ 1.2095, 1.0312, 0.8652, -0.1177] ,
  3. [ -0.5964, 0.5000, -1.4704, 2.3610] ],
  4. [[ -0.8312, -0.8122, -0.3876, 0.1245],
  5. [ 0.5627, -0.1876, -1.6413, -1.8722],
  6. [ -0.0636, 0.7284, 2.1816, 0.4933]] ]])
  7. Parameter containing:
  8. tensor([0.2837, 0.1493 ], requires_grad=True)
  9. Parameter containing:
  10. tensor([0., 0 .], requires_grad=True)
  11. tensor([[[[ 0.2892 , -0.4996 , -0.1577 , -0.1756 ],
  12. [ 0.2405, 0.1987, 0.1599, -0.0703] ,
  13. [ -0.1824, 0.0743, -0.3871, 0.5101] ],
  14. [[ -0.0975, -0.0948, -0.0347, 0.0377],
  15. [ 0.0997, -0.0064, -0.2121, -0.2448],
  16. [ 0.0111, 0.1232, 0.3287, 0.0899]] ]],
  17. grad_fn=<NativeBatchNormBackward>)
  18. 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]中的数据输出,并计算其中的均值和方差。


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

输出结果如下:


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

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


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

输出结果如下:

tensor(0.2892, grad_fn=<AddBackward0>)
    

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

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

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

                                                   

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

                                                   

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

 

 

 

 

 

 

<think>我们正在讨论PyTorch中的`nn.BatchNorm2d`模块。用户希望了解其函数原型和使用方法。 根据之前的讨论,我们已经详细介绍了`nn.BatchNorm2d`的原理、参数和使用示例。 现在,用户直接要求函数原型和使用方法,我们可以从官方文档和源码角度进行说明。 函数原型(即构造函数参数)已经在之前的回答中给出,但我们可以更正式地列出。 注意:用户提供了几个引用,其中引用[1]指向了nn.Module的源码,引用[2]是PyTorch基础知识的介绍,引用[3]是nn.Module的内部结构。 这些引用虽然不是直接关于BatchNorm2d,但我们可以参考其格式。 由于用户要求的是函数原型(function signature)和使用方法,我们将重点放在这两个方面。 根据PyTorch官方文档,`torch.nn.BatchNorm2d`的签名如下: torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True, device=None, dtype=None) 参数解释: 1. num_features (int): 来自期望输入的通道数,即输入张量的通道数C。 2. eps (float): 为数值稳定性而添加到分母的值。默认值:1e-5。 3. momentum (float): 用于运行均值和运行方差的动量值。如果设置为None,则使用累积移动平均(即简单平均)。默认值:0.1。 4. affine (bool): 当设置为True时,该模块具有可学习的仿射参数(即缩放因子gamma和偏置项beta)。默认值:True。 5. track_running_stats (bool): 当设置为True时,该模块跟踪运行均值和方差;如果设置为False,则不跟踪,并且在训练和评估模式都使用批统计量。默认值:True。 6. device (torch.device, 可选): 模块参数和缓冲区的设备。 7. dtype (torch.dtype, 可选): 模块参数和缓冲区的数据类型。 使用方法: 在定义模型时,通常将BatchNorm2d层放在卷积层之后,激活函数之前(也有放在激活函数之后的,但常见的是在激活函数之前)。在模型的前向传播中,按照顺序通过各层。 我们还可以参考源码中的说明(虽然不是直接给出,但我们可以根据官方文档和之前的知识总结)。 下面我们给出一个使用示例,并解释每一步。 注意:用户已经看到过示例,但我们可以再给一个更详细的,并配合解释。 同时,根据要求,我们需要生成相关问题。</think>### PyTorch `nn.BatchNorm2d` 函数原型与使用详解 #### 函数原型 ```python torch.nn.BatchNorm2d( num_features: int, # 输入特征图的通道数 eps: float = 1e-5, # 数值稳定项(防止除零) momentum: float = 0.1, # 运行统计量更新系数 affine: bool = True, # 是否启用可学习参数γ/β track_running_stats: bool = True, # 是否记录移动平均统计量 device=None, # 计算设备 dtype=None # 数据类型 ) -> None ``` [^1] #### 核心参数说明 | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | `num_features` | int | - | **必须参数**,输入特征图的通道数 $C$ | | `eps` | float | $10^{-5}$ | 添加到方差的小常数,防止数值不稳定 | | `momentum` | float | 0.1 | 运行统计量更新系数:$0 \leq \alpha \leq 1$ | | `affine` | bool | True | 是否启用可学习的缩放参数 $\gamma$ 和偏置参数 $\beta$ | | `track_running_stats` | bool | True | 是否记录全局运行均值 $\mu_{\text{run}}$ 和方差 $\sigma_{\text{run}}^2$ | #### 使用方法示例 ```python import torch import torch.nn as nn # 创建BN层 (输入通道数=64) bn_layer = nn.BatchNorm2d(num_features=64) # 模拟输入数据 (batch_size=8, 64通道, 32x32特征图) inputs = torch.randn(8, 64, 32, 32) # 训练模式:使用当前批统计量 bn_layer.train() output_train = bn_layer(inputs) print(f"训练输出均值: {output_train.mean().item():.4f}") # 应接近0 # 评估模式:使用预存统计量 bn_layer.eval() with torch.no_grad(): output_eval = bn_layer(inputs) print(f"评估输出均值: {output_eval.mean().item():.4f}") ``` #### 关键数学原理 1. **训练阶段计算**: $$ \hat{x} = \frac{x - \mu_{\text{batch}}}{\sqrt{\sigma_{\text{batch}}^2 + \epsilon}} \quad ; \quad y = \gamma \hat{x} + \beta $$ 其中 $\mu_{\text{batch}}$ 和 $\sigma_{\text{batch}}^2$ 是当前批次的统计量[^3]。 2. **运行统计量更新**: $$ \mu_{\text{run}} \leftarrow (1 - \alpha) \cdot \mu_{\text{run}} + \alpha \cdot \mu_{\text{batch}} $$ $$ \sigma_{\text{run}}^2 \leftarrow (1 - \alpha) \cdot \sigma_{\text{run}}^2 + \alpha \cdot \sigma_{\text{batch}}^2 $$ 其中 $\alpha$ 是动量参数 `momentum`。 3. **评估阶段计算**: $$ y = \gamma \cdot \frac{x - \mu_{\text{run}}}{\sqrt{\sigma_{\text{run}}^2 + \epsilon}} + \beta $$ #### 最佳实践建议 1. **通道匹配**:确保前一层的输出通道数等于 `num_features` ```python conv = nn.Conv2d(3, 64, kernel_size=3) # 输出通道=64 bn = nn.BatchNorm2d(64) # 正确匹配 ``` 2. **小批量优化**:当 batch_size < 16 时,建议: ```python # 降低动量值 + 冻结BN层 bn = nn.BatchNorm2d(64, momentum=0.01) for param in bn.parameters(): param.requires_grad = False ``` 3. **参数访问**:查看学习参数 ```python print("缩放参数γ:", bn.weight) # 形状 [64] print("偏置参数β:", bn.bias) # 形状 [64] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值