yolov5 結構知識點解析


與yolov3對比,yolov5主要進行了下面4方面的改進:(其實很多在yolov4中已經存在了,這里再仔細研究一下)。以5.0版本來介紹,6.0版本將Focus去掉了。結構圖見3.1

  • 輸入端:Mosaic數據增強,自適應錨框計算,自適應圖片縮放
  • Backbone:Focus + C3
  • Neck:FPN+PAN
  • Prediction:GIOU_Loss

  下面分別詳細解說:

一,Mosaic數據增強(https://zhuanlan.zhihu.com/p/143747206)

  Yolov4/5中使用的Mosaic是參考2019年底提出的CutMix數據增強的方式,但CutMix只使用了兩張圖片進行拼接,而Mosaic數據增強則采用了4張圖片,隨機縮放、隨機裁剪、隨機排布的方式進行拼接。

   這里首先要了解為什么要進行Mosaic數據增強呢?

    在平時項目訓練時,小目標的AP一般比終目標和大目標低很多。而Coco數據集中也包含大量的小目標,但比較麻煩的是小目標的分布並不均勻。首先看下小、中、大目標的定義:

    2019年發布的論文《Augmentation for small object detection》對此進行了區分:

   可以看到小目標的定義是目標框的長寬0*0~32*32之間的物體

   但在整體的數據集中,小、中、大目標的占比並不均衡。如上表所示,Coco數據集中小目標占比達41.4%,數量比中目標和大目標都要多。但在所有的訓練集圖片中,只有52.3%的圖片有小目標,而終目標和大目標的分布相對來說更加均勻一些。針對這種情況,YOLOV4/5的作者采用了Moscaic數據增強的方式。主要有幾個優點:

  1. 豐富數據集:隨機使用4張圖片,隨機縮放,再隨機分布進行拼接,大大豐富了檢測數據集,特別事隨機縮放增加了很多小目標,讓網絡的魯棒性更好。
  2. 減少GPU:可能有人會說,隨即縮放,普通的數據增強也可以做,但作者考慮到很多人可能只有一個GPU,因此Mosaic增強訓練時,可以直接計算4張圖片的數據,使得Mini-batch大小並不需要很大,一個GPU就可以達到比較好的效果。

  次外,發現另一研究者的訓練方式也值得借鑒,采用的數據增強和Mosaic比較類似,也是使用4張圖片(不是隨機分布),但訓練計算loss時,采用”缺啥補啥“的思路:如果上一個iteration中,小物體產生的loss不足(比如小於某一閾值),則下一個iteration就用拼接圖;否則就用正常圖片訓練。

二, Focus模塊(摘自:https://blog.csdn.net/qq_39056987/article/details/112712817)

1.1 Focus模塊的原理

  Focus模塊在v5中是圖片進入backbone前,對圖片進行切片操作,具體操作是在一張圖片中每隔一個像素拿到一個值,類似於鄰近下采樣,這樣就拿到了四張圖片,四張圖片互補,長的差不多,但是沒有信息丟失,這樣一來,將W、H信息就集中到了通道空間,輸入通道擴充了4倍,即拼接起來的圖片相對於原先的RGB三通道模式變成了12個通道,最后將得到的新圖片再經過卷積操作,最終得到了沒有信息丟失情況下的二倍下采樣特征圖。

  其實就是yolov2里面的ReOrg+Conv操作,也就是亞像素卷積的反向操作版本,簡單來說就是把數據切分成4份,每份數據都是相當於2倍下采樣得到的,然后再channel維度進行拼接,最后進行卷積操作。可以最大程度的減少信息損失而進行下采樣操作。

  以yolov5s為例,原始的640 × 640 × 3的圖像輸入Focus結構,采用切片操作,先變成320 × 320 × 12的特征圖,再經過一次卷積操作,最終變成320 × 320 × 32的特征圖。切片操作如下:

1.2 Focus模塊的作用

  先引用yolov5官方解答:

  Focus() 是用來降低FLOPS的,跟mAP無關,但接下來你可能看到使用Focus() 之后對比普通卷積層FLOPS反而增加了,那作者為什么說可以降低呢?作者又回答了:一個Focus層可以代替3個yolov3/4的層。層數減少了,FLOPS肯定是降低啦。

  在討論Focus的作用之前,先了解兩個概念:

  • 參數數量(params):關系到模型大小,單位通常是M,通常參數用float32表示,所以模型大小是參數數量的4倍。
  • 計算量(FLOPs):即浮點運算數,可以用來衡量算法/模型的復雜度,這關系到算法速度,大模型的單位通常為G,小模型單位通常為M;通常只考慮乘加操作的數量,而且只考慮Conv和FC等參數層的計算量,忽略BN和PReLU等,一般情況下,Conv和FC層也會忽略僅純加操作的計算量,如bias偏置加和shoutcut殘差加等,目前技術有BN和CNN可以不加bias。
  • params計算公式:Kh × Kw × Cin × Cout
  • FLOPs計算公式:Kh × Kw × Cin × Cout × H × W = 即(當前層filter × 輸出的feature map)= params × H × W

  總所周知,圖片在經過Focus模塊后,最直觀的是起到了下采樣的作用,但是和常用的卷積下采樣有些不一樣,可以對Focus的計算量和普通卷積的下采樣計算量進行做個對比:在yolov5s的網絡結構中,可以看到,Focus模塊的卷積核是3 × 3,輸出通道是32:

  那么做個對比:

  普通下采樣:即將一張640 × 640 × 3的圖片輸入3 × 3的卷積中,步長為2,輸出通道32,下采樣后得到320 × 320 × 32的特征圖,那么普通卷積下采樣理論的計算量為:

    FLOPs(conv) = 3 × 3 × 3 × 32 × 320 × 320 = 88473600(不考慮bias情況下)
    params參數量(conv) = 3 × 3 × 3 × 32 +32 +32 = 928 (后面兩個32分別為bias和BN層參數)

  Focus:將640 × 640 × 3的圖像輸入Focus結構,采用切片操作,先變成320 × 320 × 12的特征圖,再經過3 × 3的卷積操作,輸出通道32,最終變成320 × 320 × 32的特征圖,那么Focus理論的計算量為:

    FLOPs(Focus) = 3 × 3 × 12 × 32 × 320 × 320 = 353894400(不考慮bias情況下)
    params參數量(Focus)= 3 × 3 × 12 × 32 +32 +32 =3520 (為了呼應上圖輸出的參數量,將后面兩個32分別為bias和BN層的參數考慮進去,通常這兩個占比比較小可以忽略)

  可以明顯的看到,Focus的計算量和參數量要比普通卷積要多一些,但是~實際上是代替了三層,經過改進之后參數量還是變少了,也達到了提速的效果

1.3 其它幾個有趣問題(https://github.com/ultralytics/yolov5/issues/847)

  • Q1: 有個疑惑,在Focus降低計算量的同時,“步長”采樣會不會對邊框回歸有影響呢?
  • A1:Focus(在v6.0中已經被替代)是將空間信息堆疊到通道信息中,可能在邊框回歸時會有1個像素的減少,但你在回歸的時候本來就不可能預測的一個像素都不差。

  

  • Q2:Focus為什么只用了一次,並且是用在整個網絡的最開始階段?
  • A2:對分類模型,可能在主干網上使用更好一點;但對檢測模型來說,(用在主干網)很難保證不影響mAP@0.5:0.95(mAP@0.5可能影響不大)

 三, CSPDarkNet53(摘自:https://blog.csdn.net/moxibingdao/article/details/107438085,https://zhuanlan.zhihu.com/p/143747206)

  Yolov4和v5都使用CSPDarknet作為Backbone,從輸入圖像中提取豐富的信息特征。CSPNet全稱是Cross Stage Partial Networks,也就是跨階段局部網絡。CSPNet解決了其他大型卷積神經網絡框架Backbone中網絡優化的梯度信息重復問題,將梯度的變化從頭到尾地集成到特征圖中,因此減少了模型的參數量和FLOPS數值,既保證了推理速度和准確率,又減小了模型尺寸。CSPNet實際上是基於Densnet的思想,復制基礎層的特征映射圖,通過dense block 發送副本到下一個階段,從而將基礎層的特征映射圖分離出來。這樣可以有效緩解梯度消失問題(通過非常深的網絡很難去反推丟失信號) ,支持特征傳播,鼓勵網絡重用特征,從而減少網絡參數數量。

 

   CSPDarknet53是在yolov3主干網絡Darknet53的基礎上,借鑒2019年的CSPNet的經驗,產生的Backbone結構,其中包含了5個CSP模塊。

  每個CSP模塊前面的卷積核大小都是3*3,stride=2,因此可以起到下采樣的作用。因為Backbone有5個CSP模塊,輸入圖象是608*608,所以特征圖變化的規律是:608-->304-->152-->76-->38-->19。經過5次CSP模塊后得到19*19大小的特征圖。而且作者只在Backbone中采用了Mish激活函數,網絡后面仍然采用了Leaky_relu激活函數。為啥要采用CSP模塊?CSPNet全稱是Cross Stage Paritial Network,主要從網絡結構設計的角度解決推理中從計算量很大的問題。CSPNet的作者認為推理計算過高的問題是由於網絡優化中的梯度信息重復導致的。因此采用CSP模塊先將基礎層的特征映射划分為兩部分,然后通過跨階段層次結構將它們合並,在減少了計算量的同時可以保證准確率。因此Yolov4在主干網絡Backbone采用CSPDarknet53網絡結構,主要有三個方面的優點:

  • 優點一:增強CNN的學習能力,使得在輕量化的同時保持准確性。
  • 優點二:降低計算瓶頸
  • 優點三:降低內存成本

   這篇文章的CSP思想介紹的很詳細。

Mish激活函數(https://zhuanlan.zhihu.com/p/263555912)

  激活函數是為了提高網絡的學習能力,提升梯度的傳遞效率。CNN常用的激活函數也在不斷地發展,早期網絡常用的有ReLU, LeakyReLU, softplus等,后來又有了Swish,Mish等。Mish激活函數的計算復雜度比ReLU要高不少,如果你的計算資源不是很夠,可以考慮使用LeakyReLU代替Mish。在介紹之前,需要先了解softplus和tanh函數。

  softplus激活函數的公式如下:$\zeta (x)=log(1+e^x)$

 

  上圖是其輸出曲線,softplus和ReLU的曲線具有相似性,但是其比ReLU更為平滑。目前的普遍看法是,平滑的激活函數允許更好的信息深入神經網絡,從而得到更好的准確性和泛化。

  tanh的公式如下:$tanh(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}}$

  Mish激活函數的公式為:$Mish(x)=x \times tanh(\zeta (x))$

 

 

   上圖為Mish的曲線。首先其和ReLU一樣,都是無正向邊界的,可以避免梯度飽和;其次Mish函數是處處光滑的,並且在絕對值較小的負值區域允許一些負值。

CSP結構

  CSP結構,其初衷是減少計算量並且增強梯度的表現。主要思想是:在輸入block之前,將輸入分為兩個部分,其中一部分通過block進行計算,另一部分直接通過一個shortcut進行concatenate。作者基於Dense block(對DenseNet網絡不熟悉的同學可以查看這里)講述了CSP的結構,如下圖:

 

 

 

   上圖中,上者為原始的Dense Block,下者為Partial Dense Block。假設將輸入按照part_ratio=0.5的比例分成兩部分,並且假設一個Dense Block的輸入為w *h* c,growth rate為 d,Dense block的layer數量為m,則:對於原始的DenseBlock,其CIO為(Convolutional input/Output)為cm + [(mm+m)d]/2;而對於使用了CSP結構的結構來說,其CIO下降為[cm + (mm+m)d]/2。

  作者闡述了CSP結構的優點:

  1. 加強CNN的學習能力
  2. 減少計算瓶頸,現在的網絡大多計算代價昂貴,不利於工業的落地
  3. 減少內存消耗

討論(https://zhuanlan.zhihu.com/p/263555912):

  按照CSP論文中的思路,我開始認為的CSP結構應該是這樣的——特征輸入之后,通過一個比例將其分為兩個部分(CSPNet中是二等份),然后再分別輸入block結構,以及后面的Partial transition處理。這樣符合CSPNet論文中的理論思路。

 

 

   但是實際上,我參考了一些源碼以及darknet配置文件中的網絡參數,得到的結構是這樣的:

 

   和我所理解不同的是,實際的結構在輸入后沒有按照通道划分成兩個部分,而是直接用兩路的1x1卷積將輸入特征進行變換。 可以理解的是,將全部的輸入特征利用兩路1x1進行transition,比直接划分通道能夠進一步提高特征的重用性,並且在輸入到resiudal block之前也確實通道減半,減少了計算量。雖然不知道這是否吻合CSP最初始的思想,但是其效果肯定是比我設想的那種情況更好的。性能是王道。

3.1 新版v5模塊解析(https://blog.csdn.net/Mr_Clutch/article/details/119912926)

先將yolov5-5.0結構圖貼上:(https://blog.csdn.net/Q1u1NG/article/details/107511465)

在這里插入圖片描述

3.1.1 CONV模塊

  作者在CONV模塊(CBL模塊)中封裝了三個功能:包括卷積(Conv2d)、BN以及Activate函數(在新版yolov5中,作者采用了SiLU函數作為激活函數),同時autopad(k, p)實現了padding的效果。

  總的說來Conv實現了將輸入特征經過卷積層,激活函數,歸一化層,得到輸出層。

 3.1.2 Bottleneck模塊(Resunit)

 

  • 先將channel 數減小再擴大(默認減小到一半),具體做法是先進行1×1卷積將channel減小一半,再通過3×3卷積將通道數加倍,並獲取特征(共使用兩個標准卷積模塊),其輸入與輸出的通道數是不發生改變的。
  • shortcut參數控制是否進行殘差連接(使用ResNet)。
  • 在yolov5的backbone中的Bottleneck都默認使shortcut為True,在head中的Bottleneck都不使用shortcut。
  • 與ResNet對應的,使用add而非concat進行特征融合,使得融合后的特征數不變。

3.1.3 C3模塊,v5.0用C3模塊代替了CSP。

C3模塊

BottleNeckCSP模塊

  •  在新版yolov5中,作者將BottleneckCSP(瓶頸層)模塊轉變為了C3模塊,其結構作用基本相同均為CSP架構,只是在修正單元的選擇上有所不同,其包含了3個標准卷積層以及多個Bottleneck模塊(數量由配置文件.yaml的n和depth_multiple參數乘積決定)
  • 從C3模塊的結構圖可以看出,C3相對於BottleneckCSP模塊不同的是,經歷過殘差輸出后的Conv模塊被去掉了,concat后的標准卷積模塊中的激活函數也由LeakyRelu變味了SiLU。

3.1.4 SPP模塊(v6.0里新增了SPPF層)

 

  • SPP是空間金字塔池化的簡稱,其先通過一個標准卷積模塊將輸入通道減半,然后分別做kernel-size為5,9,13的maxpooling(對於不同的核大小,padding是自適應的)
  • 對三次最大池化的結果與未進行池化操作的數據進行concat,最終合並后channel數是原來的2倍。

  作用:SPP是由微軟研究院的何凱明大神提出,主要為了解決兩個問題:    

  1. 有效避免了對圖像區域剪裁、縮放操作導致的圖像失真等問題;
  2. 解決了卷積神經網絡對圖像重復特征提取的問題,大大提高了產生候選框的速度,且節省了計算成本。

  但在yolo中不是為解決這兩個問題的,yolo版本的SPP實際上只是借鑒了空間金字塔的思想,通過SPP模塊實現了局部特征和全部特征,這也是為什么SPP模塊中的最大池化核大小要盡可能地接近或者等於需要池化的特征圖的大小,特征圖經過局部特征與全矩特征相融合后,豐富了特征圖的表達能力,有利於待檢測圖像中目標大小差異較大的情況,尤其是對於yolo這種復雜的多目標檢測,對檢測的精度上有了很大的提升。

SPPF():先貼上官方介紹:

   

 

   可以用來代替SPP,結果是一樣的,但是可以降低FLOPS,運行的更快。

四,PANet(https://www.cnblogs.com/winslam/p/14486803.html, https://zhuanlan.zhihu.com/p/143747206)

4.1 FPN 結構和yolov3中的FPN結構  

  FPN就是這樣,自頂向下的模式,將高層特征傳下來。而底層特征卻無法影響高層特征,並且FPN中的這種方法中,頂部信息流往下傳,是逐層地傳,計算量比較大。PAN解決了這一問題。先看下YOLOV3中未加PAN的結構圖:

  可以看到經過幾次下采樣,三個紫色箭頭指向的地方,輸出分別是76*76, 38*38,19*19.以及最后prediction中用於預測的三個特征圖①19*19*255、②38*38*255、③76*76*255。[注:255表示80類別(1+4+80)×3=255] ,我們將Neck部分用立體圖畫出來(右),更直觀的看下兩部分之間是如何通過FPN結構融合的。

4.2 PANet

  PANet引入了自底向上的路徑,使得底層信息更容易傳遞到高層頂部。左邊圖(a),V3中講過,特征融合,featureMap越小,感受野越大;可能要走例如100層,才能遍歷玩ResNet。現在加入要將底層特征傳遞到特征圖頂部,如圖a紅線,如果是采用上述FPN算法,可能要走很多層,增加了很多計算量。而PANet采用的是:在進行自頂向下的特征融合后(實際上,PANet無論是bottom-top,還是top-bottom進行特征信息傳遞,都是在“從原始網絡中提取低、中、高層特征圖之后”,進行的),然后再進行自下向頂(這里遍歷的最終的特征圖P2-5,而不是原始100多層特征圖)的特征融合,如圖(b)綠色線條,這樣特征傳遞需要“穿越”的特征圖數量大大減少,幾層就到了。

  而Yolov4中Neck這部分除了使用FPN外,還在此基礎上使用了PAN結構:

  前面CSPDarknet53中講到,每個CSP模塊前面的卷積核都是3*3大小,步長為2,相當於下采樣操作。因此可以看到三個紫色箭頭處的特征圖是76*76、38*38、19*19。以及最后Prediction中用於預測的三個特征圖:①76*76*255,②38*38*255,③19*19*255。我們也看下Neck部分的立體圖像,看下兩部分是如何通過FPN+PAN結構進行融合的。

  我們都知道,深層的feature map攜帶有更強的語義特征,較弱的定位信息。而淺層的feature map攜帶有較強的位置信息,和較弱的語義特征。FPN就是把深層的抑郁特征傳到前蹭,從而增強多個尺度上的語義表達。而PAN則相反把前蹭的定位信息傳導到深層,增強多個尺度上的定位能力。

  PANet 結構是在FPN的基礎上引入了 Bottom-up path augmentation 結構。FPN主要是通過融合高低層特征提升目標檢測的效果,尤其可以提高小尺寸目標的檢測效果。Bottom-up path augmentation結構可以充分利用網絡淺特征進行分割,網絡淺層特征信息對於目標檢測非常重要,因為目標檢測是像素級別的分類淺層特征多是邊緣形狀等特征。PANet 在 FPN 的基礎上加了一個自底向上方向的增強,使得頂層 feature map 也可以享受到底層帶來的豐富的位置信息,從而提升了大物體的檢測效果。

  這樣結合操作,FPN層自頂向下傳達強語義特征,而特征金字塔則自底向上傳達強定位特征,兩兩聯手,從不同的主干層對不同的檢測層進行參數聚合,這樣的操作確實很皮。FPN+PAN借鑒的是18年CVPR的PANet,當時主要應用於圖像分割領域,但Alexey將其拆分應用到Yolov4中,進一步提高特征提取的能力。

五,損失函數(https://zhuanlan.zhihu.com/p/335345293)

  YOLOv5損失函數包括:

  • classification loss, 分類損失
  • localization loss, 定位損失(預測框與GT框之間的誤差)
  • confidence loss, 置信度損失(框的目標性;objectness of the box)

  總的損失函數:classification loss + localization loss + confidence loss (組成部分從yolov1~yolov5都是這三類,但具體損失的計算方法有變)

  • YOLOv5使用二元交叉熵損失函數計算類別概率和目標置信度得分的損失。(大多數分類器假設輸出標簽是互斥的。如果輸出是互斥的目標類別,則確實如此。因此YOLO應用softmax函數將得分轉換為總和為1的概率。而YOLOv3/v4/v5使用多標簽分類。例如,輸出標簽可以是“行人”和“兒童”,他們不是排他性的。所以輸出得分的總和可以大於1)YOLOv3/v4/v5使用多個獨立的邏輯(logistic)分類器替換softmax函數,以計算輸入屬於特定標簽的可能性。在計算分類損失進行訓練時,YOLOV3/V4/V5對每個標簽使用兒園交叉熵損失。這也避免使用softmax函數而降低了計算復雜度。
  • YOLOv5使用CIOU Loss作為bounding box回歸的損失。邊界框回歸是許多2D/3D計算機視覺任務中最基本的組件之一,一個改進機會是根據IOU計算的度量損失取代回歸損失(例如$l_1$和$l_2-norms$),但是IOU直接用作性能度量和損失函數有兩個問題:1)如果兩個物體不重疊,則IOU值將為零,並且不會反應兩個形狀彼此之間的距離。2)在物體不重疊的情況下,如果將IOU用作損失,則其梯度將為零並且無法進行優化。想法:推廣到IOU到非重疊清醒,並且確保:a)遵循與IoU相同的定義,即將比較對象的形狀屬性編碼為區域(region)屬性;b)維持IoU的尺寸不變性;c) 在重疊對象的情況下確保與IoU的強相關性。

   YOLOv5 采用了BECLogits 損失函數計算objectness score的損失,class probability score采用了交叉熵損失函數(BCEcls loss),bounding box采用了GIOU(DIOU, CIOU) Loss。GIoU Loss 用來計算bounding box的 Loss, GIOU 是在CVPR2019中,論文中提出。GIOU直接把IoU設為回歸的 Loss。

   $GIoU = IoU-\frac{|C\(AUB)|}{|C|}$

    上面公式的意思是將兩個任意框A,B,我們找到一個最小的封閉形狀C,讓C可以把A,B包含在內,接着計算C種沒有覆蓋A和B的面積占C總面積的比值,然后用A與B的IoU減去這個比值。與IoU類似,GIoU也可以作為一個距離,loss可以用

$L_GIoU = 1-GIoU$

 六,YOLOV5的訓練技巧

  最后引入B站上大神的yolov5訓練技巧:

6.1 訓練預熱 Warmup

  剛開始訓練時,模型的權重是隨機初始化的,此時若選擇一個較大的學習率,可能帶來模型的不穩定(振盪)。選擇Warmup預熱學習率的方式可以使得開始訓練的幾個epoches或者一些steps內學習率較小,在預熱的小學習率下,模型可以慢慢趨於穩定,等模型相對穩定后再選擇預先設置的學習率進行訓練,使得模型收斂速度變得更快,模型效果更佳。

  余弦退火調整學習率CosineAnnealingLR:https://arxiv.org/pdf/1608.03983.pdf

6.2 自動計算錨框 Autoanchor

  Anchor給出了目標寬高的初始值,需要回歸的是目標真實寬高與初始寬高的偏移量,而不適用anchor的做法需要回歸寬高的絕對量。Autoanchor only runs when the best possible recall(BPR, 最大可能召回率) is under threshold. yolov5的threshold是98%。

  自動計算錨框是采用聚類方法,You can disable autoanchor with python train.py -- noautoanchor. AutoAnchor will attach anchors automatically to your model.pt file (i.e. last.pt or best.pt)

6.3 超參數進化

  Hyperparameter evolution is a method of Hyperparameter Optimization using a Genetic Algorithm(GA) for optimization. 好吧,還是看官網吧(https://github.com/ultralytics/yolov5/wiki/Tips-for-Best-Training-Results)

6.4 斷點續訓

  You use --resume by itself with no arguments, or by pointing to a last.pt to resume from: 

python train.py --resume # resume from most recent last.pt

python train.py --resume runs/exp0/weights/last.pt # resume from specific weights

 

 6.5 多GPU訓練

  • DataParallel
  • Distriubted DataParallel

 

 

 

   更多內容請看:https://github.com/ultralytics/yolov5/issues/607, https://github.com/ultralytics/yolov5/issues/475

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM