YOLOv5白皮书-第Y3周:yolov5s.yaml文件解读
目錄
- 一、課題背景和開發環境
- 開發環境
- 二、參數配置
- 三、anchors配置
- 四、backbone
- 五、head
- 六、調整模型
- 七、打印模型查看
一、課題背景和開發環境
📌第Y3周:yolov5s.yaml文件解讀📌
- 語言:Python3、Pytorch
- 📌本周任務:將yolov5s網絡模型中第4層的C3*2修改為C3*1,第6層的C3*3修改我C3*2。
- 💫任務提示:僅需修改./models/yolov5s.yaml文件
YOLOv5配置了4種不同大小的網絡模型,分別是YOLOv5s、YOLOv5m、YOLOv5l、YOLOv5x,其中YOLOv5s是網絡深度和寬度最小但檢測速度最快的模型,其他3中模型都是在YOLOv5s的基礎上不斷加深、加寬網絡使得網絡規模擴大,在增強模型檢測性能的同時增加了計算資源和速度消耗。出于對檢測精度、模型大小、檢測速度的綜合考量,本文選擇YOLOv5s作為研究對象進行介紹。
./models/yolov5s.yaml文件是YOLOv5s網絡結構的定義文件,如果你想改進算法的網絡結構,需先修改該文件中的相關參數,然后再修改./models/common.py與./models/yolo.py中的相關代碼。
開發環境
- 電腦系統:Windows 10
- 語言環境:Python 3.8.2
- 編譯器:無(直接在cmd.exe內運行)
- 深度學習環境:Pytorch 1.8.1+cu111
- 顯卡及顯存:NVIDIA GeForce GTX 1660 Ti 12G
- CUDA版本:Release 10.2, V10.2.89(cmd輸入nvcc -V或nvcc --version指令可查看)
- YOLOv5開源地址:YOLOv5開源地址
- 數據:🔗水果檢測
二、參數配置
# Parameters nc: 80 # number of classes depth_multiple: 0.33 # model depth multiple 控制模型深度 width_multiple: 0.50 # layer channel multiple 控制COnv通道channel個數(卷積核數量)- depth_multiple:控制子模塊數量, = int(number*depth),該參數與任務有關
- width_multiple:控制卷積核的數量, = int(number*width)
通過這兩個參數可以實現不同復雜度的模型設計。YOLOv5s、YOLOv5m、YOLOv5l、YOLOv5x這四個模型的區別僅在于depth_multiple與width_multiple這兩個參數不同。
三、anchors配置
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,檢測大目標,共三組小 目標3組:[10, 13], [16, 30], [33, 23]
中 目標3組:[30, 61], [62, 45], [59,119]
大 目標3組:[116,90], [156,198], [373,326]
YOLOv5初始化了9個anchor,在3個Detect層(3個feature map)中使用,每個feature map的每個grid_cell都有3個anchor進行預測。分配規則是:尺度越大的feature map越靠前,相對原圖的下采樣率越小,感受野越小,則相對可以預測一些尺度比較小的物體,所有分配到定anchor越小;尺度越小的feature map越靠后,相對原圖的下采樣率越大,感受野越大,則相對可以預測一些尺寸比較大的物體,所有分配到的anchor也越大。即可以在小特征圖(feature map)上檢測大目標,也可以在大特征圖上檢測小目標。
YOLOv5根據工程經驗得到了這么3組anchors(9對尺寸參數),對于很多數據集而言已經很合適了。但也不能保證這3組anchor就適用于所有數據集,所以YOLOv5還有一個anchor進化的策略:使用k-means和遺傳進化算法,找到與當前數據集最吻合的anchors。
k-means:對當前數據集中所有的標注信息中的目標框的尺寸做聚類,輸出9對anchors的值。下面是我找到的一段聚類輸出anchors的代碼。
yolo_kmeans.py
import numpy as npdef wh_iou(wh1, wh2):# Returns the nxm IoU matrix. wh1 is nx2, wh2 is mx2wh1 = wh1[:, None] # [N,1,2]wh2 = wh2[None] # [1,M,2]inter = np.minimum(wh1, wh2).prod(2) # [N,M]return inter / (wh1.prod(2) + wh2.prod(2) - inter) # iou = inter / (area1 + area2 - inter)def k_means(boxes, k, dist=np.median):"""yolo k-means methodsrefer: https://github.com/qqwweee/keras-yolo3/blob/master/kmeans.pyArgs:boxes: 需要聚類的bboxesk: 簇數(聚成幾類)dist: 更新簇坐標的方法(默認使用中位數,比均值效果略好)"""box_number = boxes.shape[0]last_nearest = np.zeros((box_number,))# 在所有的bboxes中隨機挑選k個作為簇的中心。clusters = boxes[np.random.choice(box_number, k, replace=False)]while True:# 計算每個bboxes離每個簇的距離 1-IOU(bboxes, anchors)distances = 1 - wh_iou(boxes, clusters)# 計算每個bboxes距離最近的簇中心current_nearest = np.argmin(distances, axis=1)# 每個簇中元素不在發生變化說明以及聚類完畢if (last_nearest == current_nearest).all():break # clusters won't changefor cluster in range(k):# 根據每個簇中的bboxes重新計算簇中心clusters[cluster] = dist(boxes[current_nearest == cluster], axis=0)last_nearest = current_nearestreturn clusters四、backbone
# YOLOv5 v6.0 backbone backbone:# [from, number, module, args][[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2[-1, 1, Conv, [128, 3, 2]], # 1-P2/4[-1, 3, C3, [128]],[-1, 1, Conv, [256, 3, 2]], # 3-P3/8[-1, 6, C3, [256]],[-1, 1, Conv, [512, 3, 2]], # 5-P4/16[-1, 9, C3, [512]],[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32[-1, 3, C3, [1024]],[-1, 1, SPPF, [1024, 5]], # 9]這是YOLOv5s的backbone,可以看到每一行是一個模塊,每行都是由四個參數構成,分別是:
- from:表示當前模塊的輸入來自哪一層的輸出,-1表示來自上一層的輸出,層編號由0開始計數。
- number:表示當前模塊的理論重復次數,實際的重復次數還要由上面的參數depth_multiple共同決定,該參數影響整體網絡模型的深度。
- module:模塊類名(也可以理解為模塊的功能),通過這個類名在common.py中尋找相應的類,進行模塊化的網絡搭建。
- args:是一個list,對應到模塊類搭建時需要的參數,主要是channel、kernel_size、stride、padding、bias等。
五、head
# YOLOv5 v6.0 head head:[[-1, 1, Conv, [512, 1, 1]],[-1, 1, nn.Upsample, [None, 2, 'nearest']],[[-1, 6], 1, Concat, [1]], # cat backbone P4[-1, 3, C3, [512, False]], # 13[-1, 1, Conv, [256, 1, 1]],[-1, 1, nn.Upsample, [None, 2, 'nearest']],[[-1, 4], 1, Concat, [1]], # cat backbone P3[-1, 3, C3, [256, False]], # 17 (P3/8-small)[-1, 1, Conv, [256, 3, 2]],[[-1, 14], 1, Concat, [1]], # cat head P4[-1, 3, C3, [512, False]], # 20 (P4/16-medium)[-1, 1, Conv, [512, 3, 2]],[[-1, 10], 1, Concat, [1]], # cat head P5[-1, 3, C3, [1024, False]], # 23 (P5/32-large)[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)]這是YOLOv5s的head,數據格式和backbone一樣。
六、調整模型
我們需要調整的地方主要是backbone部分,調整如下:
第4層的C3*2修改為C3*1,第6層的C3*3修改我C3*2
七、打印模型查看
Overriding model.yaml nc=80 with nc=4from n params module arguments0 -1 1 3520 models.common.Conv [3, 32, 6, 2, 2]1 -1 1 18560 models.common.Conv [32, 64, 3, 2]2 -1 1 18816 models.common.C3 [64, 64, 1]3 -1 1 73984 models.common.Conv [64, 128, 3, 2]4 -1 1 74496 models.common.C3 [128, 128, 1]5 -1 1 295424 models.common.Conv [128, 256, 3, 2]6 -1 2 460800 models.common.C3 [256, 256, 2]7 -1 1 1180672 models.common.Conv [256, 512, 3, 2]8 -1 1 1182720 models.common.C3 [512, 512, 1]9 -1 1 656896 models.common.SPPF [512, 512, 5]10 -1 1 131584 models.common.Conv [512, 256, 1, 1]11 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest']12 [-1, 6] 1 0 models.common.Concat [1]13 -1 1 361984 models.common.C3 [512, 256, 1, False]14 -1 1 33024 models.common.Conv [256, 128, 1, 1]15 -1 1 0 torch.nn.modules.upsampling.Upsample [None, 2, 'nearest']16 [-1, 4] 1 0 models.common.Concat [1]17 -1 1 90880 models.common.C3 [256, 128, 1, False]18 -1 1 147712 models.common.Conv [128, 128, 3, 2]19 [-1, 14] 1 0 models.common.Concat [1]20 -1 1 296448 models.common.C3 [256, 256, 1, False]21 -1 1 590336 models.common.Conv [256, 256, 3, 2]22 [-1, 10] 1 0 models.common.Concat [1]23 -1 1 1182720 models.common.C3 [512, 512, 1, False]24 [17, 20, 23] 1 24273 models.yolo.Detect [4, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], [128, 256, 512]] YOLOv5s summary: 200 layers, 6824849 parameters, 6824849 gradients, 14.9 GFLOPs從日志打印出來的當前網絡結構可以看到:
· 網絡第4層為C3模塊,重復1次;
· 網絡第6層為C3模塊,重復2次;
總結
以上是生活随笔為你收集整理的YOLOv5白皮书-第Y3周:yolov5s.yaml文件解读的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信小程序----手势图案锁屏
- 下一篇: MiniGUI开发