YOLOV8模型及损失函数

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.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]
  2. 正样本筛选。
    用TaskAlignedAssigner分配策略。anchors中心点在GT(真实框)内部anchors为候选框。计算GT内部包含的每个anchors预测物体类别cls与CIOU的乘积作为分数对aanchors的分值,对分值排序,选取top_k个框作为正样本。
  3. 损失函数。类别损失(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*59*913*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()


################################### 调试YOLOV8的步骤 #############################################


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)     # ultralytics/engine/trainer.py
      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)  #  ultralytics/utils/loss.py
  
  def __call__(self, preds, batch):                            # 207行
    """Calculate the sum of the loss for box, cls and dfl multiplied by batch size."""
    # 3.1 处理特征,把模型输出feats变为 feats--> pred_distri[3, 4*16+cls, 8400], pred_scores[3, 64, 8400]
    loss = torch.zeros(3, device=self.device)                   # 存储box, cls, dfl 损失; tensor([0., 0., 0.])
    feats = preds[1] if isinstance(preds, tuple) else preds     # feats[[3,16*4+cls,80,80],[3,16*4+cls,40,40],[3,16*4+cls,20,20]]
    pred_distri, pred_scores = torch.cat([xi.view(feats[0].shape[0], self.no, -1) for xi in feats], 2).split(
        (self.reg_max

你可能感兴趣的:(计算机视觉,Python,YOLO)