深度剖析目標檢測演算法YOLOV4
- 2020 年 12 月 10 日
- 筆記
- 機器學習(ML Machine Learning), 深度學習(DL Deep Learning)
深度剖析目標檢測演算法YOLOV4
目錄
-
簡述 yolo 的發展歷程
-
介紹 yolov3 演算法原理
-
介紹 yolov4 演算法原理(相比於 yolov3,有哪些改進點)
-
YOLOV4 源程式碼日誌解讀
yolo 發展歷程
採用卷積神經的目標檢測演算法大致可以分為兩個流派,一類是以 R-CNN 為代表的 two-stage,另一類是以 YOLO 為代表的 one-stage,
R-CNN 系列的原理:通過 ROI 提取出大約 2000 個候選框,然後每個候選框通過一個獨立的 CNN 通道進行預測輸出。
R-CNN 特點:準確度高,速度慢,所以速度成為它優化的主要方向。
YOLO 系列的原理:將輸入圖片作為一個整體,通過 CNN 通道進行預測輸出。
YOLO 特點:速度快,準確度低,所以準確度成為它優化的主要方向。
經過一系列的優化與改進,特別是今年 4 月份推出的 YOLOV4,使得它在準確度方面得到了大幅度的提升,另外,它還能達到實時檢測(在 GPU 加持的情況下)。
下圖是 YOLOV4 源程式碼的頁面,github: //github.com/AlexeyAB/darknet
它的 Star 達到 13400,可以說,知名度不是一般的高,在目標檢測領域,好像只有 YOLOV3 超過它了,達到了 19000 ,是不是值得大家花點時間精力去探索一下呢 ?
這裡需要說明一下的是 YOLOV3(美國大神),YOLOV4 (俄羅斯大神)作者不是同一個人,在 19 年的時候,YOLOV3 作者發表了一個聲明:有些組織將他的演算法用於
軍事和窺探個人隱私方面,使得他在道德上很難接受,他將不再進行 CV 的研究與更新。當然,這是一個小插曲了,這裡,我們看到,YOLOV4 作者更新是非常頻繁的,
commits 達到了 2000 + 。下面我們看看官方給出的實驗結果。
這裡是以 COCO 作為測試數據集,相比於 YOLOV3,YOLOV4 在精度方面提升了 10%,FPS(frame per second) 提升了 12%。
順便說一句,YOLOV3 的作者也是認可 YOLOV4 的改進的,在 YOLOV3 的官網 //github.com/pjreddie/darknet 也是給出了
YOLOV4 的鏈接。
yolov3 演算法原理
這裡借用某位大神畫的結構圖,因為 YOLOV4 是在 YOLOV3 的基礎上改進的,所以我們需要先介紹一下 YOLOV3,
這裡可能需要一些神經網路的知識,比如卷積,池化,全連接,前向傳播,反向傳播,損失函數,梯度計算,權重參數更新,如果對
這些不是很清楚,可以看我之前的部落格(卷積神經網路(CNN)詳解與程式碼實現 //www.cnblogs.com/further-further-further/p/10430073.html)。
YOLOV3 原理我在上上一篇部落格(深度剖析YOLO系列的原理 //www.cnblogs.com/further-further-further/p/12072225.html)有過介紹,
這裡我就介紹一下大家容易忽略,或者是比較難理解的點:
- 輸入圖片尺寸可變
輸入圖片尺寸是 608 * 608,當然,這個尺寸是可以改變的,它只需要滿足是 32 的倍數,因為在經過後面的網路結構的時候,圖片尺寸縮小的最大倍數是 32 倍,
這可以從它的輸出 19 * 19 看出來。
- 主幹網路
採用的是 darknet 53 層網路結構,去掉了全連接層,53 – 1 = 52
52 = 1+(1+2*1)+(1+2*2)+(1+2*8)+(1+2*8)+(1+2*4)
為什麼要去掉全連接層 ?
解答:全連接的本質是矩陣的乘法運算,會產生固定尺寸的輸出,而 YOLOV3 是需要多尺寸的輸出的,所以要去掉全連接層。
CBL :表示基礎的卷積模組,是由一個 Conv 卷積層 + BN 批量歸一化層 + relu 非線性激活函數層組成。
為什麼在 CBL 里沒有池化層 pooling ?
解答:池化層有兩種實現方式,最大值池化和平均值池化,他們都有一個缺點,會造成資訊的明顯丟失(相比於卷積實現池化的功能來說,改變滑動窗口的步長) 。
Res Unit(殘差單元) :表示將上一層的輸出一分為二,一部分通過兩個基礎卷積模組得到輸出,與另一部分進行求和,這樣就能使得輸出的殘差不可能為 0,
從而有效的防止梯度消失或者梯度爆炸。
ResX : 是由不同的 Res Unit 組成。
多尺寸輸出:用到 2 個上取樣,注意 Concat 和 Add 的區別。
上取樣原理:以特徵圖相鄰像素值來預測中間位置的像素值,然後以這個值插入到中間位置,實現特徵圖尺寸的翻倍。
Concat : 特徵圖張量的拼接,拼接後尺寸不變,深度改變。
Add :特徵圖對應位置像素值的求和,求和後的尺寸和深度不發生改變。
- 輸出
有三個輸出,19 * 19 * 255,38 * 38 * 255,76 * 76 * 255
這三個輸出有著怎樣的物理含義 ?
解答:將輸入圖片網格化,網格化後的大小是 19 *19, 38 * 38,76 * 76,每個網格化後的小方格,也就是一個 grid cell,將要
預測 3 個 bounding box,每個 bounding box = 1 個置信度 + 4 個位置資訊 + 類別總數(COCO 數據集就是 80)
為什麼每個 grid cell 要預測 3 個 bounding box ?
解答:這樣來理解,比如說,一個人站在一輛車的前面,從遠處看,這個人和這輛車中心點是完全重合的,但是我們能夠看清楚
人和車,但是如果中心點重合的對象超過 3 個,那麼我們很有可能對第 4 個,第 5 個以及後面的對象就完全看不清楚了,
所以,這裡的 3 表示對象中心點重疊的最大值。
bounding box 如此之多,如何確定最佳的 bounding box ?
解答:採用的 NMS(Non Maximum Suppression)非極大值抑制演算法來去除重疊。
NMS 演算法原理:> 將預測輸出的 bounding boxes 放入到左邊的列表中,以置信度來進行降序排列,找到置信度最大的 bounding box ,
比如說這裡的 dog1,將 dog1 移出左邊列表到右邊列表中;
> 遍歷左邊列表,求出每個 bounding box 與 dog1 的交並比(IoU = Intersection over Union 兩個框的交集/並集),
當然,要提前設定一個閾值(一般是 0.5),大於 0.5表示左邊 bounding box 與 dog1 有高度的重疊,將這個 bounding box 去掉;
> 重複之前的操作,直至左邊列表為空,右邊列表得到的 bounding box 就是最佳的結果;
檢測匹配問題,為什麼 19 * 19 => 大對象 ? 38 * 38 => 中等對象 ? 76 * 76 => 小對象 ?
解答:輸入圖片尺寸是固定的,比如說這裡的 608 * 608,將它網格化,網格化就有三種情況:19 * 19,38 * 38,76 * 76,那麼是不是 19 * 19 網格化後
的小方格的寬和高要比其他兩種要大,這也就意味著它的感受視野是最大的,所以它就能檢測出大對象,而其他兩個的對應關係也是相同的道理。
yolov4 演算法原理
還是借用某位大神畫的結構圖,記不清名字了,是在抱歉。
乍一看,是不是跟 YOLOV3 長得很像,只不過比 YOLOV3 更複雜了一些,這裡 YOLOV4 的作者將結構劃分為以下四個部分:
Input,Backbone,Neck,Head,下面就來看看每個部分都做了哪些改進。
- Input 改進點
採用 Mosaic 實現數據增強。
Mosaic 演算法原理:在輸入圖片集中隨機選取 4 張圖片進行隨機縮放,隨機裁剪,隨機扭曲,然後將他們拼接起來,
其目的就是豐富樣本數據集。
- Backbone 改進點
採用 CSPNet(Cross Stage Partial Network)網路結構,它其實是在殘差網路的基礎上發展起來的。
具體改進點:
> 用 Concat 代替 Add,提取更豐富的特徵。
之前介紹過 Concat 操作後,特徵圖的尺寸不變,深度會增加,而 Add 操作後尺寸和深度都不改變,從這個意義上說,用 Concat 代替 Add,就能夠提取更豐富的特徵。
> 引入 transition layer (1 * 1conv + 2 * 2pooling),提取特徵,降低計算量,提升速度。
為什麼引入 1 * 1conv,能夠降低計算量,提升速度 ?
解答:這裡我舉一個實例來說明,輸入圖片大小是 56 * 56 * 256,要求得到輸出大小是 28 * 28 * 512,這裡就有兩種實現方式:
一次卷積方式,它的卷積核參數個數是 117 萬;另一種是二次卷積方式,引入了 1 * 1 卷積,它的卷積核參數個數是 62 萬,
相比於一次卷積方式,它的卷積核參數個數降低了一倍。
> 將 Base layer 分為兩部分進行融合,提取更豐富的特徵。
將 Base layer 一分為二,一部分通過類似殘差網路得到的輸出與另一部分進行 Concat 操作,將操作後的結果通過 Transition Layer。
- Backbone 改進點
用 dropblock 取代 dropout
dropout 作用:防止過擬合,
dropout 缺點:每次訓練時隨機去掉的神經元可以通過相鄰的神經元來預測,因為隨著網路層數的增加,神經元之間的相關性是越來越強。
dropblock:每次訓練時隨機去掉一整片區域,這樣就能組合更多不一樣的網路,從而表現出更好的泛化作用。
- Neck 改進點
FPN(Feature pyramid networks) + PANet(Path Aggregation Network)
它其實是在 YOLOV3 的基礎上增加了一個自底向上的 PANet 結構,特徵圖的尺寸是通過下取樣得到的,而下取樣是通過卷積的方式實現的(改變滑動窗口的步長)。
- Head 改進點
用 CIoU Loss 取代 Iou Loss
IoU loss 中 IoU 交並比,兩個框的交集/並集,有兩個缺點:
> 無法反應兩個的距離
例如 狀態 1,兩個框不相交,無論怎樣移動兩個框,IoU = 0。
> 無法區分兩者相交的情況
例如 狀態 2 和 3,兩個框相交的情況完全不一樣,但是 IoU 相同。
CIoU Loss 的思想:第一步,在兩個框最外層再畫一個最小的矩形框,求出這個框的對角線的距離,這個距離就能衡量兩個框的距離;
第二步,求出兩個框中心點的歐式距離,這歐式距離就能衡量兩者的相交情況。
CIoU Loss 數學表達式如上,它能有效的解決 IoU Loss 存在的問題。
YOLOV4 源程式碼日誌解讀
- 網路層數:
YOLOV4 總共層數有 161 層,YOLOV3 是 106 層,網路層數增加是非常明顯的。
從這個圖可以看出,YOLOV4 採用了大量的 1 * 1 卷積,之前介紹過,採用 1 * 1 卷積,是能降低計算量,提升速度的。
- 每列含義
layer : 每層操作名稱
filters :卷積核的深度
size/strd(dil):卷積核的尺寸/滑動窗口的步長
input:輸入圖片的大小
output:輸出圖片的大小
- 代表性層的含義(需要注意的是,這裡隱藏了一個前提條件 padding = 1)
> 第 0 層 conv 卷積操作,表示 608 * 608 * 3 & 3 * 3 * 32 => 608 * 608 * 32,這裡 32(輸出特徵圖尺寸深度)
是由卷積核的深度決定的。
> 第 1 層 conv 還是卷積操作,表示 608 * 608 * 32 & 3 * 3 * 64 => 304 * 304 * 64,大家發現沒有,輸出特徵圖的尺寸
相比於輸入特徵圖的尺寸,降低了一倍,這是因為滑動窗口的步長變成了 2 。
> 第 7 層 Shortcut,它其實等價於 Add 操作,也就是第 6 層的輸出與第 4 層的輸出進行卷積,
304 * 304 * 64 & 304 * 304 * 64 => 304 * 304 * 64,輸出特徵圖的尺寸和深度都沒有改變。
> 第 9 層 route 操作,它其實等價於 Concat 操作,也就是第 8 層的輸出與第 2 層的輸出進行卷積,
304 * 304 * 64 & 304 * 304 * 64 => 304 * 304 * 128,輸出特徵圖尺寸不變,深度增加,為兩個輸入特徵圖深度之和。
相信大家理解了這些層的含義之後,對於後面的其他層的理解,就比較容易了,下面看看它最後的輸出:
76 * 76 * 255, 38 * 38 * 255,19 * 19 * 255,這跟之前介紹 YOLOV4 結構圖的輸出是相一致的。
引用
//pjreddie.com/media/files/papers/YOLOv3.pdf
//arxiv.org/pdf/2004.10934.pdf
//arxiv.org/pdf/1911.11929v1.pdf
//arxiv.org/pdf/1803.01534.pdf
不要讓懶惰佔據你的大腦,不要讓妥協拖垮了你的人生。青春就是一張票,能不能趕上時代的快車,你的步伐就掌握在你的腳下。