目录
训练配置
网络的搭建过程
数据的处理
mosaic数据增强方法
模型的前向处理过程
在主项目文件夹下创建 datasets文件夹,并配置coco数据集
# ├── yolov5
# └── datasets
# └── coco ← downloads here (20.1 GB)
标签数据可以直接运行train.py,自动下载并解压,
python train.py --data coco.yaml --epochs 300 --weights '' --cfg yolov5n.yaml --batch-size 32
cp ./Arial.ttf /root/.config/Ultralytics/
如果github连不上,则可以挂去下载
https://github.com/ultralytics/yolov5/releases/download/v1.0/coco2017labels.zip
1. model = Model(cfg, ch=3, nc=nc, anchors=hyp.get('anchors')).to(device) # train.py--137
2. self.model, self.save = parse_model(deepcopy(self.yaml), ch=[ch]) # yolo.py--186
3. m_ = nn.Sequential(*(m(*args) for _ in range(n))) if n > 1 else m(*args) # module yolo.py--347
4. layers.append(m_)
5. nn.Sequential(*layers)
网络的参数设定都在yaml中,d中的内容
这里涉及 eval() 函数的使用,参考这里
for i, (f, n, m, args) in enumerate(d['backbone'] + d['head']):
# 其中的参数值举例
i : 1
f : -1
n : 1
m : 'Conv'
args : [64, 6, 2, 2]
它们都来自yaml文件中的定义。
# m.anchors
tensor([[[ 10., 13.],
[ 16., 30.],
[ 33., 23.]],
[[ 30., 61.],
[ 62., 45.],
[ 59., 119.]],
[[116., 90.],
[156., 198.],
[373., 326.]]])
优化器的搭建
optimizer = smart_optimizer(model, opt.optimizer, hyp['lr0'], hyp['momentum'], hyp['weight_decay']) # train.py--162
EMA更新参数机制
ema = ModelEMA(model) if RANK in {-1, 0} else None # train.py--172
cache中的内容
1、 设定shape,保证最大的一边不超过640, dataloader.py -- 560始
2、 保证图片的每一边都是步长的倍数
前面都是一些设置,主要的导入数据过程在 dataloaders.py 的 __getitem__中。
随即采用的,并不是都采用
mosaic = self.mosaic and random.random() < hyp['mosaic'] # True, 随机采用
首先在范围内选取center,在随机选取额外的3张图片的索引并打乱顺序。
加载这些图片
fn中内容
采用cv2读入的数据
im = cv2.imread(f) # BGR
标签的对齐,主要如下
padw = x1a - x1b
padh = y1a - y1b
y[..., 0] = w * (x[..., 0] - x[..., 2] / 2) + padw
通过计算相对坐标,将得到的偏移量加到原有的,从而统一到增强后的坐标系中。相对坐标的应用系分析详见这里
# x 中的值,归一化了
[[ 0.50074 0.60091 0.99852 0.77579], [ 0.47636 0.63401 0.78222 0.61711]]
# y中的值, 反归一化了
[[ 358.95 601.53 998 931.24], [ 412.56 649.32 913.18 911.59]]
后续还在此基础上进行了一些数据增强操作,包括旋转,尺度变化等等
因此,标签会根据数据增强后的再次进行对齐。最终的标签会再度除以宽和高进行归一化
labels[:, 1:5] = xyxy2xywhn(labels[:, 1:5], w=img.shape[1], h=img.shape[0], clip=True, eps=1E-3) # dataloader.py--698
按每个类别的数量计算了权重
最终 , train_loader的返回值为
torch.from_numpy(img), labels_out, self.im_files[index], shapes
其中labels_out 是个6维的数据,
labels_out[2:6] 为归一化的 xywh bounding box 的标签
labels_out[1] 为 类别标签
labels_out[0] 为 0
前向处理过程中 Detect头直接输出,因为 self.training is False。整个模型端到端
pred中的内容举例
ai 内容
targets内容
第一维变成batch size 的arrange了。
注意,在
t = targets * gain
时将标签的尺度转到了输出的特征图的尺度上。
yolov5锚框的设置,autoanchor 以及这里
这里结合代码进行了说明
yolov5锚框在每个尺度的特征图上的点设置了偏移量,并且每个点随机的采取周围的上下左右3个点作为anchor的中心点。
置信度的设定,采用的是预测的box与真实值box的CIoU,
tobj = torch.zeros(pi.shape[:4], dtype=pi.dtype, device=self.device) # 初始值为0
iou = bbox_iou(pbox, tbox[i], CIoU=True).squeeze() # iou(prediction, target)
tobj[b, a, gj, gi] = iou # iou ratio 正样本标签采用CIoU
回归损失,采用的是CIoU损失,
置信度损失和分类损失,均采用Focal loss。