一、前言
本周任务:将YOLOv5s网络模型中的C3模块按照下图方式修改形成C2模块,并将C2模块插入第2层与第3层之间,且跑通YOLOv5s。
任务提示:
提示1:需要修改common.yaml、yolo.py、yolov5s.yaml文件。
提示2:C2模块与C3模块是非常相似的两个模块,我们要插入C2到模型当中,只需要找到哪里有C3模块,然后在其附近加上C2即可。
二、导入需要的包和基本配置
"""
YOLO-specific modules
Usage:
$ python models/yolo.py --cfg yolov5s.yaml
"""
import argparse
import contextlib
import os
import platform
import sys
from copy import deepcopy
from pathlib import Path
FILE = Path(__file__).resolve()
ROOT = FILE.parents[1]
if str(ROOT) not in sys.path:
sys.path.append(str(ROOT))
if platform.system() != 'Windows':
ROOT = Path(os.path.relpath(ROOT, Path.cwd()))
from models.common import *
from models.experimental import *
from utils.autoanchor import check_anchor_order
from utils.general import LOGGER, check_version, check_yaml, make_divisible, print_args
from utils.plots import feature_visualization
from utils.torch_utils import (fuse_conv_and_bn, initialize_weights, model_info, profile, scale_img, select_device,
time_sync)
try:
import thop
except ImportError:
thop = None
三、 parse_model函数
这个函数用于将模型的模块拼接起来,搭建完成的网络模型。后续如果需要动模型框架的话,你需要对这个函数做相应的改动。
def parse_model(d, ch):
LOGGER.info(f"\n{
'':>3}{
'from':>18}{
'n':>3}{
'params':>10} {
'module':<40}{
'arguments':<30}")
anchors, nc, gd, gw, act = d['anchors'], d['nc'], d['depth_multiple'], d['width_multiple'], d.get('activation')
if act:
Conv.default_act = eval(act)
LOGGER.info(f"{
colorstr('activation:')} {
act}")
na = (len(anchors[0]) // 2) if isinstance(anchors, list) else anchors
no = na * (nc + 5)
layers, save, c2 = [], [], ch[-1]
for i, (f, n, m, args) in enumerate(d['backbone'] + d['head']):
m = eval(m) if isinstance(m, str) else m
for j, a in enumerate(args):
with contextlib.suppress(NameError):
args[j] = eval(a) if isinstance(a, str) else a
n = n_ = max(round(n * gd), 1) if n > 1 else n
if m in {
Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv,
BottleneckCSP, C3, C3TR, C3SPP, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x}:
c1, c2 = ch[f], args[0]
if c2 != no:
c2 = make_divisible(c2 * gw, 8)
args = [c1, c2, *args[1:]]
if m in {
BottleneckCSP, C3, C3TR, C3Ghost, C3x}:
args.insert(2, n)
n = 1
elif m is nn.BatchNorm2d:
args = [ch[f]]
elif m is Concat:
c2 = sum(ch[x] for x in f)
elif m in {
Detect, Segment}:
args.append([ch[x] for x in f])
if isinstance(args[1], int):
args[1] = [list(range(args[1] * 2))] * len(f)
if m is Segment:
args[3] = make_divisible(args[3] * gw, 8)
elif m is Contract:
c2 = ch[f] * args[0] ** 2
elif m is Expand:
c2 = ch[f] // args[0] ** 2
else:
c2 = ch[f]
m_ = nn.Sequential(*(m(*args) for _ in range(n))) if n > 1 else m(*args)
t = str(m)[8:-2].replace('__main__.', '')
np = sum(x.numel() for x in m_.parameters())
m_.i, m_.f, m_.type, m_.np = i, f, t, np
LOGGER.info(f'{
i:>3}{
str(f):>18}{
n_:>3}{
np:10.0f} {
t:<40}{
str(args):<30}')
save.extend(x % i for x in ([f] if isinstance(f