配置文件解析
一些可读的玩意儿_yolov5_segment
data/hyps
hyp超参数配置文件
lr0 : 0.01 #初始学习率 (SGD=1E-2, Adam=1E-3)
lrf : 0.01 #最终的 OneCycleLR 学习率 (lr0 * lrf)
momentum: 0.937 # SGD 动量/Adam beta1
weight_decay : 0.0005 #优化器权重衰减 5e-4
warmup_epochs : 3.0 # warmup epochs (fractions ok)
warmup_momentum : 0.8 #预热初始动量
warmup_bias_lr : 0.1 #预热初始偏差 lr
box : 0.05 # box loss gain
cls : 0.5 # cls 损失增益
cls_pw : 1.0 # cls BCELoss positive_weight
obj : 1.0 # obj loss gain(按像素缩放)
obj_pw : 1.0 # obj BCELoss positive_weight
iou_t : 0.20 # IoU训练阈值
anchor_t : 4.0 #锚倍阈值
#anchors:3 # 每个输出层的锚点(0 忽略)
fl_gamma : 0.0 #focal loss gamma (efficientDet default gamma=1.5)
hsv_h : 0.015 #图像 HSV-Hue 增强(分数)
hsv_s : 0.7 #图像 HSV-Saturation 增强(分数)
hsv_v : 0.4 #图像 HSV 值增强(分数)
degree : 0.0 #图像旋转 (+/- deg)
translate : 0.1 #图像翻译(+/- 分数)
scale : 0.5 #图像比例(+/- 增益)
shear:0.0 #图像剪切(+/- 度)
perspective : 0.0 #图像透视(+/- 分数),范围 0-0.001
flipud : 0.0 #图像上下翻转(概率)
fliplr : 0.5 #图像左右翻转(概率)
mosaic: 1.0 #图像马赛克(概率)
mixup : 0.0 #图像混合(概率)
copy_paste : 0.0 #段复制粘贴(概率)
- yolov5/data/hyps/hyp.scratch-low.yaml(YOLOv5 COCO训练从头优化,数据增强低)
- yolov5/data/hyps/hyp.scratch-mdeia.yaml(数据增强中)
- yolov5/data/hyps/hyp.scratch-high.yaml(数据增强高)
默认使用的都是low,倒数第三行mosaic值设置为0即可关闭mosaic数据增强
train.py
所在行数 | 参数 | 含义 | 解释 |
---|---|---|---|
465 | weights | 模型的权重 | .pt文件,存储了模型的所有参数 |
466 | cfg | config,模型配置文件 | .yaml文件,存储模型各层的形状和类别 |
473 | resume | 中断后继续 | 中断后继续 |
481 | image-weights | image-weights | 设为True时,计算图像采集的权重,若图像权重越大,那么该图像被采样的概率也越大 |
483 | multi-scale | 是否多尺度训练图片 | 设为True时,将图片放缩成多个尺寸,能够得到不同尺度的特征信息,但速度慢。 |
484 | single-cls | single class,单类别训练 | 设为True时,把多类别标签都视为同一种标签进行训练。 |
485 | optimizer | 优化器 | 默认SGD,有3种可选择’SGD’, ‘Adam’, ‘AdamW’ |
491 | quad | 是否使用四元数据加载器 | 一个实验性功能参数,允许小尺寸图片训练时获得高尺寸训练的优势 |
493 | label-smoothing | 标签平滑 | label-smoothing |
495 | freeze | 冻结 | 冻结网络的指定层,冻结的层的权重在训练过程中不会改变 |
497 | seed | seed | 固定训练的随机性,玄学1017 |
魔改
使用Shufflenetv2 ,论文:https://arxiv.org/abs/1807.11164
- common.py中添加以下代码:
# ---------------------------- ShuffleBlock start ----------------------------
---
# 通道重排,跨group信息交流
def channel_shuffle(x, groups):
batchsize, num_channels, height, width = x.data.size()
channels_per_group = num_channels // groups
# reshape
x = x.view(batchsize, groups,
channels_per_group, height, width)
x = torch.transpose(x, 1, 2).contiguous()
# flatten
x = x.view(batchsize, -1, height, width)
return x
class conv_bn_relu_maxpool(nn.Module):
def __init__(self, c1, c2): # ch_in, ch_out
super(conv_bn_relu_maxpool, self).__init__()
self.conv = nn.Sequential(
nn.Conv2d(c1, c2, kernel_size=3, stride=2, padding=1, bias=False),
nn.BatchNorm2d(c2),
nn.ReLU(inplace=True),
)
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
def forward(self, x):
return self.maxpool(self.conv(x))
class Shuffle_Block(nn.Module):
def __init__(self, inp, oup, stride):
super(Shuffle_Block, self).__init__()
if not (1 <= stride <= 3):
raise ValueError('illegal stride value')
self.stride = stride
branch_features = oup // 2
assert (self.stride != 1) or (inp == branch_features << 1)
if self.stride > 1:
self.branch1 = nn.Sequential(
self.depthwise_conv(inp, inp, kernel_size=3, stride=self.stride, padding=1),
nn.BatchNorm2d(inp),
nn.Conv2d(inp, branch_features, kernel_size=1, stride=1, padding=0, bias=False),
nn.BatchNorm2d(branch_features),
nn.ReLU(inplace=True),
)
self.branch2 = nn.Sequential(
nn.Conv2d(inp if (self.stride > 1) else branch_features,
branch_features, kernel_size=1, stride=1, padding=0, bias=False),
nn.BatchNorm2d(branch_features),
nn.ReLU(inplace=True),
self.depthwise_conv(branch_features, branch_features, kernel_size=3, stride=self.stride, padding=1),
nn.BatchNorm2d(branch_features),
nn.Conv2d(branch_features, branch_features, kernel_size=1, stride=1, padding=0, bias=False),
nn.BatchNorm2d(branch_features),
nn.ReLU(inplace=True),
)
@staticmethod
def depthwise_conv(i, o, kernel_size, stride=1, padding=0, bias=False):
return nn.Conv2d(i, o, kernel_size, stride, padding, bias=bias, groups=i)
def forward(self, x):
if self.stride == 1:
x1, x2 = x.chunk(2, dim=1) # 按照维度1进行split
out = torch.cat((x1, self.branch2(x2)), dim=1)
else:
out = torch.cat((self.branch1(x), self.branch2(x)), dim=1)
out = channel_shuffle(out, 2)
return out
# ---------------------------- ShuffleBlock end --------------------------------
- yolo.py中注册
conv_bn_relu_maxpool, Shuffle_Block
两个模块 - 新建yolov5s-shufflenetv2-seg.yaml文件为:
# YOLOv5 🚀 by Ultralytics, AGPL-3.0 license
# Parameters
nc: 80 # number of classes
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
anchors:
- [10,13, 16,30, 33,23] # P3/8
- [30,61, 62,45, 59,119] # P4/16
- [116,90, 156,198, 373,326] # P5/32
# YOLOv5 v6.0 backbone
backbone:
# [from, number, module, args]
# Shuffle_Block: [out, stride]
[[ -1, 1, conv_bn_relu_maxpool, [ 32 ] ], # 0-P2/4
[ -1, 1, Shuffle_Block, [ 128, 2 ] ], # 1-P3/8
[ -1, 3, Shuffle_Block, [ 128, 1 ] ], # 2
[ -1, 1, Shuffle_Block, [ 256, 2 ] ], # 3-P4/16
[ -1, 7, Shuffle_Block, [ 256, 1 ] ], # 4
[ -1, 1, Shuffle_Block, [ 512, 2 ] ], # 5-P5/32
[ -1, 3, Shuffle_Block, [ 512, 1 ] ], # 6
]
# YOLOv5 v6.0 head
head:
[[-1, 1, Conv, [256, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 4], 1, Concat, [1]], # cat backbone P4
[-1, 1, C3, [256, False]], # 10
[-1, 1, Conv, [128, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 2], 1, Concat, [1]], # cat backbone P3
[-1, 1, C3, [128, False]], # 14 (P3/8-small)
[-1, 1, Conv, [128, 3, 2]],
[[-1, 11], 1, Concat, [1]], # cat head P4
[-1, 1, C3, [256, False]], # 17 (P4/16-medium)
[-1, 1, Conv, [256, 3, 2]],
[[-1, 7], 1, Concat, [1]], # cat head P5
[-1, 1, C3, [512, False]], # 20 (P5/32-large)
[[14, 17, 20], 1, Segment, [nc, anchors, 32, 256]], # Detect(P3, P4, P5)
]
激活函数
- 在common.py中导入需要更换的激活函数 比如Hard-Swish,则 from utils.activations import Hardswish
- 注释掉默认激活函数,更换为Hardswish即可
其他激活函数同理:
# self.act = nn.Identity() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
# self.act = nn.Tanh() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
# self.act = nn.Sigmoid() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
# self.act = nn.ReLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
# self.act = nn.LeakyReLU(0.1) if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
# self.act = nn.Hardswish() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
# self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
# self.act = Mish() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
# self.act = FReLU(c2) if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
# self.act = AconC(c2) if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
# self.act = MetaAconC(c2) if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
# self.act = SiLU_beta(c2) if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
# self.act = FReLU_noBN_biasFalse(c2) if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
# self.act = FReLU_noBN_biasTrue(c2) if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
参考链接: