【目標檢測】2萬字詳解 RCNN系列 YOLO系列 YOLOv3程式碼實現全流程詳解 pytorch

不佛發表於2020-11-09

目標檢測概述

之前的MTCNN實現了單類多目標的高效檢測,而現實中更普遍的任務是多類多目標檢測。

目標檢測可劃分為3個發展階段:

  1. 傳統的目標檢測
    區域選擇:滑動視窗
    特徵提取:Harr、SIFT、HOG等特徵提取演算法
    分類器:如常用的SVM模型
    基於滑動視窗的區域選擇策略沒有針對性,時間複雜度高,視窗冗餘;
    手工設計特徵費時費力,且對於多樣性的變化沒有很好的魯棒性。
  2. 基於Region Proposal的深度學習目標檢測演算法
    使用 region proposal+CNN 代替傳統目標檢測使用的 滑動視窗+手工設計特徵
    region proposal利用影像中的紋理、邊緣、顏色等資訊預先找出圖中目標可能出現的位置,獲取的候選視窗要比滑動視窗的質量更高, 可以在選取較少視窗(幾千個甚至幾百個)的情況下保持較高的召回率。以RCNN系列為代表。
  3. 基於迴歸方法的端到端的深度學習目標檢測演算法
    端到端(End-to-End)的目標檢測方法,不需要將檢測過程分為兩步(two-stage), 用region proposal來選擇區域,而是把目標檢測問題,當作迴歸問題,一步(one-stage)直接完成分類和定位。
    YOLO系列為代表,一張圖只需看一次,這也是YOLO(You Only Look Once)名字的由來。

RCNN系列

R-CNN

在這裡插入圖片描述
在這裡插入圖片描述
流程:

  1. 輸入影像,使用選擇性搜尋演算法(selective search)評估相鄰影像之間的相似度,把相似度高的進行合併,對合並後的區塊打分,選出2000個左右的region proposal(建議框),並把所有 region proposal 裁剪/縮放成固定大小。
  2. 將歸一化後的region proposal 輸入CNN網路,提取特徵。
  3. 對於提取到的CNN特徵,用SVM分類來做識別,用線性迴歸來微調邊框位置與大小,其中每個類別單獨訓練一個邊框迴歸(bounding-box regression)器。

不足:

  1. 2000個左右的候選框都需要進行卷積操作,計算量依然很大,其中有不少是重複計算。
  2. 訓練分為多個階段,步驟繁瑣:region proposal、CNN特徵提取、SVM分類、邊框迴歸。
  3. 訓練耗時,佔用磁碟空間大:卷積出來的特徵資料還需要單獨儲存。

Fast R-CNN

在這裡插入圖片描述
在這裡插入圖片描述

在這裡插入圖片描述

流程:

  1. 利用selective search 演算法在影像中從上到下提取2000個左右的Region Proposal。
  2. 將整張圖片輸入CNN,進行特徵提取。
  3. 把建議框對映到CNN的最後一層卷積feature map上。
  4. 通過RoI pooling層(類似SPP精簡版)使每個建議視窗生成固定尺寸的feature map。
  5. 使用Multi-task Loss(多工損失函式)對Softmax Loss(分類概率) 和Smooth L1 Loss(邊框迴歸)聯合訓練。

SPP-net
在這裡插入圖片描述
在這裡插入圖片描述
R-CNN 之所以要將建議框crop / warp成固定尺寸,是因為網路最後是全連線層。 空間金字塔池化層(Spatial Pyramid Pooling,SPP)使用多尺度池化,然後將結果拼接。可以在不限制輸入大小的情況下,固定輸出尺寸,有效避免了R-CNN演算法對影像區域剪裁、縮放操作導致的影像物體剪裁不全以及形狀扭曲等問題。

輸入圖片的某個位置的特徵反映在特徵圖上也是在相同位置。基於這一事實,對某個RoI區域的特徵提取只需要在特徵圖上的相應位置提取即可。SPP-net 最重要的改進在於,對原圖只做一次特徵提取,而不是對所有region proposal都做卷積,解決了重複特徵提取的問題,極大地提高了檢測速度。

Faster R-CNN

在這裡插入圖片描述
在這裡插入圖片描述
流程:

  1. 將整張圖片輸入CNN,進行特徵提取。
  2. RPN層,用於生成候選框,並利用softmax判斷候選框是前景還是背景,從中選取前景候選框(因為物體一般在前景中),並利用bounding box regression調整候選框的位置,從而得到特徵子圖(proposals)。
  3. RoI pooling層 生成固定尺寸的feature map
  4. 通過全連線層判斷proposal的類別,同時再次對bounding box進行regression從而得到精確位置。

selective search 演算法是非常耗時的,Faster R-CNN最大的貢獻就是RPN(Region Proposal Networks)網路,創造性地採用卷積網路自行產生建議框,並且和目標檢測網路共享卷積網路,使得建議框數目從原有的約2000個減少為300個,且建議框的質量也有本質的提高.。

RPN具體步驟:

  1. 生成錨框 anchors
    經過RPN層的3x3卷積後每個feature map上的一個點,生成9個anchor(3種尺寸×3種比例)。anchor分為前景和背景兩類(先不管物體類別,只用區分它是前景還是背景即可)。anchor有[x,y,w,h]四個座標偏移量,x,y表示中心點座標,w和h表示寬度和高度。
  2. 判斷選區是前景還是背景
    輸出分為兩部分,一部分在1x1卷積後,reshape成一維向量,經過softmax來判斷anchors是前景還是背景,由於感興趣的物體位於前景中,大量背景anchors將被捨棄。
  3. 確定建議框位置
    另一部分經1x1卷積後用來確定建議框的位置,也就是迴歸anchors的 [x,y,w,h] 座標值。
  4. 輸出特徵子圖 proposal
    對anchors做非極大值抑制(NMS)等篩選處理,至此得到最終的proposals,即物體的粗糙定位。
  5. RoI pooling層 生成固定尺寸的feature map。
  6. 通過全連線層和softmax得到分類概率,並對建議框做最後迴歸調整。

Faster R-CNN用resNet101模型作為卷積層,在voc2012資料集上可以達到83.8%的準確率,超過YOLO SSD和YOLOv2。 其最大的問題是速度偏慢,每秒只能處理5幀,達不到實時性要求。
在這裡插入圖片描述

YOLO系列

YOLOv1

針對於two-stage目標檢測演算法普遍存在的運算速度慢的缺點,YOLO創造性的提出了one-stage端到端演算法,將目標檢測重新定義為單個迴歸問題,也就是將物體分類和物體定位在一個步驟中完成,直接在輸出層迴歸bounding box的位置座標和所屬類別概率。通過這種方式,YOLO可實現45幀每秒的檢測速度,完全能滿足實時性要求。


YOLO的使用流程非常簡潔:

  1. resize圖片大小至448×448
  2. 傳入單個卷積網路
  3. 根據模型置信度做非極大值抑制

在這裡插入圖片描述
實現原理
將輸入影像劃分成 S ∗ S S * S SS個網格,如果一個物體的中心點落入一個grid cell(單元格)內,那麼這個grid cell就負責檢測這個物體。每一個grid cell預測 B B B個bounding boxes,以及這些bounding boxes的分數。這個分數反映了模型預測這個grid cell是否含有物體,以及是這個物體的可能性是多少。

定義 c o n f i d e n c e = P r ( O b j e c t ) ∗ I O U p r e d t r u t h confidence=Pr(Object)*IOU^{truth}_{pred} confidence=Pr(Object)IOUpredtruth ,如果這個 cell 中不存在物體,則得分為0 ;否則的話,分數為 predicted box(預測框)與ground truth(真實框)之間的 IoU(交併比)。

每個 bounding box 由五個預測值組成:x,y,w,h,confidence。座標(x,y)代表了 bounding box 的中心點相對於 grid cell 邊界的值,(w,h) 則是 bounding box 的寬和高相對於整幅影像的值,confidence 就是 IoU 值。

在測試階段,把每個柵格的條件類別概率乘上每個 bounding box 的 confidence,這樣既包含了 bounding box 包含物體的類別資訊,也包含了預測框和真實框的符合程度。
在這裡插入圖片描述
圖片劃分為 S × S S×S S×S個grid , 每個grid cell預測 B B B個bounding boxes,類別數為 C C C。預測值是一個 S × S × ( B ∗ 5 + C ) S×S×(B*5+C) S×S×(B5+C)的張量。在論文中,使用 PASCAL VOC 資料集, S = 7 , B = 2 , C = 20 S=7,B=2,C=20 S=7,B=2,C=20, 最終預測值為 7 × 7 × 30 7×7×30 7×7×30的張量。

網路模型
在這裡插入圖片描述
YOLO檢測網路結構借鑑了GoogLeNet ,用1x1+3x3卷積層簡單代替 inception 模組,包括24個卷積層和2個全連線層。

特點:

  1. 使用 224 ∗ 224 224*224 224224的影像預訓練分類樣本,再改為 448 ∗ 448 448*448 448448訓練檢測樣本。
  2. 啟用函式由ReLU改為PReLU。
  3. 輸出層為全連線層,因此在檢測時要求輸入影像尺寸和訓練影像相同。

損失函式
在這裡插入圖片描述

  • 第1行:bounding box 中心點座標 ( x , y ) (x, y) (x,y)損失
  • 第2行:bounding box 寬高 ( w , h ) (w, h) (w,h)損失
    相同值的寬高誤差對不同大小的目標影響是不一樣的,比如同樣是寬度相差2個畫素,對小目標的預測影響很大,對大目標則無足輕重,因此加根號的目的是拉開這種差距,使得同樣的誤差對大目標的損失更小,對小目標的損失更大。
  • 第3、4行:bounding box 的置信度損失
    分為包含物體和不包含物體兩部分,包含物體的置信度只在每個grid cell的兩個bounding boxes中選擇IoU大的計算,因此每個grid cell只能預測一個物體,這是YOLOv1的一個缺陷。
  • 第5行:分類損失
    只有在grid cell包含物體的時候才計算。
    在這裡插入圖片描述

YOLO最大的特點就是速度快,處理速度達到45fps,fast版本(網路較小)甚至可以達到155fps。

不足之處有以下幾點:

  1. 一張圖片最多隻能檢測 7 ∗ 7 = 49 7*7=49 77=49個物體。
  2. 每個grid cell只有兩個bounding boxes,只對應一個類別,容易漏檢,相比較Faster R-CNN雖然降低了背景誤檢率,但召回率低。
  3. 對小目標和聚集目標效果差。

在這裡插入圖片描述
在這裡插入圖片描述

SSD

SSD(Single Shot MultiBox Detector)針對YOLOv1對寬高不常見物體和小目標物體偵測效果差的缺陷做了改進。

SSD去掉了網路最後的全連線層,其認為目標檢測中的物體,只與周圍資訊相關,它的感受野是區域性的,故沒必要也不應該做全連線。

SSD最大的特點是:多尺度檢測。對多個卷積層,提取不同大小感受野的feature map,在這些多尺度的feature map上,進行目標位置和類別的訓練和預測。顯然,越淺層的feature map感受野越小,越利於檢測小物體。

和Faster R-CNN相似,SSD也提出了anchor(錨框)的概念。feature map 的每個點對應為原圖的一個區域的中心點,以這個點為中心,構造出6個寬高比例不同,大小不同的anchor, 每個anchor對應4個位置引數 ( x , y , w , h ) (x,y,w,h) (x,y,w,h)和21個類別概率(VOC訓練集20個類別,加上anchor是否為背景,共21類)。
在這裡插入圖片描述
通過多尺度多 anchor 的方法,SSD顯著提升了YOLOv1的檢測精度。

YOLOv2 / YOLO9000

YOLOv1與Fast R-CNN的誤差比較分析表明,YOLOv1 產生了大量的定位錯誤。此外,與生成候選區域方法相比,YOLOv1召回率相對較低。 因此,YOLOv2主要關注改善召回率和定位,同時保持分類準確性。
在這裡插入圖片描述
YOLOv1到YOLOv2的進化之路中嘗試了各項改進,我們看一下最重要的幾點:

批標準化(batch normalization)
批標準化可以顯著改善收斂性,避免過擬合,而且不再需要dropout和其他形式的正則化。

全卷積網路
和SSD一樣,YOLOv2移除了全連線層,另外消除一個池化層,使網路卷積層的輸出具有更高的解析度,將網路輸入影像解析度由448×448改為416X416,這樣做是為了讓特徵圖尺寸為奇數,只有一箇中心點。目標,尤其是大的目標,往往佔據影像的中心,所以最好在正中心擁有單獨一個位置來預測這些目標,而不是在中心附近的四個位置。如此,通過32倍的下采樣,416X416的影像最終得到13×13的特徵圖。

使用錨框anchor
在這裡插入圖片描述
引入anchor後,我們將類別預測與座標迴歸分開處理,單獨預測每個anchor的類及其目標。對比YOLOv1,現在每個grid cell可以預測多個類別的物體,一個anchor可以預測一個物體。YOLOv1僅為每個圖片預測98個框,使用anchor後,模型預測的框數超過一千個,雖然精度會小幅下降,但召回率顯著提升。

聚類獲得anchor尺寸
anchor的尺寸是手工挑選的,雖然網路可以通過學習適當地調整方框,但是如果從一開始就為網路選擇更好的prior(先驗),就可以讓網路更容易學習。
YOLOv2不手工選擇先驗,而是對訓練集的邊框使用k-means聚類演算法,自動找到良好的prior。如果在演算法中使用歐氏距離進行聚類,大框比小框的誤差會更大,我們重視的是同一類框的IoU值,因此定義距離為:
在這裡插入圖片描述
在這裡插入圖片描述
用不同的k值執行k-means,並繪製樣本框和聚類中心的平均IoU。權衡模型複雜度和召回率,選擇 k = 5 k = 5 k=5。聚類的中心與手工選取的anchor顯著不同,它有更少的短寬框,更多的長窄框。5個聚類anchor的效能類似於9個手工選取anchor。

位置預測
按照Faster RCNN的anchor方法,在訓練的早期階段,預測bounding box的中心點沒有約束,可能出現在任何位置,位置預測容易不穩定,因此YOLOv2調整了預測公式。
在這裡插入圖片描述
b x , b y , b w , b h b_x,b_y,b_w,b_h bx,by,bw,bh為bounding box的中心點和寬高;
σ \sigma σ為sigmoid函式;
c x , c y c_x,c_y cx,cy為grid cell大小歸一化後,當前grid cell相對影像左上角的座標;
p w , p h p_w,p_h pw,ph為anchor的寬高;
t x , t y , t w , t h , t o t_x,t_y,t_w,t_h,t_o tx,ty,tw,th,to是要學習的引數,分別用於預測bounding box的中心點、寬高、置信度。
在這裡插入圖片描述
通過sigmoid函式, t x , t y t_x,t_y tx,ty被約束在 ( 0 , 1 ) (0,1) (0,1),即當前grid cell內。如此引數更容易學習,網路更穩定。
在這裡插入圖片描述

相較YOLOv1計算loss時使用 w , h \sqrt w,\sqrt h w ,h 來平衡大小框的損失,YOLOv2選擇用自然對數函式 ln ⁡ \ln ln壓縮寬高,對照兩個函式影像, ln ⁡ \ln ln函式的值域在 ( − ∞ , + ∞ ) (-\infty,+\infty) (,+),更符合網路輸出。

網路模型

在這裡插入圖片描述
為了進一步提升速度,YOLOv2提出了Darknet-19模型,包含19個卷積層和5個最大池化層,最後使用全域性平均池化來進行預測。

識別更多類別
YOLOv2聯合訓練ImageNet資料集和COCO資料集,其中混合了分類和檢測兩種資料,當學習分類樣本時,只計算分類損失,學習檢測樣本時,才同時計算位置損失。這是一種開創性的訓練方法,擴充了網路檢測能力,使其學會檢測一些沒有檢測樣本的物件。由此,訓練出了可以識別9000個類的YOLO9000。

在這裡插入圖片描述

YOLOv3

雖然YOLO之父Joseph Redmon在YOLOv3論文引言中說,他之前一年啥也沒幹,主要刷Twitter… 但絲毫不影響YOLOv3成為當時目標檢測演算法的集大成者。

使用sigmoid分類器
作者發現Softmax對於提升網路效能沒什麼作用,YOLOv3選擇使用單獨的Logistic分類器,在訓練中用binary cross-entropy loss(二元交叉熵損失)來預測類別。

因為Softmax總和為1的排他性,強加了一個假設:每個框有且只有一個類別。對於有巢狀關係標籤的複雜資料集(如“人”和“女人”),這種假設是不妥的,相比之下,多標籤的分類方法能更好地模擬資料。

跨尺度預測
為了更好地檢測小目標,YOLOv2曾使用passthrough層來獲得細粒度特徵(感受野更小), 而YOLOv3選擇在3個不同尺度進行預測,網路分別為每種尺寸各預測了3個邊界框,對於COCO資料集,每種尺寸最終得到的張量為 N × N × [ 3 × ( 4 + 1 + 80 ) ] N ×N ×[3 \times (4+ 1+ 80)] N×N×[3×(4+1+80)]:4個邊框偏移量、1個目標置信度、80個類別。

從淺層網路提取特徵圖,上取樣之後,在element-wise(畫素級別)將高低兩種解析度的特徵圖拼接到一起,由此得到早期特徵對映中的細粒度特徵,並獲得更豐富的語義資訊。

在這裡插入圖片描述
YOLOv3依然使用K-Means聚類方法來得到anchor的尺寸,在COCO資料集上選擇了9個聚類和3個尺寸。特徵圖下采樣次數越少,尺寸越大,感受野越小,用來檢測越小的物體。

新的網路
在這裡插入圖片描述
YOLOv3提出新的網路模型:Darknet-53。在Darknet-19基礎上借鑑了residual(殘差)網路,新增了shortcut connection(捷徑連線),共有53個卷積層。這個新網路在效能上遠超Darknet-19 ,但是在效率上同樣優於ResNet-101和ResNet-152。

YOLOv3 程式碼實現流程詳解

anchor

在進入實現流程之前,不得不先開啟一個番外篇。你說不就anchor嘛,看好多遍早明白了。不!你沒有!!好叭對不起,是我沒有……讓我們不厭其煩(手動微笑)地再來擼一擼:

bounding box?anchor box??
這兩個概念在一些不嚴謹的說法裡容易混淆。Bounding box是完整的邊框資訊,包括中心座標、寬高、置信度以及類別;而anchor box是一個物體形狀的先驗,只包含寬高。

搞個anchor出來有啥用??
按照吳恩達的課程,anchor是為了在一個grid cell中預測多個物體。

我的腦回路
:為啥YOLOv1選擇一個類別對應兩組座標?一個類別對應一組座標,再來一個類別對應一組座標,不就能預測兩個物體了嘛?
:哦……這樣的兩組預測好像沒法對應物體。做標籤的時候可以指定哪組標籤表示哪個物體,可是預測的時候網路只會輸出最有可能的兩組值,這兩組值基本上只會是預測同一個物體的相似值,起不到預測多個物體的效果。
:emmm 我想起來了,好像在做單類單目標檢測的時候遇到過類似的問題,如果單純地將一幅圖片上的目標改成兩個,標註兩個目標進行訓練,預測的時候兩個框只會出現在同一個目標上,置信度較低的目標是框不到的。

so,anchor的意義就是告訴這兩組預測,你倆分別負責找什麼形狀的物體。比如1號bounding box找高瘦的目標,2號bounding box找矮胖的目標。在訓練的時候用anchor和ground truth的IoU作為置信度來篩選正負樣本,將物體交給大小形狀相近的anchor所對應的那組值來學習,這樣在預測時,兩個bounding box就有了傾向,不會只框到同一個物體。

那麼,anchor的尺寸怎麼給呢?這是一種先驗,表示我們一開始就告訴模型物體更有可能是哪些大小形狀的。這個尺寸如果給的不好,不同的物體就沒法區分,自然會影響訓練效果。比如,我給了高瘦和矮胖兩個尺寸較小的anchor,而實際物體的ground truth都是接近正方形的或者尺寸很大的,這就不好辦了,它和兩個anchor的IoU都不大,可能被判作負樣本不參與訓練,即使勉強作為正樣本,網路根據IoU學習到的置信度也是不高的,在預測的時候效果也不會好。我們主觀估計的anchor尺寸並不準確,因此才需要K-means聚類演算法。

anchor思想在程式碼中的實現並不複雜,但我一直沒有徹底理解,也沒找到解釋很清晰的文章。那不管了,暫時按我說的為主!有不服的……請快來教教我!
好了,番外篇完結,進入正題~

網路

YOLOv3網路模型的主幹部分是Darknet-53,輸入影像經過Darknet-53得到52×52、26×26、13×13三種尺寸的特徵圖,網路具體引數如下:


在這裡插入圖片描述

通過route(特徵在通道維度拼接)操作,融合了不同層次的特徵,從而提高預測精度。以26×26的特徵圖為例,concatenate(拼接)操作融合了淺層網路的512維特徵(偏區域性)和由上取樣得到的256維特徵(偏全域性),為了預測小物體,顯然以區域性特徵為主。52×52的特徵圖同理。

網路輸出為:
在這裡插入圖片描述
其中 3 3 3表示每個尺寸的特徵圖預測3個anchor, 5 5 5表示4個座標偏移量+置信度,C為類別數。

以COCO資料集80分類為例,網路輸出如下:

在這裡插入圖片描述

標籤

生成的訓練標籤應該和網路輸出相對應,分別有13×13、26×26、52×52三組。
思路是這樣的:首先生成 ( 13 , 13 , 3 , 5 + C ) , ( 26 , 26 , 3 , 5 + C ) , ( 52 , 52 , 3 , 5 + C ) (13,13,3,5+C),(26,26,3,5+C),(52,52,3,5+C) (13,13,3,5+C),(26,26,3,5+C),(52,52,3,5+C)三個零矩陣,其中 3 3 3表示每種尺寸特徵圖的每個grid cell有3個anchor, 5 + C 5+C 5+C的含義同上。然後在有物體的grid cell計算3個anchor與對應ground truth的IoU和座標偏移量,填入矩陣。沒有物體的grid cell只需要訓練置信度,預設為0即可。
在這裡插入圖片描述
在這裡插入圖片描述
b x , b y , b w , b h b_x,b_y,b_w,b_h bx,by,bw,bh為bounding box的中心點和寬高;
σ \sigma σ為sigmoid函式;
c x , c y c_x,c_y cx,cy為grid cell大小歸一化後,當前grid cell相對影像左上角的座標;
p w , p h p_w,p_h pw,ph為anchor的寬高;
t x , t y , t w , t h , t o t_x,t_y,t_w,t_h,t_o tx,ty,tw,th,to是要學習的引數,分別用於預測bounding box的中心點、寬高、置信度。

為了避免混淆,沿用上圖預測時的引數名稱進行說明。設每張樣本圖片有n個物體,每個物體對應標籤 ( c l s , x , y , w , h ) (cls,x,y,w,h) (cls,x,y,w,h),分別表示類別、中心點座標、寬高。

grid cell在歸一化之前,代表原圖的尺寸就是該特徵圖在網路中下采樣的倍數,如13×13的特徵圖, 每個grid cell代表的尺寸自然是 416 ÷ 13 = 32 {416}\div{13}=32 416÷13=32,這也是網路中5次下采樣的倍數總和 32 = 2 5 32=2^5 32=25

我們先要找到有物體的grid cell的座標 c x , c y c_x,c_y cx,cy,這裡有個取巧的做法:將物體中心點座標 ( x , y ) (x,y) (x,y)除以每個grid cell代表的尺寸,相當於給grid cell做歸一化,如此可以同時得到物體所在grid cell的座標 c x , c y c_x,c_y cx,cy和中心點偏移量 t x , t y t_x,t_y tx,ty
在這裡插入圖片描述
舉個例子:13×13的特徵圖,一個grid cell尺寸為32,現有一物體中心點座標 ( x , y ) = ( 88 , 60 ) (x,y)=(88,60) (x,y)=(88,60),除以32後等於 ( 2.75 , 1.875 ) (2.75,1.875) (2.75,1.875),不難發現,其中整數部分 ( 2 , 1 ) (2,1) (2,1)正是物體所在grid cell的座標 c x , c y c_x,c_y cx,cy,小數部分 ( 0.75 , 0.875 ) (0.75,0.875) (0.75,0.875)正是物體對所在grid cell左上角點的偏移量 t x , t y t_x,t_y tx,ty

寬高偏移量 t w , t h = l o g e w p w , l o g e h p h \displaystyle t_w,t_h=log_e \frac w{p_w},log_e \frac h{p_h} tw,th=logepww,logephh,置信度 t o t_o to只需計算物體的真實框ground truth與3個anchor的IoU即可。最後,在建立的零矩陣中,對應座標 c x , c y c_x,c_y cx,cy處,填入三個anchor對應的 5 + C 5+C 5+C個值,類別 C C C經過one-hot編碼,因此需要 C C C個數表示。

至此,標籤處理完成。你可能注意到,標籤shape和網路輸出還是不一樣,在計算loss和預測時,通過矩陣變換就能解決,具體在損失設計中說明。

這裡我在一開始有個疑惑:在做訓練label時, t w , t h t_w,t_h tw,th是用真實框ground truth寬高比上anchor寬高,再取log得到,因此在預測時符合上述公式,可是 t x , t y t_x,t_y tx,ty並未做任何處理,為什麼在預測時可以直接加上sigmoid函式?

我的理解是: t x , t y t_x,t_y tx,ty的label是在 ( 0 , 1 ) (0,1) (0,1)內,可是網路學習到的值沒有任何約束,很可能超出這個範圍,顯然超出當前grid cell的預測是不合理的。sigmoid函式是增函式,在壓縮的同時,不會改變值的大小關係,也就是說網路梯度更新的方向是對的,只是對值的要求變低了。比如我們希望 σ ( t x ) \sigma(t_x) σ(tx)值在 ( 0.5 , 0.6 ) (0.5,0.6) (0.5,0.6),根據sigmoid反函式算得,網路學習到的 t x t_x tx滿足 ( 0 , 0.4 ) (0,0.4) (0,0.4)範圍內即可,降低了學習難度。置信度 t o t_o to也是同理。

另外還有一個小點:
如果物體和anchor形狀不太匹配,置信度值會比較低,訓練和預測的效果不太好,有些GitHub上的程式碼選擇直接將IoU最大的anchor置信度直接給1。

損失

根據置信度標籤篩選正負樣本,按照論文,選擇置信度最高的anchor負責該物體,忽略不是最高但高於閾值(論文中給0.5)的anchor,小於閾值的anchor作為負樣本。正樣本損失包含置信度、座標、分類損失3部分,負樣本置信度標籤為0,只有置信度損失。

在具體實現中,因為雖然YOLO使用了anchor,但相較MTCNN多個偏移框迴歸一個預測框,YOLO的召回率還是較低的,因此在篩選樣本時有些GitHub上的程式碼選擇儘可能保留anchor,將大於設定閾值的數個anchor都作為正樣本參與訓練。這樣在預測時可以增加預測數,提高召回率。這些GitHub程式碼的改動實現效果還可以,可能有什麼負面影響我尚不清楚。

相對於anchor的總數,其中需要負責物體預測的正樣本往往是遠不足一半,正負樣本損失求和時前面可以加上係數以均衡樣本: l o s s = α l o s s p o s i t i v e + β l o s s n e g a t i v e loss=\alpha loss_{positive} + \beta loss_{negative} loss=αlosspositive+βlossnegative。最後將3種特徵圖的損失求和得到總損失。
在這裡插入圖片描述
損失函式如下:

  1. 置信度損失:二元交叉熵損失(BCE)
  2. 座標損失:均方差損失(MSE)
  3. 分類損失:交叉熵損失(標籤無巢狀)或二元交叉熵損失(標籤有巢狀)

三種損失其實都可以簡單地用均方差損失函式,YOLOv2就是這麼幹的,但是對分類損失,使用交叉熵更合理,而且在求導時不會有MSE的梯度彌散問題。

別忘了在計算前,要將網路輸出的3組值通過換軸和reshape變成和標籤一致:

( ( 3 × ( 5 + C ) ) , f e a t u r e , f e a t u r e ) ((3×(5+C)),feature,feature) ((3×(5+C)),feature,feature)
− > ( f e a t u r e , f e a t u r e , ( 3 × ( 5 + C ) ) ) ->(feature,feature,(3×(5+C))) >(feature,feature,(3×(5+C)))
− > ( f e a t u r e , f e a t u r e , 3 , 5 + C ) ->(feature,feature,3,5+C) >(feature,feature,3,5+C)

我一開始覺得,網路輸出的值本身是沒有任何含義的,只要和標籤對應上就行,所以輸出可以直接reshape,沒必要加一步換軸操作。後來經過思考和實驗發現不是這樣,2個feature維度是通過下采樣得到的特徵尺寸,不能被reshape破壞,否則下采樣和特徵融合就沒意義了。

預測

流程:

  1. 將網路輸出reshape。
  2. 置信度經sigmoid函式後,根據給定閾值篩選,大於閾值的作為預測目標留下。
  3. 根據公式反算bounding box的座標值。
  4. 預測出的同一種類別的邊框進行NMS(非極大值抑制)。
  5. 在原圖上畫出邊框,輸出預測類別。

座標反算:

mask = torch.sigmoid(output[..., 0]) > thresh
idxs = mask.nonzero()
vecs = output[mask]

根據置信度篩選得到滿足條件的特徵圖座標idxs和對應向量vecs。

設共檢測到n的物體。
idxs的shape為 ( n , 4 ) (n,4) (n,4),4個值為 ( N , H , W , 3 ) (N,H,W,3) (N,H,W,3),分別表示第幾張圖片、物體中心點所在grid cell座標 c y , c x c_y,c_x cy,cx(注意變換)、第幾個anchor。
vecs的shape為 ( n , 5 + C ) (n,5+C) (n,5+C) 5 + C 5+C 5+C含義同上。
在這裡插入圖片描述
b x , b y , b w , b h b_x,b_y,b_w,b_h bx,by,bw,bh為bounding box的中心點和寬高;
σ \sigma σ為sigmoid函式;
c x , c y c_x,c_y cx,cy為當前grid cell在特徵圖中的座標;
p w , p h p_w,p_h pw,ph為anchor的寬高;
t x , t y , t w , t h t_x,t_y,t_w,t_h tx,ty,tw,th為vecs中的第2到第5個值。

接下來找到每個物體對應的anchor尺寸,按照公式反算即可,沒有太難的地方。

閒言

YOLOv4、v5嘛,其中技巧太多,我現在理解還不透徹,就不獻醜,之後有機會再補上。

YOLOv3作者在論文最後探討了一下YOLO的意義,許多人選擇忽視甚至翻譯都跳過了。私以為作者的表達極客且活潑,我向來不覺得程式和文學或藝術是矛盾的。人需要理性的技術,也需要敏感的心。作者對YOLO侵犯隱私和傷害生命的用途表達了抗議和愧疚,直至在YOLOv4誕生前夕選擇退出CV界。

雙刃恆存,不予置評。
技術不會停止,關於技術的思考也不會。

文章難免有錯漏之處,敬請指正。

相關文章