YOLOv5 网络组件(含common.py文件注解)(六)

课程链接

目录

Conv  Focus  BCSPn  SPP  Concat

common.py代码解析

Conv

Conv是yolov5中的最核心模块,代码如下:

# 为same卷积或same池化自动扩充,为了让卷积或池化以后的特征图的大小不变,在输入的特征图上要做0填充,填充多少通过以下函数进行计算
def autopad(k, p=None):  # kernel, padding
    # Pad to 'same'
    if p is None:
        # k是int类型则整除2;或若干的整数值则循环整除
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-pad
    return p

class Conv(nn.Module):
    # Standard convolution  标准卷积:conv+BN+hardswish
    # 初始化构造函数 c1为输入channel的值, c2为输出channel的值, kernel, stride, padding, groups
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):
        super(Conv, self).__init__()
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
        self.bn = nn.BatchNorm2d(c2)
        self.act = nn.Hardswish() if act else nn.Identity()  # 若act=false, 则不使用激活函数

    def forward(self, x):  # 网络的执行顺序是根据forward函数来决定的
        return self.act(self.bn(self.conv(x)))  # conv->bn->hardswish

    def fuseforward(self, x):  # 没有BN,只有卷积和激活
        return self.act(self.conv(x))

当不指定 p 时,Conv2d 的 pad 值是让 k//2 (除法向下取整) 计算得到的 (aotopad函数) 。

有以下两种情况:

  • 当s=1时候,显然经过 Conv2d 后特征的大小不变;
  • 当s=2时候,那么经过 Conv2d 后特征的大小减半;

Conv:Conv2d + BatchNorm2d + Hardswish,bias默认为False,即不使用bias偏置,Conv2d和BatchNorm2d结合使用以后,会进行融合操作,融合时卷积的base值会被消掉。

Conv模块

代码中使用 fuse_conv_and_bn 函数合并了 Conv2d 层和 BatchNorm2d 层。在模型训练完成后,代码在推理阶段和导出模型时,将卷积层和BN层进行融合。为了可视化,可以关闭 models / yolo.py -- fuse()

def fuse(self):  # fuse model Conv2d() + BatchNorm2d() layers
    print('Fusing layers... ')
    # for m in self.model.modules():
    #     if type(m) is Conv and hasattr(m, 'bn'):
    #         m._non_persistent_buffers_set = set()  # pytorch 1.6.0 compatability
    #         m.conv = fuse_conv_and_bn(m.conv, m.bn)  # update conv
    #         delattr(m, 'bn')  # remove batchnorm
    #         m.forward = m.fuseforward  # update forward
    # self.info()
    return self

当关闭 fuse() 后,也使用 Netron 对 yolov5s.torchscript.pt 可视化,看到 BN。

对于任何用到shape、size返回值的参数时,例如:tensor.view(tensor.size(0), -1)这类操作,避免直接使用tensor.size的返回值,而是加上int转换,tensor.view(int(tensor.size(0)), -1)。为了避免pytorch 导出 onnx 时候,对size 进行跟踪,跟踪时候会生成gather、shape的节点。

修改代码:models/yolo.py

# bs, _, ny, nx = x[i].shape  # x(bs,255,20,20) to x(bs,3,20,20,85)
bs, _, ny, nx = map(int, x[i].shape)

Focus

Focus示意图

Netron可视化

若要图显示输出的尺寸,可以修改 export.py 代码,并重新导出onnx

# Checks
onnx.save(shape_inference.infer_shapes(onnx_model), f)

切片

x[..., ::2, ::2],           红色图         w, h 从0开始,每隔一个切一个

x[..., 1::2, ::2],         黄色图         w 从1开始, h 从0开始,每隔一个切一个

x[..., ::2, 1::2],         绿色图         w 从0开始, h 从1开始,每隔一个切一个

x[..., 1::2, 1::2]        蓝色图         w, h 从1开始,每隔一个切一个

Co

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值