YOLOV8代码分析
- 1. YOLOV8相对于YOLOV5的改进
- 2 模型
-
-
- 2.1 模型主要模块
- 2.1.1 模型主要模块:
- 2.1.2 CBS、SPPF、Bottleneck、C2f、model
- 3 损失 ultralytics/models/yolo/detect/train.py
- 3.2.1 生成anchor_points
- 3.3.1 把targets[9,6]变为[bs,max_gt,1+4]
- 3.4 获取预测框 Pboxes
- 3.5 获取标签及正样本掩码
- 4.1 Cls loss
- 4.2 Bbox loss
1. YOLOV8相对于YOLOV5的改进
- 模型改进。
1.1 将YOLOv5中的C3模块替换为C2f模块。将Detect(耦合头 + Anchor-based)模块替换为Detect模块(解耦头 + Anchor-free + DFL)。YOLOv5的耦合头输出尺寸为[batch_size,h,w,(classes+4+1)*3]。classes(分类损失 BCE),4(框回归boxes reg)+ 1(置信度obj BCE)。
YOLOV8的解耦头输出尺寸为:Obj的BCE损失[batch_size,h,w,1],Boxes的CIOU[batch_ls类别损失[batch_size,h,w,cls]
- 正样本筛选。
用TaskAlignedAssigner分配策略。anchors中心点在GT(真实框)内部anchors为候选框。计算GT内部包含的每个anchors预测物体类别cls与CIOU的乘积作为分数对aanchors的分值,对分值排序,选取top_k个框作为正样本。
- 损失函数。类别损失(BCE)+位置损失(CIOU+ DFL)
2 模型
2.1 模型主要模块
2.1.1 模型主要模块:
- CBS:卷积层convolution、批标准化(BN)和SiLU激活函数。
- C2f:多梯度融合特征提取模块
- SPPF:快速金字塔池化特征层
- Detect:检测头(解耦头 + Anchor-free + Distribution)
2.1.2 CBS、SPPF、Bottleneck、C2f、model
1. CBS:
Conv + BN + SiLU
(k=3,s=2)
(k=3,s=1)
(k=1,s=1)
SiLU 的优点是无上界,有下界,平滑(可导)。SiLU函数随之自变量取值增大,因变量的取值先下降后上升。
SiLU的导函数呈现S形,当自变量接近正无穷大时,导数接近于比1大一点的恒定常数。
2. SPPF:
CBS(A) ——> MaxPool5(B) ——> MaxPool5(C) ——> MaxPool5(D) ——> Concat([A,B,C,D])——> CBS
SPPF相对于SPP效果一样,但是参数量大大降低。SPP是用5*5、9*9、13*13的卷积核对输入图提取特征,而
SPPF用5*5的卷积核对输入图提取特征后,用串联方式对每次卷机后的结果依次用5*5的卷积核提取特征,两个
5*5的卷积核得到的结果相当于一次9*9卷积核的结果,三个
5*5的卷积核得到的结果相当于一次13*13卷积核的结果,因此SPPF比SPP的参数量减少,速度更快。
3. Bottleneck:
input --> CBS(s=1,k=3) --> CBS(s=1,k=3)--> output -->output add input
4. C2f:
input --> CBS(s=1,k=1) --> split --> Bottleneck*n --> concat [Bottleneck*n ,split]--> CBS(s=1,k=1)
5.model
input (640,640)
↓
CBS(s=2,k=3) (320,320)
↓
CBS(s=2,k=3) (160,160)
↓
C2f(n=3) (160,160)
↓ { CBS(s=1,k=3,n=2) → Conv(k=1) →﹜
CBS(s=2,k=3) (80,80) → concat → C2f(n=3) → { ﹜→ concat
↓ ↑ ↓ { CBS(s=1,k=3,n=2) → Conv(k=1) →﹜
C2f(n=6) (80,80) upsample CBS(s=2,k=3)
↓ ↑ ↓
CBS(s=2,k=3) (40,40) C2f(n=3) → concat
↓ ↑ ↓ { CBS(s=1,k=3,n=2) → Conv(k=1) →﹜
C2f(n=6) (40,40) → concat C2f(n=3) → { ﹜→ concat
↓ ↑ | { CBS(s=1,k=3,n=2) → Conv(k=1) →﹜
CBS(s=2,k=3) (20,20) | ↓
↓ | CBS(s=2,k=3)
C2f(n=3) (20,20) | |
↓ | ↓ { CBS(s=1,k=3,n=2) → Conv(k=1) →﹜
SPPF(k=6) (20,20) → upsample → concat → C2f(n=3) → { ﹜→concat
{ CBS(s=1,k=3,n=2) → Conv(k=1) →﹜
3 损失 ultralytics/models/yolo/detect/train.py
from ultralytics.models.yolo.detect import DetectionTrainer
args = dict(model="yolov8n.pt", data="my_coco8.yaml", epochs=1, batch=3)
trainer = DetectionTrainer(overrides=args)
trainer.train()
1 准备数据集 下载ultralytics-main
1.1 在官网下载 ultralytics-main
1.2 在ultralytics-main文件夹下新建dataset文件夹,dataset文件夹下设置images和labels文件夹。
1.3 设置数据集参数。 ultralytics/cfg/datasets/my_coco8.yaml
1.4 设置模型参数。 ultralytics/cfg/models/v8/my_yolov8.yaml
1.5 调试代码。
2 数据batch
batch = self.preprocess_batch(batch)
batch = {
dict:7}
"im_file" :3
"ori_shape":((423,541)),((308,271)),((377,493))
"resize_shape":((640,640)),((640,640)),((640,640))
"img":[3,3,640,640]
"cls":(9,1)
"bboxes":(9,4)
"batch_idx":(9,)
3 损失
self.loss, self.loss_items = self.model(batch)
def __call__(self, preds, batch):
"""Calculate the sum of the loss for box, cls and dfl multiplied by batch size."""
loss = torch.zeros(3, device=self.device)
feats = preds[1] if isinstance(preds, tuple) else preds
pred_distri, pred_scores = torch.cat([xi.view(feats[0].shape[0], self.no, -1) for xi in feats], 2).split(
(self.reg_max