Pytorch实战 |Y4 common.py文件解读

前沿

文件位置:./models/commonpy
该文件是实现YOLO算法中各个模块的地方,如果我们需要修改某一模块(例如C3),那么就需要修改这个文件中对应模块的的定义。由于YOLOv5版本问题,同一个模块可能会看到不同的版本,这都是正常的,以官网为主即可。

  • 本周任务:将yolov5s网络模型中的C3模块按照下图方式修改,并跑通yolov5

0、导入需要的包和基本配置

import ast
import contextlib
import json
import math                # 数学函数模块
import platform
import warnings
import zipfile
from collections import OrderedDict, namedtuple
from copy import copy      # 数据拷贝模块,分浅拷贝和深拷贝
from pathlib import Path   # Path将str转换为Path对象,使字符串路径易于操作的模块
from urllib.parse import urlparse

import cv2
import numpy as np          # numpy数组操作模块
import pandas as pd         # pandas数组操作模块
import requests             # Python的HTTP客户端库
import torch                # pytorch深度学习框架
import torch.nn as nn       # 专门为神经网络设计的模块化接口
from IPython.display import display
from PIL import Image       # 图像基础操作模块
from torch.cuda import amp  # 混合精度训练模块

from utils import TryExcept
from utils.dataloaders import exif_transpose, letterbox
from utils.general import (LOGGER, ROOT, Profile, check_requirements, check_suffix, check_version, colorstr,
                           increment_path, is_notebook, make_divisible, non_max_suppression, scale_boxes, xywh2xyxy,
                           xyxy2xywh, yaml_load)
from utils.plots import Annotator, colors, save_one_box
from utils.torch_utils import copy_attr, smart_inference_mode

1、基本组件

1.1 autopad

这个模块可以根据输入的卷积核计算卷积模块所需的pad值。将会用于下面会讲到的 Conv 函数和 Classify 函数中。

def autopad(k, p=None, d=1):  # kernel, padding, dilation
    # Pad to 'same' shape outputs
    if d > 1:
        k = d * (k - 1) + 1 if isinstance(k, int) else [d * (x - 1) + 1 for x in k]  # actual kernel-size
    if p is None:
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-pad
    return p

1.2 Conv

这个函数是整个网络中最基础的组件,由 卷积层 + BN层 + 激活函数组成,具体结构如下
在这里插入图片描述

class Conv(nn.Module):
    # Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)
    default_act = nn.SiLU()  # default activation

    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
        ''' 在Focus、Bottleneck、BottleneckCSP、C3、SPP、DWConv、TransformerBlock等模块中调用
        Standard convolution : conv + BN + act
        :params c1: 输入的channel值
        :params c2: 输出的channel值
        :params k: 卷积的kernel_size
        :params s: 卷积的stride
        :params p: 卷积的padding,默认是None,可以通过autopad自行计算需要的padding值
        :params g: 卷积的groups数,1就是普通的卷积,>1就是深度可分离卷积
        :params act: 激活函数类型,True就是SiLU()/Swish,False就是不使用激活函数,类型是nn.Module就使用传进来的激活函数类型
        '''
        super().__init__()
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
        self.bn = nn.BatchNorm2d(c2)
        self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()

    def forward(self, x):
        return self.act(self.bn(self.conv(x)))

    def forward_fuse(self, x):
        ''' 用于Model类的fuse函数
        融合 Conv + BN 加速推理,一般用于测试/验证阶段
        '''
        return self.act(self.conv(x))

这个类中还有一个特殊函数 forward_fuse ,这是一个前向加速推理模块,在前向传播过程中,通过融合 Conv + BN 层,达到加速推理的作用,一般用于测试或验证阶段

1.3 Focus

Focus模块是作者自己设计出来,为了减少浮点数和提高速度,而不是增加featuremap的,本质就是将图像进行切片,类似于下采样取值,将原图像的宽高信息切分,聚合到channel通道中。结构如下所示:
在这里插入图片描述

class Focus(nn.Module):
    # Focus wh information into c-space 把宽度w和高度h的信息整合到c空间中
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):  # ch_in, ch_out, kernel, stride, padding, groups
        ''' 在yolo.py的parse_model函数中被调用
        理论:从高分辨率图像中,周期性的抽出像素点重构到低分辨率图像中,即将图像相邻的四个位置进行堆叠,
        聚集wh维度信息到c通道中,提高每个点的感受野,并减少原始信息的丢失,该模块的设计主要是减少计算量加快速度。
        先做4个slice,再concat,最后在做Conv
        slice后 (b1,c1,w,h) -> 分成4个slice,每个slice(b,c1,w/2,h/2)
        concat(dim=1)后 4个slice(b,c1,w/2,h/2) -> (b,4c1,w/2,h/2)
        conv后 (b,4c1,w/2,h/2) -> (b,c2,w/2,h/2)
        :params c1: slice后的channel
        :params c2: Focus最终输出的channel
        :params k: 最后卷积的kernel
        :params s: 最后卷积的stride
        :params p: 最后卷积的padding
        :params g: 最后卷积的分组情况,=1普通卷积,>1深度可分离卷积
        :params act: bool激活函数类型,默认True[SiLU()/Swish],False[不用激活函数]
        '''        
        super().__init__()
        self.conv = Conv(c1 * 4, c2, k, s, p, g, act=act)
        # self.contract = Contract(gain=2)

    def forward(self, x):  # x(b,c,w,h) -> y(b,4c,w/2,h/2)
        ''' 有点像做了个下采样 '''
        return self.conv(torch.cat((x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]), 1))
        # return self.conv(self.contract(x))

1.4 Bottleneck

在这里插入图片描述

class Bottleneck(nn.Module):
    # Standard bottleneck  Conv + Conv + shortcut
    def __init__(self, c1, c2, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, shortcut, groups, expansion
        ''' 在BottleneckCSP和yolo.py的parse_model函数中被调用
        :params c1: 第一个卷积的输入channel
        :params c2: 第二个卷积的输入channel
        :params shortcut: bool值,是否有shortcut连接,默认True
        :params g: 卷积分组的个数,=1普通卷积,>1深度可分离卷积
        :params e: expansion ratio,e*c
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值