批归一化

数据的规范化也即(x−mean(x)/var(x))(x-mean(x)/var(x))(x−mean(x)/var(x)) 可以将数据的不同特征规范到均值为0,方差相同的标准正态分布,这就可以避免大数造成得数据溢出。可以使网络以更高得学习率更快得收敛。
如果仅仅对输入的图片进行归一化,后面其余网络层的输出不进行相关操作,那么随着网络深度得增加,数据得分布会逐渐偏离标准正态分布,由于梯度得反向传播是不同层得梯度不断相乘得结果,数据过小或过大容易造成梯度消失或梯度爆炸。
为了解决上述问题,有人提出了对网络层的中间输出进行规范化得方法,也就是批规范化(Batch Normalization),对某个网络层的批规范化,通常是在加权和与激活函数运算之间进行的。也就是:
sigmoid(BN(xW+b))=sigmoid(BN(z))sigmoid(BN(xW+b))=sigmoid(BN(z))sigmoid(BN(xW+b))=sigmoid(BN(z)) 但是如果将zzz 规范到N(0,1)N(0,1)N(0,1) 的标准正态分布,那么无论前面的网络如何变化,经过这个这个层后都将服从标准正态分布,批规范化引入了可学习的参数β、γ\beta、 \gammaβ、γ ,将规范到N(0,1)N(0,1)N(0,1) 的标准正态分布变换到N(β,γ)N(\beta,\gamma)N(β,γ) 由于β、γ\beta、 \gammaβ、γ 是可学习的,所以就避免了模型能力降低的问题:
x^i=γxi−μσ2+ϵ+β\hat{x}_{i}=\gamma \frac{x_{i}-\mu}{\sqrt{\sigma^{2}+\epsilon}}+\betax^i​=γσ2+ϵ​xi​−μ​+β其中μ=1n∑xiσ2=1n∑(xi−μ)2\begin{array}{c} \mu=\frac{1}{n} \sum x_{i} \\ \sigma^{2}=\frac{1}{n} \sum\left(x_{i}-\mu\right)^{2} \end{array}μ=n1​∑xi​σ2=n1​∑(xi​−μ)2​

BN和卷积层融合

在图像处理过程中,BN经常用于卷积之后,可以考虑将两个融合在在一起 ,简单点就是将是合二为一(融合层通常用测试阶段)。那么合二为一新的网络层的网络权重和偏置该怎么初始化呢?根据卷积层和BN层的相关参数进行计算得到新的权重和偏置,公式入下:yi=xi−μσ2+ϵ⋅γ+β=w∗xi+b−μσ2+ϵ⋅γ+β=w∗γσ2+ϵ⋅x+(b−μσ2+ϵ⋅γ+β)(1)\begin{aligned} y_{i} &=\frac{x_{i}-\mu}{\sqrt{\sigma^{2}+\epsilon}} \cdot \gamma+\beta \\ &=\frac{w * x_{i}+b-\mu}{\sqrt{\sigma^{2}+\epsilon}} \cdot \gamma+\beta \\ &=\frac{w * \gamma}{\sqrt{\sigma^{2}+\epsilon}} \cdot x+\left(\frac{b-\mu}{\sqrt{\sigma^{2}+\epsilon}} \cdot \gamma+\beta\right) \end{aligned} (1)yi​​=σ2+ϵ​xi​−μ​⋅γ+β=σ2+ϵ​w∗xi​+b−μ​⋅γ+β=σ2+ϵ​w∗γ​⋅x+(σ2+ϵ​b−μ​⋅γ+β)​(1)
简化公式结构为yi=wnewx+bnewy_{i} = w_{new}x+b_{new}yi​=wnew​x+bnew​.
wnew =w∗γσ2+ϵbnew =(b−μσ2+ϵ⋅γ+β)(2)\begin{array}{l} w_{\text {new }}=\frac{w * \gamma}{\sqrt{\sigma^{2}+\epsilon}} \\ b_{\text {new }}=\left(\frac{b-\mu}{\sqrt{\sigma^{2}+\epsilon}} \cdot \gamma+\beta\right) \end{array} (2)wnew ​=σ2+ϵ​w∗γ​bnew ​=(σ2+ϵ​b−μ​⋅γ+β)​(2) 其中w,bw,bw,b为卷积层的权重和偏置,γ、β,μ、σ2\gamma、\beta,\mu、\sigma^{2}γ、β,μ、σ2为BNBNBN层的权重、偏置、mean、varmean、varmean、var对应的参数

pytorch代码

pytorch 中 Conv2 和 BN 层中参数的的具体意义

import torch
def fuse_conv_and_bn(conv, bn):# 初始化fusedconv = torch.nn.Conv2d(conv.in_channels,conv.out_channels,kernel_size=conv.kernel_size,stride=conv.stride,padding=conv.padding,bias=True)w_conv = conv.weight.clone().view(conv.out_channels, -1)w_bn = torch.diag(bn.weight.div(torch.sqrt(bn.eps+bn.running_var)))# 融合层的权重初始化(W_bn*w_conv(卷积的权重))fusedconv.weight.copy_( torch.mm(w_bn, w_conv).view(fusedconv.weight.size()) )if conv.bias is not None:b_conv = conv.biaselse:b_conv = torch.zeros( conv.weight.size(0) )b_bn = bn.bias - bn.weight.mul(bn.running_mean).div(torch.sqrt(bn.running_var + bn.eps))# 融合层偏差的设置fusedconv.bias.copy_( torch.matmul(w_bn, b_conv) + b_bn )return fusedconv

那么,融合层计算出来的结果和分层计算出来的结果有多大差距呢??从下面代码可以看到用人家预训练好的相关参数进行融合,融合层和分层计算得出的结果所差无几嘛。

import torchvision
torch.set_grad_enabled(False)
x = torch.randn(32, 3, 256, 256)   # batch,channel,w,h
rn18 = torchvision.models.resnet18(pretrained=True)
rn18.eval()
net = torch.nn.Sequential(rn18.conv1,rn18.bn1
)
y1 = net.forward(x)
fusedconv = fuse_conv_and_bn(net[0], net[1])
y2 = fusedconv.forward(x)
# torch.norm()是求范数,没有指定维度则是对所有元素求二范数
d = (y1 - y2).norm().div(y1.norm()).item()
print("error: %.8f" % d)>>>error: 0.00000022

那么问题又出来了,既然所查无几,为什么要费劲的去融合他呢,那我们再想想深度网络运行时间是不是我们担心的问题呢,走起,去验证一下时间上有无改进吧。
这里就假设一次输入32张图片,测试了300次。可以看出,在速度提升上还是蛮大的。

def cal_time(fun):def inner(*args,**kwargs):t1 = time.time()fun(*args,**kwargs)t2 = time.time()print(f"运行时间:{t2-t1}")    return inner@cal_time
def main(net,x):for i in tqdm(range(300)): # 假设一次输入32张图片,测试了300次。y = net.forward(x)main(net,x)
main(fusedconv,x)>>>93.39383339
>>>69.93862175

那么事在训练的时候融合还是测试的时候融合呢,那肯定是用在测试阶段,前面说过融合层的权重和偏置要根据训练好的卷积、BN层的参数确定。这样测试阶段使用融合后的网络进行推理就可以加快推理速度。对于有些实时检测场所,速度越快岂不是更好。
参考链接: Fusing batch normalization and convolution in runtime
小白一枚,如果有问题,希望大家提出来。谢谢。

pytorch实现卷积层和BN层融合相关推荐

  1. 目标检测 YOLOv5 - 卷积层和BN层的融合

    目标检测 YOLOv5 - 卷积层和BN层的融合 即Conv2d和 BatchNorm2d融合 flyfish 为了减少模型推理时间,YOLOv5源码中attempt_load已经包括两层的合并,主要 ...

  2. 卷积层与BN层的融合方式

    BN(批归一化)层常用于在卷积层之后,对feature maps进行归一化,从而加速网络学习,也具有一定的正则化效果.训练时,BN需要学习一个minibatch数据的均值.方差,然后利用这些信息进行归 ...

  3. 【PyTorch】eval() ==>主要是针对某些在train和predict两个阶段会有不同参数的层,比如Dropout层和BN层

    model的eval方法主要是针对某些在train和predict两个阶段会有不同参数的层.比如Dropout层和BN层 torch为了方便大家,设计这个eval方法就是让我们可以不用手动去针对这些层 ...

  4. 详细解释卷积神经网络CNN中卷积层以及BN层的参数

    问题的提出 在做关于python的卷积神经网络的项目中,发现了一个卷积层加一个BN层竟然一共有6个参数.百思不得其解. if batch_norm:layers += [nn.Conv2d(in_ch ...

  5. Pytorch中BN层入门思想及实现

    批归一化层-BN层(Batch Normalization) 作用及影响: 直接作用:对输入BN层的张量进行数值归一化,使其成为均值为零,方差为一的张量. 带来影响: 1.使得网络更加稳定,结果不容易 ...

  6. PyTorch中BN层中新加的 num_batches_tracked 有什么用?

    从PyTorch 0.4.1开始, BN层中新增加了一个参数 track_running_stats, BatchNorm2d(128, eps=1e-05, momentum=0.1, affine ...

  7. merge卷积和bn层的原理

    <merge卷积和bn层的原理>   这是一个在移动端非常实用的技巧,而且丝毫不会影响模型的精度,而提高模型的运算速度,就是把BN层离线的时候做好,放在权重值和偏执项中就可以了. Key ...

  8. 模型压缩(一)通道剪枝-BN层

    论文:https://arxiv.org/pdf/1708.06519.pdf BN层中缩放因子γ与卷积层中的每个通道关联起来.在训练过程中对这些比例因子进行稀疏正则化,以自动识别不重要的通道.缩放因 ...

  9. 深度学习笔记(一):卷积层+池化层+激活函数+全连接层

    写在前面:大家好!我是[AI 菌],一枚爱弹吉他的程序员.我热爱AI.热爱分享.热爱开源! 这博客是我对学习的一点总结与记录.如果您也对 深度学习.机器视觉.算法.Python.C++ 感兴趣,可以关 ...

最新文章

  1. Qt显示中文ansi字符串乱码问题解决方案
  2. 开源使得所有的软件卖成白菜价,但终将普惠世界!
  3. qt creator无法删除文件怎么办?(需要在cmakelists文件里配置)
  4. IntelliTest实战直通车(上集)
  5. cryptojs支持rsa加密_新特性解读 | 从 wireshark 看 MySQL 8.0 加密连接
  6. 实时获取滚动条的高度_适用于星上快速处理的雷达高度计有效波高反演技术
  7. DevExpress之TreeList用法
  8. HTTP上传大文件的注意点
  9. Leetcode639. Decode Ways II
  10. 《生物信息学》——李霞;;生信概念
  11. 昨天,美团程序员的年终奖金可能没了!
  12. delphi 分析抓取html,delphi网页数据抓取
  13. 如何下载安装 Visual Studio2010
  14. PS CS6启动“不能打开暂存盘文件”的解决方法
  15. 摄像机镜头的计算方法
  16. WIN10安装Debugging Tools for Windows
  17. opencv-11-中值滤波的C++实现与自适应中值滤波
  18. 第一次学游泳技巧_第一次学习游泳
  19. [深度学习之CNN]CNN卷积神经网络LeNet-5
  20. 查找/下载文献的一些网址汇总

热门文章

  1. 召开云计算技术交流大会计算机,2017年职称计算机考试WPS_Office强化练习(1)
  2. Python版中秋佳节月饼抢购脚本
  3. flutter 层叠布局Stack、Positioned
  4. 3D引擎刷脸 金融级别安全 清微智能携手一诺KLOCK 为家多一重保障
  5. 叮~2021 CSDN年度报告已出炉;私信新增拉黑功能;创作助手支持错别字检测……【2021.12.29】
  6. 面试阿里不到半小时被破格录取,问我原因?还不是因为Redis
  7. 联合索引-最左匹配原则
  8. Oracle数据库开启归档日志和补充日志
  9. vue2实现数组push/pop/shift/unshift方法重写
  10. 华为机试真题 javascript和java 报文解压缩 100%通过