[Object detection] YOLOv8.yaml詳細說明

泓宇
12 min readJan 24, 2024

--

在前兩篇介紹如何訓練yolov8和整體架構詳解後,我們要來介紹yolov8的參數檔。yolov8.yaml可在此連結下載

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect

# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs

nc:數據集類別數

scales:不同尺寸的模型大小

Backbone

# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9

# [from, repeats, module, args]

from:來源,也就是輸入。-1代表將上層得輸入作為本層的輸出

repeats:重複次數

module:名稱

args:參數

第0層:[-1, 1, Conv, [64, 3, 2]] # 0-P1/2

-1代表將上層的輸入作為本層的輸入。 輸入的是640*640*3的影像。

Conv代表卷積層,對應的參數:64代表輸出通道數,3代表卷積核大小k,2代表stride步長。

以下是Conv的程式碼

從autopad所定義可看出,當k=3時,p=1,所以第0層的卷積 f_in=640,cout = 64,k=3,s=2,p=1

輸出的特徵圖公式為:f_out = ((f_in - k + 2*p ) / s ) + 1

所以經過此層,輸出的特徵圖尺寸為320*320*64,長寬為初始圖片的一半。

第1層:[-1, 1, Conv, [128, 3, 2]] # 1-P2/4

本層和上一層是一樣的操作(128代表輸出通道數,3代表卷積核大小k,2代表stride步長),卷積後的特徵圖尺寸為160*160*128

第2層:[-1, 3, C2f, [128, True]]

本層是C2f模組,3代表本層重複3次。 128代表輸出通道數,True表示Bottleneck有shortcut。

假設輸入C2f模組的特徵圖尺寸是h*w*cin,輸出通道數是cout,則c1=cin,c2=cout,c=0.5*cout

cv1是Conv(cin, cout, 1, 1) (k=1,s=1) //輸出為h*w*cout

cv2是Conv((2+n)*0.5*cout, cout, 1) (k=1,s=1)//輸出為h*w*cout

n是bottleneck的個數 ,m是接上了n個Bottleneck模組,Bottlenectk輸入和輸出通道數都是c=0.5*cout

在forward裡,先將輸入的特徵圖x進行cv1的Conv(cin, cout, 1, 1) (k=1,s=1)操作,然後再使用chunk將其分成2塊。所以y得到的是分成2塊的特徵圖的list。

torch.chunk:將tensor分為多塊,在不同維度上切分。
torch.chunk(tensor, chunk數,維度)

y[-1]表示被切分的最後一塊,m(y[-1]) for m in self.m就是把最後一塊放進n個連續的Bottleneck裡。

torch.cat(y, 1) 將y依第一維度拼接在一起。最後對拼接好的特徵圖進行cv2的Conv((2+n)*0.5*cout, cout, 1) (k=1,s=1 )。

以上就是C2f模組的全過程,輸出的特徵圖尺寸為h*w*cout。

第3層: [-1, 1, Conv, [256, 3, 2]] # 3-P3/8

進行卷積操作(256代表輸出通道數,3代表卷積核大小k,2代表stride步長),輸出特徵圖尺寸為80*80*256,特徵圖的長寬已經變成輸入影像的1/8。

第4層: [-1, 6, C2f, [256, True]]

本層是C2f模組,可以參考第2層的講解。 6代表本層重複6次。 256代表輸出通道數,True表示Bottleneck有shortcut。

經過這層之後,特徵圖尺寸依舊是80*80*256。

第5層: [-1, 1, Conv, [512, 3, 2]] # 5-P4/16

進行卷積操作(512代表輸出通道數,3代表卷積核大小k,2代表stride步長),輸出特徵圖尺寸為40*40*512,特徵圖的長寬已經變成輸入影像的1/16。

第6層: [-1, 6, C2f, [512, True]]

本層是C2f模組。 6代表本層重複6次。 512代表輸出通道數,True表示Bottleneck有shortcut。

經過這層之後,特徵圖尺寸依舊是40*40*512。

第7層: [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32

進行卷積操作(1024代表輸出通道數,3代表卷積核大小k,2代表stride步長),輸出特徵圖尺寸為20*20*1024,特徵圖的長寬已經變成輸入影像的1/32。

第8層: [-1, 3, C2f, [1024, True]]

本層是C2f模組。 3代表本層重複3次。 1024代表輸出通道數,True表示Bottleneck有shortcut。

經過這層之後,特徵圖尺寸一樣是20*20*1024。

第9層:[-1, 1, SPPF, [1024, 5]] # 9

快速空間金字塔池化層(SPPF)。 1024代表輸出通道數,5代表池化核大小k。 從程式碼可以看出,最後concat得到的特徵圖尺寸是20*20*(512*4),經過一次Conv得到20*20*1024。

Head

# YOLOv8.0n head
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 3, C2f, [512]] # 12

- [-1, 1, nn.Upsample, [None, 2, 'nearest']]
- [[-1, 4], 1, Concat, [1]] # cat backbone P3
- [-1, 3, C2f, [256]] # 15 (P3/8-small)

- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 12], 1, Concat, [1]] # cat head P4
- [-1, 3, C2f, [512]] # 18 (P4/16-medium)

- [-1, 1, Conv, [512, 3, 2]]
- [[-1, 9], 1, Concat, [1]] # cat head P5
- [-1, 3, C2f, [1024]] # 21 (P5/32-large)

- [[15, 18, 21], 1, Detect, [nc]] # Detect(P3, P4, P5)

第10層: [-1, 1, nn.Upsample, [None, 2, ‘nearest’]]

上採樣層。 -1代表將上層的輸出作為本層的輸入。 None代表上採樣的size(輸出尺寸)不指定。 2代表scale_factor=2,表示輸出的尺寸是輸入尺寸的2倍。 nearest代表使用的上取樣演算法為最近鄰插值演算法。 經過這層之後,特徵圖的長度和寬度變成原來的兩倍,通道數不變,所以最終尺寸為40*40*1024。

第11層: [[-1, 6], 1, Concat, [1]] # cat backbone P4

concat層,[-1, 6]代表將上層和第6層的輸出作為本層的輸入。 [1]代表concat拼接的維度是1。 從上面的分析可知,上層的輸出尺寸是40*40*1024,第6層的輸出是40*40*512,最終本層的輸出尺寸為40*40*1536。

第12層: [-1, 3, C2f, [512]] # 12

C2f模組,。 3代表本層重複3次。 512代表輸出通道數。 與Backbone中C2f不同的是,此處的C2f的bottleneck模組的shortcut=False。經過這層之後,特徵圖尺寸變成40*40*512。

第13層:[-1, 1, nn.Upsample, [None, 2, ‘nearest’]]

上採樣層。 經過這層之後,特徵圖的長度和寬度變成原來的兩倍,通道數不變,所以尺寸為80*80*512。

第14層: [[-1, 4], 1, Concat, [1]] # cat backbone P3

concat層,[-1, 4]代表將上層和第4層的輸出作為本層的輸入。 [1]代表concat拼接的維度是1。 從上面的分析可知,上層的輸出尺寸是80*80*512,第4層的輸出是80*80*256,最終本層的輸出尺寸為80*80*768。

第15層: [-1, 3, C2f, [256]] # 15 (P3/8-small)

C2f模組,。 3代表本層重複3次。 256代表輸出通道數。經過這層之後,特徵圖尺寸變成80*80*256。

第16層: [-1, 1, Conv, [256, 3, 2]]

進行卷積操作(256代表輸出通道數,3代表卷積核大小k,2代表stride步長),輸出特徵圖尺寸為40*40*256。

第17層:[[-1, 12], 1, Concat, [1]] # cat head P4

concat層,[-1, 12]代表將上層和第12層的輸出作為本層的輸入。 [1]代表concat拼接的維度是1。 從上面的分析可知,上層的輸出尺寸是40*40*256,第12層的輸出是40*40*512,最終本層的輸出尺寸為40*40*768。

第18層: [-1, 3, C2f, [512]] # 18 (P4/16-medium)

C2f模組。 3代表本層重複3次。 512代表輸出通道數。

經過這層之後,特徵圖尺寸變成40*40*512。

第19層:[-1, 1, Conv, [512, 3, 2]]

行卷積操作(512代表輸出通道數,3代表卷積核大小k,2代表stride步長),輸出特徵圖尺寸為20*20*512。

第20層: [[-1, 9], 1, Concat, [1]] # cat head P5

concat層,[-1, 9]代表將上層和第9層的輸出作為本層的輸入。 [1]代表concat拼接的維度是1。 上層的輸出尺寸是20*20*512,第9的輸出是20*20*1024,最終本層的輸出尺寸為20*20*1536。

第21層: [-1, 3, C2f, [1024]] # 21 (P5/32-large)

C2f模組。 3代表本層重複3次。 1024代表輸出通道數。

經過這層之後,特徵圖尺寸變成20*20*1024。

第22層: — [[15, 18, 21], 1, Detect, [nc]] # Detect(P3, P4, P5)

本層為Detect層,[15, 18, 21]代表將第15、18、21層的輸出(分別是80*80*256、40*40*512、20*20*1024)作為本層的輸入 。 nc是資料集的類別數

--

--

泓宇

Specialist in machine learning, image processing, computer vision, and object recognition.