卷积神经网络中的Conv层和BN层融合细节

本文阐述了批归一化(BN)层的工作原理及其在卷积神经网络中的作用,包括加速模型收敛、充当正则器及减少dropout需求。同时介绍了BN层如何与卷积层进行融合以提高模型推理效率。

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

BN层

批归一化层(Batch Normallization)是一种在卷积神经网络模型中大量使用,为了加速模型收敛的技术。为什么CNN 中引入 BN 层可以加速网络的收敛呢?因为将输入的样本数据或特征图,归一化后,改善了输入数据的分布,或者说减少了内部相关变量分布的偏移,模型在统一的分布中更能获取数据的特征。所以这里的归一化,其实是标准化(Standardization),即
x n e w = x − μ σ x_{new} = \frac{x - \mu}{\sigma} xnew=σxμ
一张图可以解释,改善输入数据的分布,可以更容易找到模型参数w和b,从而加速模型收敛

在这里插入图片描述

此外,BN 还充当正则器的作用,减少了 dropout 的需要。原文摘要如下

Batch Normalization allows us to use much higher learning rates and be less careful about initialization. It also acts as a regularizer, in some cases eliminating the need for Dropout.

算子融合

在训练时,卷积层和 BN 是两个模块,但是为什么训练时不能融合,而训练完成后,仅执行前向推理却可以融合?因为训练时是按批次输入数据的,BN 就是为了解决小批次输入数据的分布偏移而提出的,因此训练时需要BN层。而训练后的推理,是单样本输入,训练时 BN 的参数已经确定,这些参数相当于对前一层的特征图数据做一次线性变换,而卷积层也可以转化为对特征图的线性变换。因此这两个相邻的算子可以融合。

模型训练时通过移动平均的方法近似获得整个样本集的均值和方差
μ = μ n = α μ n − 1 + ( 1 − α ) ⋅ 1 N ∑ i n x i , n \mu = \mu_n = \alpha\mu_{n-1} + (1-\alpha)\cdot\frac{1}{N}\sum_{i}^nx_{i,n} μ=μn=αμn1+(1α)N1inxi,n
对于特征图 Fc,i,j 中第 c 个通道的 ( i , j ) 的值,写程向量和矩阵形式为
( F ~ 1 , i , j F ~ 2 , i , j ⋮ F ~ C , i , j ) = ( 1 σ 1 2 + ε 0 0 0 0 1 σ 2 2 + ε 0 0 0 ⋱ 0 0 0 0 0 1 σ n 2 + ε ) ( F 1 , i , j F 2 , i , j ⋮ F C , i , j ) + ( − μ 1 σ 1 2 + ε − μ 2 σ 2 2 + ε ⋮ − μ n σ n 2 + ε ) \left(\begin{array}{l} \tilde{F}_{1, i, j} \\ \tilde{F}_{2, i, j} \\ \vdots \\ \tilde{F}_{C, i, j} \end{array}\right)=\left(\begin{array}{cccc} \frac{1}{\sqrt{\sigma_{1}^{2}+\varepsilon}} & 0 & 0 & 0 \\ 0 & \frac{1}{\sqrt{\sigma_{2}^{2}+\varepsilon}} & 0 & 0 \\ 0 & \ddots & 0 & 0\\ 0 & 0 & 0 & \frac{1}{\sqrt{\sigma_{n}^{2}+\varepsilon}} \end{array}\right)\left(\begin{array}{l} F_{1, i, j} \\ F_{2, i, j} \\ \vdots \\ F_{C, i, j} \end{array}\right)+\left(\begin{array}{c} -\frac{\mu_{1}}{\sqrt{\sigma_{1}^{2}+\varepsilon}} \\ -\frac{\mu_{2}}{\sqrt{\sigma_{2}^{2}+\varepsilon}} \\ \vdots \\ -\frac{\mu_{n}}{\sqrt{\sigma_{n}^{2}+\varepsilon}} \end{array}\right) F~1,i,jF~2,i,jF~C,i,j = σ12+ε 10000σ22+ε 100000000σn2+ε 1 F1,i,jF2,i,jFC,i,j + σ12+ε μ1σ22+ε μ2σn2+ε μn
即 F = W * x + b,因此可将两者合并
F ~ i , j = W b n ( W c o n v F i , j + b c o n v ) + b b n \tilde{F}_{i, j} = W_{bn}(W_{conv}F_{i,j} + b_{conv}) + b_{bn} F~i,j=Wbn(WconvFi,j+bconv)+bbn
从而新的卷积层的 W 为 Wbn* Wconv ,新的 b 为 Wbn * Wconv + Wbn

具体实现可参考PyTorch的相关源码

参考文档

Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift

ML 入门:归一化、标准化和正则化

BN与Conv层的合并

模型推理加速技巧:融合BN和Conv层

### 将注意力机制融入卷积神经网络CNN) #### 方法概述 为了克服传统卷积神经网络(CNN)在处理复杂场景长距离依赖关系上的局限性,引入注意力机制可以显著提升模型性能。通过让模型聚焦于输入特征图中最相关的部分,从而提高对关键区域的关注度并减少无关信息的影响。 具体来说,在标准的 CNN 架构基础上加入空间注意模块(Spatial Attention Module),该模块能够自适应地调整不同位置的重要性权重;同时也可以采用通道注意机制(Channel-wise Attention Mechanism), 对各个滤波器响应进行加权组合来增强有用的特性表示[^1]。 #### 实现细节 以下是将这两种类型的注意力机制集成到现有 CNN 结构中的基本框架: - **空间注意力机制** 首先计算每个像素点在整个感受野内的相对贡献程度,并据此生成一个二维的空间分布映射矩阵 \(A_s\) 。接着将其与原始特征图相乘得到经过加权后的输出\(F'\): \[ F' = A_s \odot F \] 这里\(\odot\) 表示逐元素乘法操作符。对于任意给定的位置(i,j),其对应的注意力得分可通过如下方式获得: \[ a_{ij}=\frac{\exp (z_{i j})}{\sum_k \exp(z_k)} \] 其中\( z_{ij}\) 是由原特征图经变换后所得向量形式表达的结果之一。 ```python import torch.nn as nn class SpatialAttention(nn.Module): def __init__(self, kernel_size=7): super().__init__() self.conv = nn.Conv2d(2, 1, kernel_size, padding=kernel_size//2) def forward(self, x): avg_out = torch.mean(x, dim=1, keepdim=True) max_out, _ = torch.max(x, dim=1, keepdim=True) scale = torch.cat([avg_out, max_out], dim=1) fsa = self.conv(scale).sigmoid() return x * fsa.expand_as(x) ``` - **通道注意力机制** 类似地构建另一个分支用于捕捉跨间的信息交互模式。此过程涉及到两个全连接以及激活函数ReLU Sigmoid 的连续作用下完成从低维嵌入空间到高维重建的过程,最终形成一组新的权重系数应用于初始输入之上。 \[ W_c = f(W_2(f(W_1(F))) ) \] 此处f代表非线性转换操作,而Wc即为所求得的一系列比例因子集合。 ```python from functools import partial def conv_bn(in_channels, out_channels, stride=(1, 1)): return nn.Sequential( nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False), nn.BatchNorm2d(out_channels)) class ChannelAttention(nn.Module): def __init__(self, in_planes, ratio=16): super().__init__() self.avg_pool = nn.AdaptiveAvgPool2d(output_size=(1, 1)) self.max_pool = nn.AdaptiveMaxPool2d(output_size=(1, 1)) self.shared_mlp = nn.Sequential( conv_bn(in_planes, in_planes // ratio), nn.ReLU(), conv_bn(in_planes // ratio, in_planes)) self.sigmoid = nn.Sigmoid() def forward(self, inputs): avgout = self.shared_mlp(self.avg_pool(inputs)) maxout = self.shared_mlp(self.max_pool(inputs)) attention_weights = self.sigmoid(avgout + maxout) return inputs * attention_weights.expand_as(inputs) ``` 最后一步则是简单地串联起上述两部分组件构成完整的 attentive-CNN 模型架构。值得注意的是实际应用场景中可能还需要考虑更多因素比如正则化项设置、损失函数定义等以确保训练稳定性泛化能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值