- 這篇大概是寫給有碰過一些 object detection model,但是很久沒追細節的人
- 這篇應該寫得最清楚的 https://medium.com/@jonathan_hui/yolov4-c9901eaa8e61
- 把這篇當成一篇 review paper 也不為過
- 這篇主要是講如何改進,所以會列舉一些相關技術,所以是很 hard-core 的,請耐心閱讀。
- 文字部分很多都是我腦補的 不一定是原文的意思
隨著時間演進,人類越來越了解 deep learning,越來越多觀念被提出,所以算力即使沒上漲很多,model 也該越來越好。
Object detection 就是輸入圖片,輸出位置(x,y),大小(w,h),分類(classes),有時候會加 confidence level,如下圖所示。
在講簡單一點,假設我們圖片中只有一個物件一個種類,那麼輸入是 512x512x3(RGB),輸出就是 1x1x5,5 就是 x,y,w,h, c,c 為 0~1 的 class 信心。
多物件就有多物件的 purpose 方法。至於怎麼 train Yolo,Yolo 實際上幹了什麼,怎麼生出物件的 bounding box,請參考這篇[英文][正體中文的都沒寫得很優]
反正最暴力的方式就是用 CNN 硬 train 一波
然後分類問題,分別改善,Yolov4 提出了 Object detection 中各個問題的分類:Input, Backbone(CNN 架構), Neck(融合各種 scale 的方式), Head(如何propose bounding box 的方法 與 loss function)
有關什麼是 one-stage two-stage 可以看[這篇]
結論是 Yolov4 好棒棒!如下圖,越往右上方越好
- AP(average precision) 越高=越準
- FPS(Frame per second)越大=越快
論文裡面還分兩類改善方式
- Bag of freebies 架構不改,但能得到更好準確度的方式
- Bag of specials 架構小改,跑的變慢,但能得到更好準確度的方式
以下我們就來分別介紹 以下這兩個表格,這兩張列表告訴你那些技術在解決該類的問題。
Backbone(骨架)
VGG16 應該是各位最熟的
model 一直加深以後,發現會有 gradient vanish 的現象,下圖紅色部分,最靠近 output(右邊) , gradient 還很OK,越接近 input(左邊),一堆回到gradient 都在 0。
ResNet, DenseNet
主流解決方式兩種 residual block(ResNet), 跟dense block(DenseNet)
Residual block 把前面的 feature 接過來(shortcut) [中文][英文]
Dense Block 則是把前面所有的 feature 都拿來算[中文][英文]
ResNeXt
則是告訴你深度跟寬度不算什麼,cardinality 比較重要,也就是說分支會比一起算好,所以即是參數量一樣,ResNeXt 的 error 硬生生少了 1%
CSP(Cross-Stage-Partial-connections, bag of specials)
也是這個概念,不過比較簡單,split, bypass 最後 merge,這個架構可以套用在任何 model 比如說 ResNet 或 DenseNet。
而這次選用的 CSPdarknet-53(yolov4 recommended) 就是將 CSP 套用在 darknet-53 上,但好像沒說怎麼接的
總結一下 Backbone 這段
Backbone 目的就是要有能力去找出圖片的 latent feature,但 model 越大跑的越慢,所以就要取一個平衡點,也就是給定時間與參數量下,能萃取出越多的 feature 越好。
接下來是修飾 Backbone 的技術
Activation(Backbone, Bag of specials)
如果有在做 training 的人,應該知道改 activation function 其實花不到 5mins,卻可以帶來可觀的效果。
除了大家熟知的 ReLU 以外,還有 leaky ReLU(<0 時還有一點斜率)[中文] 為主流。Yolov4 在舉出幾個可能會變好的 function。
- Swish: 這是 google brain 使用 RNN 去尋找的新的 activation function
- Mish(yolov4 recommended): 這個是不知道怎麼找出來的
然後這兩個函數的形狀其實差不多,而且都是連續可微的,如下圖
以上這兩個 activation function 雖然比較好,但是缺點是會犧牲一點計算。下面公式為 Mish 跟 Swish,相較 ReLU 來說稍微複雜了點,所以會比較慢一點,故歸類在 Bag of specials,然後效果如下表,數據結果證明 Mish 是比較厲害的
其他的
- LReLU and PReLU is to solve the problem that the gradient of ReLU is zero when the output is less than zero.
- ReLU6 and hard-Swish, they are specially designed for quantization networks
- SELU is for self-normalizing a neural network.
DropOut(Backbone, Bag of freebies)
Dropout 跟 activation 一樣 5mins 的 code 就搞定了,而且效果卓越,且training 的時候才會用到,所以歸類在 bag of freebies
Dropout 目的是防止 overfitting,也就是讓 model 不會過度專注在某些特徵上。至於 overfitting 怎麼來的不外乎以下兩種:
- 只有這個 weight 很重要(在 CNN 中叫做 kernel),比如一看到綠色就決定他是葉子
- 只有這個 feature 很重要,比如說你的圖片上的某幾個 pixel 是熱區
一般 Dropout
就是隨機(其實是 Bernoulli distribution) 丟掉部分的 feature ,也就是把 feature 直接設成 0。
DropConnect
既然 weight 會導致 overfitting,那就隨機丟掉部分的 weight,如下圖
SpatialDropout
則是 dropout 掉 feature map 的其中幾個 channel,目的是防止 kernel 太強。
不然的話,如下圖橘色紅色箭頭的部分,雖然某些被 dropout 掉,但只要 W2 這個 kernel 存在,就能發揮他的影響力。
DropPath
dropout 掉整個 Convolution 層,論文裡分成兩種
- Local: Dropout 掉 Convolution layer(紅色)
- Global: 只 train 其中一條路徑,額外的好處是可以看到各個 path 的能力
Dropblock(Yolov4 recommended)
因為圖片是連續的,所以只隨機 dropout 幾個 pixel 大概是沒什麼用的,要的話就是一整個區域。
Batch Normalization(Backbone, Bag of specials)
BN(Batch Normalization)
就是把 features 做 normalization,這樣 gradient 會比較均勻。
可是 batch normalization,是用統計來算 mean, variance,這會有幾個問題
- 統計的數量跟 batch size 有關(下圖公式的 m)
- batch size 小的時候,會不會抽樣不均勻導致 normalize 會有問題,那麼 batch size =1 呢
為了避免跟 batch size(下圖的 N) 有關, Batch Renormalize, Group Normalize, Layer Normalize, Instance Normalize[英文參考] 相繼被提出 如下圖
Batch Renormalize
想法很簡單 既然 N 太小,那我也把之前的 mini-batch 跟現在的 mini-batch 一起算 mean,這個叫 moving average
好的,那接下來問題是,我有在更新 weight,所以之前的 mean 已經過時了,那怎麼辦
CBN(Cross-Iteration Batch Normalization)
不要保留太多個 mini-batch 的 mean,我只保留 k-1 次,並假設每次參數 update 是平滑的,所以可以利用 linear 逼近現在的 mean,我們就有算式可以估計目前的 mean 跟 deviation 有多大
CmBN(Cross mini-Batch Normalization, yolov4 recommended)
這是 Yolov4 自己新創的,其實也沒什麼,就是 CBN 但是每個 batch 分開算 i.e. 第 i batch 的第 1 個 mini-batch,不可以參考 i-1 batch 的 最後一個 mini-batch。
Cross-GPU Batch Normalization (CGBN or SyncBN)
則不適合在單張 GPU 上跑
總結一下這個小節
Activation, Dropout, Normalize 這三個技術,無非就是幫助 backbone 可以萃取出更好的 latent feature,當然越深的 model 更是較克服 overfitting 的問題。
Domain Knowledge(Input, Bag of freebies)
人類不會說明圖片的 latent feature,可是我們會說經過旋轉後 latent feature 不太變,於是我們可以用這些 domain knowledge 來操作 data augmentation ,最終增加資料量。
普通的操作(Pixel-wise adjustments)
混合與修改 label 的操作(Simulating object occlusion)
Yolov4 特有的 Mosaic(Yolov4 recommended)
優點是一張圖片當4 張用,某種程度有增加 minibatch size 的效果
其他類似的
- Random Erase, CutOut
- Hide-and-seek, Grid Mask
- Style Transfer GAN
圖片 scaling 也不會影響太多人類的判斷,但這方面機器比較難解決,等等會說明,解決方式會歸類到 neck 的部分
小結
這部分是圖片特有的想法,過去的影像處理知識,都是人類對圖片的了解,透過這些了解,我們可以肆無忌憚地增加 data 量來輔助 ML。
而其他非圖片要使用這些技術時,要小心。
Multi-scale Prediction(Neck, Bag of specials)
為什麼需要這層呢,是因為 backbone 本身的缺點。
簡單的說,每次 max-pooling ,圖片大小就少一半,細節也會跟著消失(下圖b)。e.g. 你的物體很小共有 14pixel x 14pixel 那麼做四次 pooling 後(1/16)就消失了。
(下圖a) 一開始呢,那就我把圖片分成,一般的,縮小的,縮小很多的,這樣子叫 image pyramid 的方式 ,缺點是浪費資源(要跑很多次 model)
(下圖c) 把前面幾層接回來做預測,就有 scaling 的味道在
(下圖d) 但是這樣預測的結果,不同 scale 是獨立的,所以就用 FPN(Feature Pyramid Network) 把它們串起來
PAN(Path Aggregation Network)
(下圖b)接下來 串一層不夠,就兩層,
NAS-FPN BiFPN
(下圖c, d)串兩層不夠,就 deep 起來,
要特別注意的是這並不會花掉太多資源,從 p0(input) 到 p7 (最後一層)共 100 層以上(Backbone 貢獻的),但接下來的 bottom-up top-down 都大概 10 層左右,計算量不會多太多,所以被歸類在 Bag of specials。
這個架構就是 EfficientDet[英文參考] 所採取的,畫在第二重要那張圖中,他的速度跟準確度在 Yolov4 之前都算厲害的。
Modified PAN(Yolov4 recommended)
架構跟 PAN 一樣,唯一的修改是: 合併會比直接相加更好,但是缺點是會變多 channel ,計算量會稍大
以上是橫向(scale-scale 之間的融合),接下來是直接對最後一層動手的
SPP(Spatial Pyramid Pooling, Yolov4 recommended)
就是對最後一層做不同 window-size 的 max-pooling , 如下圖
圖(a) 是原本 Yolov2 的方式,2D feature map 被弄成 1D 的 feature,所以最後面需要接 fully-connected layers,
圖(b) 則是把他們再黏起來,所以後面能繼續接 CNN,為 Yolov3 使用的方式。然後好處是你可以想像成他又多了一層這樣,如下下圖所示
ASPP(Atrous Spatial Pyramid Pooling)
跟上面很像,不過不是用 max-pooling,是用 Dilated Convolution 接。[英文]
RFB(Receptive Field Block)
就融合 ASPP 的 dilated convolution 跟 SPP 不同 window-size 的策略(下圖最右邊)
最最後,我們剛剛提到的技術都是 scale 怎麼做融合與提取。而要生出 bounding box 預測之前,還有三種作法
- 每層分開輸出(畢竟已經融合過 latent feature 了)
- 直接 merge,可以是 concatenation(把 channel 合併) 或是 直接相加
- MiWRC(Multi-input Weighted Residual Connections, yolov4 自己發明的名詞?)
MiWRC(Yolov4 recommended)
我猜是指在 BiFPN 中黑色虛線箭頭這裡,他不是簡單的相加,而是有多乘上一個 weights,這個 weighs 是簡單的加權(有點像後面的 attention, 不過不是),意思就是每個 scale 其實有不同的權重。
小結
這部分也是針對圖片的 scaling 而做出的一些修正,也可以說它是再從 backbone 的每個 layer 裡再萃取一些資訊
Attention Module(Neck, Bag of specials)
因為經過太長的 neural network,所以最早輸入的影響力會比小,attention 目的就是再把重要的東西提煉出來,這概念來自 RNN[中文參考 寫得不錯][英文參考]。
第二種舉例是,如下圖,如果有一張 CT 圖你要找一個腫瘤,你不可能一次就找到,我們會先瞄準極有可能的區域,然後再仔細看。
簡單來說 Attention 就是對你的 Features 再做一次加權
加權的值通常是 0 到 1, 所以最後一層通常是
- Softmax
- Sigmoid
- 比例(就是直接 Normalize)
SE(Squeeze-and-Excitation block)
把最後一層拿出來,拿出去跑 NN ,然後得到每個 channel 應該有多少權重,然後再乘回最後一層。
如果仔細看 SE,你會發現他把 Channel*H*W 縮到 Channel*1*1,也就是這個 attention 是根據 global 資訊(Note: CNN 只能看 local)來對 channel 做加權。
SE 使用 sigmoid 把值弄到 0~1,使用 averge-pooling 做降維的動作。
SAM(Spatial Attention Module)
來自CBAM(Convolutional Block Attention Module) 這篇 paper,提供了兩種 attention 技巧
- CAM(Channel Attention Module): 對 channel 做 attention,跟 SE 一樣會縮到 1x1xC,不過中間的 NN 是 max-pooling 跟 average pooling 都用。
- SAM(Spatial Attention Module): 對區域做 attention,會生成 HxWx1 的 attention ,哪些區域重要就會被加權起來,(就像剛剛的 CT 圖片,腫瘤區域的權重應該就要比較高)
Modified SAM(Yolov4 recommended)
Yolov4 覺得不需要 pooling,所以直接接 CNN(kernel 7x7) ,好處就是不會有 pooling 這樣除2的動作可能會丟失任何資訊,所以他說是 pointwise 的 attention
SFAM(Scale-wise Feature Aggregation Module)
來自 M2Det [中文參考] 把最後一層跟最後第二層拿來再接很多 CNN(下圖的 TUM), 號稱是把不同 scale 做融合。下下圖,SFAM 則放在最後把融合的所有 scale 裡面的所有 channel 們去做加權,用的也是 SE。
ASFF(Adaptively Spatial Feature Fusion)
上面的加權是對 scale 的 channel ,那這篇就是對 scale 的 pixel。
這篇把每層 feature map 接 NN(是 1x1 的 CNN) 再做 softmax,也就是對 scale 跟 pixel 做加權,如下圖最下方
小結
我認為 Attention 就是因為原本的 CNN 的 output 包含太多雜訊,所以乘上一個加權來針對某些 feature 進行操作
Loss Function(Head, Bag of freebies)
因為在做 evaluation 的時候,跟 loss function 沒有關係, loss 只在 training 時有用,所以是 bag of freebies。
Focal Loss
解決 imbalance data(不平均的 class 數量), 這個概念來自於 RetinaNet[中文],如果有 1000個 class A 分正確,那另外 3 個 class B 亂分影響不大,所以 loss function 應該跟該 class 的正確率有關。也就是說 class B 從 1/3 到 2/3 會比 class A 從 900/1000 到 910/1000 還要重要。
如下圖,當整個 class 正確率很低的時候,Loss 就會變很大,同時就有更高的 gradient 來訓練權重。
hard negative example mining or online hard example mining
不適合在 one-stage 上操作(也是為了解決 Imbalance data)
Label Smoothing (Yolov4 recommended)
引用的這篇 paper 其實很早期,告訴你
- Network 的深度跟寬度要 balance
- 不要一口氣少掉太多 channels(避免變成 bottleneck)
- (Inception)跑 1x1 的 convolution 降維度,然後再跑 3x3
- (Inception)5x5 可以用較小的兩個 3x3 取代
- (Inception) 1x3 3x1 要對稱使用
- Label Smoothing(今天重點)[英文參考]
因為最後面一層是 cross entropy,所以你要讓你的預測接近 1 的話,這個 label 就要 predict 一個很大的數
e.g. 假設你最後一層的 output 是 [0.1, 0.1, 0.1, 0.1, 6] 做完 cross entropy 變成 [0.002, 0.002, 0.002, 0.002, 0.992],你會發現 6 是 0.1 的 60 倍,這種嚴重的偏差,很容易導致 overfitting
所以解決方式很簡單,把你的 ground truth 如下面的公式改成 [0.02, 0.02, 0.02, 0.02, 0.92],也就是說過度完美的解答是不好的。
Grid Sensitivity(YOLOv4 recommended)
在預測 bounding box 大小時也同樣的問題,有一個 sigmoid(最多只會趨近 0 或趨近 1) 讓他無法完美,所以就把 sigmoid 前面乘上 1.1( >1 就好)
Label Refinement Network(LRN)
這個也是利用 domain knowledge 的概念,我們知道圖片變小不會怎樣,所以就縮小的圖片也拿來當 groud-truth
Loss Function on IOU(Head, Bag of freebies)
原本 classification 就用 cross-entropy 這沒什麼問題,但是當有 bounding box,最 naive 的方式就是 對 x, y, w, h 跟 ground truth 做 Mean Square Error(MSE, 下圖第一行第二行)
有三點問題
- 在做 MSE 有個前提是,他離 ground truth 太遠的話,就當成沒對到 ground truth,於是乎 error 就變成沒對到的 error ,而非 bounding box 的距離
- MSE 的值根本不重要,重要的是 IOU 的值(越大越好,代表跟 grounded truth 的 bounding box 越像)
- 所以我們把 loss function 設成 IOU 就好了?
沒錯,把 loss function 都用 IOU 表示。但是這樣會有一個大問題,只要沒有 overlap,IOU都會=0,所以以下三種方式都是處理這個問題。
GIOU(Generalized Intersection over Union)
GIOU[英文參考] 就是會再多考慮兩個 bounding box 的聯集,離越遠聯集越大,如下圖,綠色框框比橘色框框理論上還要好,但 IOU=0,而 GIOU (圖左下的公式)可以分得出這個差異,所以在下下圖中,loss function 是比較平滑的,這對 training 是很有幫助的。
DIOU(Distance-IoU Loss)
DIOU 就不這麼麻煩了,距離就用中心距離去算,加了 c(對角線距離) 距離才會是從 0~1。重點是距離是有方向性的,所以收斂的速度會比較快。
CIOU(Complete IoU Loss, Yolov4 recommended)
跟上面同一篇 paper,那我們多考慮 aspect ratio(長寬比,w/h 的比)
順便介紹
DIOU-NMS(Non-Maximum Suppression using DIoU, Neck, Yolov4 recommended)
是在做 objection detection 時,會 propose 出許多同義的 bounding box。NMS 作法就是有 overlap 到的就 deduplicated。
當然有可能會錯刪(比如說 confidence 不高且靠得很近),所以 DIOU-NMS 就是再加上距離的 criteria
小結
Loss function 對 model training 有非常重要的影響,就很像畫一個坡道讓你的車車可以順利滾下來,所以設的好非常重要(有 training 過就知道),而且改 loss function 也是 5 分鐘的事情。
其他
SAT(Self-Adversarial Training, Input, Input, Bag of freebies, Yolov4 recommended)
這應該是自己發明的。用 adversal (對抗)來避免 overfit,作法很簡單:
- 圖片輸入 model 後,中間會輸出 feature 的值
- 扣掉這些值,也就是沿著 gradient 對 圖片做修改(model 的參數沒有動)
- 然後把修改的圖片再丟進 model 訓練
e.g. 如果這個 model 只判斷狗的眼睛,就 classify 出他是狗的話,那 SAT 會在步驟二把 狗狗的眼睛的 feature 從圖片中扣掉。這樣 model 就必須學到狗勾的其他特徵,才可以 classify 出來。
乍聽之下很奇怪,其實概念有點像 GAN[中文參考],又有點像 saliency map[英文參考]
Cosine Annealing Scheduler(Bag of freebies, Yolov4 recommended)
[英文參考]因為模型應該會收斂,所以我們要用越來越小的 learning rate 才好。會比原本的 schedule 一段時間就降 learning rate 來的好(藍色虛線)。
不過會有個小問題是他可能降太快,導致跑到 local min,所以會加個 restart 機制(不知 Yolov4 沒有有用),如下圖,但應該注意的是最後幾次就是 fine-tune 應該就不需要 restart
Optimal hyperparameters(Bag of freebies, Yolov4 recommended)
用基因演算法 Genetic Algorithms (Evolutionary Algorithms)
我沒很熟這個,反正應該是
- 有一堆參數
- 把其中幾個組合拿去 train train 看
- 把最好的 10% 的組合的參數拿出來
- 重複 2
剩下的我就直接複製過來
Dynamic mini-batch size
Automatic increase of mini-batch size during small resolution training by us-ing Random training shapes
Optimized Anchors(Neck, Yolov4 recommended)
Using the optimized anchors for training with the 512x512 network resolution
Multiple anchors for ground truth(Neck, Yolov4 recommended)
Using multiple anchors for a singleground truth IoU (truth, anchor)>IoU threshold
Conclusion
終於結束了 寫的好累 按 clap 鼓勵我一下
所以這篇 paper 介紹(X) 提到(O) 了許多技巧,當然
沒有絕對好的技巧
要看數字說話, naive 的想法說不定也是有用的。
以下為 Yolov4 選用他最適合的。
Reference
- Yolov4
- Yolov3
- Yolov2
- Yolov1
- SSD
- Efficient Det
- Mish
- Mixup
- Cutmix
- FPN
- EfficientDet
- Residual Network
- Dense Network
- Swish
- Mish
- SPP
- CSPNet
- DropBlock
- DropConnect
- FocalLoss
- LabelSmoothing
- LRN
- IOU Rerference
- GIOU
- DIOU, CIOU
- Group Normalization
- Renormalize
- CBN
- SE
- CBAM
- ASFF
- M2Det
- Cosine annealing
- Cosine annealing +ensemble
- NMS
- DropPath
- SpatialDropout
- 補充:有關各種 CNN 可以參考這一篇