yolov8中卷积层和正则化层融合过程,代码解读

本文对Conv或DWConv和BN层融合进行介绍,以代码为主,配合示例,进行详细解读。在验证或预测时,前期是加载模型和一些配置信息,如图像路径和参数等,此部分不做过多介绍。

在进行层融合时,先依次判断加载的模块中,是否同时具有Conv或DWConv和BN层,如果同时具备,则进行融合。如下代码

        LOGGER.info('Fusing layers... ')
        for m in self.model.modules():
            if isinstance(m, (Conv, DWConv)) and hasattr(m, 'bn'):
                m.conv = fuse_conv_and_bn(m.conv, m.bn)  # update conv
                delattr(m, 'bn')  # remove batchnorm
                m.forward = m.forward_fuse  # update forward
        self.info()
        return self

在这里插入图片描述
进入模块融合卷积和bn,代码如下

def fuse_conv_and_bn(conv, bn):
    # Fuse Conv2d() and BatchNorm2d() layers https://tehnokv.com/posts/fusing-batchnorm-and-conv/
    fusedconv = nn.Conv2d(conv.in_channels,
                          conv.out_channels,
                          kernel_size=conv.kernel_size,
                          stride=conv.stride,
                          padding=conv.padding,
                          dilation=conv.dilation,
                          groups=conv.groups,
                          bias=True).requires_grad_(False).to(conv.weight.device)

    # Prepare filters
    w_conv = conv.weight.clone().view(conv.out_channels, -1)
    w_bn = torch.diag(bn.weight.div(torch.sqrt(bn.eps + bn.running_var)))
    fusedconv.weight.copy_(torch.mm(w_bn, w_conv).view(fusedconv.weight.shape))

    # Prepare spatial bias
    b_conv = torch.zeros(conv.weight.size(0), device=conv.weight.device) if conv.bias is None else conv.bias
    b_bn = bn.bias - bn.weight.mul(bn.running_mean).div(torch.sqrt(bn.running_var + bn.eps))
    fusedconv.bias.copy_(torch.mm(w_bn, b_conv.reshape(-1, 1)).reshape(-1) + b_bn)

    return fusedconv

先构建一个卷积层 fusedconv,
然后把conv的输入、输出、和大小等信息赋值给fuseconv。
重构conv权重的的尺寸,如conv.weight为(32,48,1,1),conv.out_channels为32,则w_conv则为(32,48)。
进行正则化参数的计算,进行协方差、偏执因子等的融合。
进行wbn和convbn两个矩阵进行相乘,然后重构矩阵形状。
到此得到融合后的权重fusedconv.weight,形状为(32,48,1,1)
在判断卷积层中是否有偏执,如果有,则b-conv=conv.bias,否则根据输出的大小,生成一系列0。
在这里插入图片描述
进行卷积的偏执和正则化的偏执进行结合。生成的结果形状依旧为(32,),如上图所示。
把结合后的偏执赋值到fusedconv,得到fusedconv.bias。
到此处,新建立的fusedconv层需要的权重更新完毕,输出fusedconv。
用fusedconv替换模块m中的卷积层m.conv = fuse_conv_and_bn(m.conv, m.bn) # update conv
然后删除模块m中的bn层,delattr(m, 'bn') # remove batchnorm,至此,融合的层已经完成替换。
最后,更新前项传播 m.forward = m.forward_fuse # update forward self.info()

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木彳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值