像玩樂高一樣拆解Faster R-CNN:詳解目標檢測的實現過程

機器之心發表於2018-02-23
  • Luminoth 實現:https://github.com/tryolabs/luminoth/tree/master/luminoth/models/fasterrcnn


  • 在閱讀本文之前,若想了解 R-CNN 網路家族的發展,可以參看機器之心的文章:


    深度 | 用於影象分割的卷積神經網路:從R-CNN到Mark R-CNN


    去年,我們決定深入瞭解 Faster R-CNN,閱讀原始論文以及其中引用到的其他論文,現在我們對其工作方式和實現方法有了清晰的理解。


    我們最終在 Luminoth 中實現了 Faster R-CNN,Luminoth 是基於 TensorFlow 的計算機視覺工具包,易於訓練和監控,支援多種不同的模型。到目前為止,Luminoth 已經吸引了很大的關注,我們在 ODSC Europe 和 ODSC West 的論壇中也介紹過這個專案。

    (ODSC,Open Data Science Conference,專注於開源資料科學的會議)。


    基於開發 Luminoth 的工作和過去的報告,我們認為把所有實現 Faster RCNN 的細節和相關連結整合到一篇部落格中是一個不錯的點子,這對未來其他對此領域感興趣的人會很有意義。


    背景


    Faster R-CNN 最早在 2015 年的 NIPS 釋出。其在釋出後經歷了幾次修改,這在之後博文中會有討論。Faster-RCNN 是 RCNN 系列論文的第三次迭代,這一系列論文的一作和聯合作者是 Ross Girshick。


    這一切始於 2014 年的一篇論文「Rich feature hierarchies for accurate object detection and semantic segmentation」(R-CNN),其使用了稱為 Selective Search 的演算法用來提取感興趣候選區域,並用一個標準的卷積神經網路 (CNN) 去分類和調整這些區域。Fast R-CNN 從 R-CNN 演變優化而來,Fast R-CNN 釋出於 2015 年上半年,其中一種稱為感興趣區域池化的技術,使得網路可以共享計算結果,從而讓模型提速。這一系列演算法最終被優化為 Faster R-CNN,這是第一個完全可微分的模型。


    框架


    Faster R-CNN 的框架由幾個模組部件組成,所以其框架有些複雜。我們將從高層次的概述開始,之後會介紹不同組成部分的具體細節。


    從一張圖片開始,我們將會得到:


  • 一個邊框列表

  • 每個邊框會被分配一個標籤

  • 每對標籤和邊框所對應的概率

  • 像玩樂高一樣拆解Faster R-CNN:詳解目標檢測的實現過程


    完整的 Faster R-CNN 框架


    輸入的圖片以長×寬×高的張量形式表徵,之後會被饋送入預訓練好的卷積神經網路,在中間層得到特徵圖。使用該特徵圖作為特徵提取器並用於下一流程。


    上述方法在遷移學習中經常使用,尤其在為小資料集訓練分類器時,其通常取用了在另一個較大資料集訓練好的權重。我們在下一章節會深入瞭解這個部分。接著,我們會使用到區域建議網路(Region Proposal Network,RPN)。使用 CNN 計算得到的特徵,去尋找到預設好數量的可能包含目標的區域 (邊框)。


    使用深度學習進行目標檢測最大的困難可能是生成一個長度可變的邊框列表。使用深度神經網路建模時,模型最後一部分通常是一個固定尺寸的張量輸出(除了迴圈神經網路)。例如,在圖片分類中,輸出是 (N,) 形狀的張量,N 是類別的數量,其中在第 i 個位置標量含有該圖片屬於類別 i 的概率。


    RPN 中長度可變列表的問題可以使用錨點解決:使用固定尺寸的參考邊框在原始圖片上一致地定位。不是直接探測目標在哪,而是把問題分兩個方面建模,對每個錨點,我們考慮:


  • 這個錨點包含相關目標嗎?

  • 如何調整錨點以更好的擬合到相關目標?


  • 可能會有點困擾,但是沒關係,下面會深入瞭解。


    在取得一系列的相關目標和其在原始圖片上的位置後,目標探測問題就可以相對直觀地解決了。使用 CNN 提取到的特徵和相關目標的邊框,我們在相關目標的特徵圖上使用感興趣區域池化 (RoI Pooling),並將與目標相關的特徵資訊存入一個新的張量。之後的流程與 R-CNN 模型一致,利用這些資訊:


  • 對邊框內的內容分類(或者捨棄它,並用「背景」標記邊框內容)

  • 調整邊框的座標(使之更好地包含目標)


  • 顯然,這樣做會遺失掉部分資訊,但這正是 Faster-RCNN 如何進行目標探測的基本思想。下一步,我們會仔細討論框架、損失函式以及訓練過程中各個元件的具體細節。


    基礎網路


    之前提到過,Faster R-CNN 第一步要使用在圖片分類任務 (例如,ImageNet) 上預訓練好的卷積神經網路,使用該網路得到的中間層特徵的輸出。這對有深度學習背景的人來說很簡單,但是理解如何使用和為什麼這樣做才是關鍵,同時,視覺化中間層的特徵輸出也很重要。沒有一致的意見表明哪個網路框架是最好的。原始的 Faster R-CNN 使用的是在 ImageNet 上預訓練的 ZF 和 VGG,但之後出現了很多不同的網路,且不同網路的引數數量變化很大。例如,MobileNet,以速度優先的一個小型的高效框架,大約有 330 萬個引數,而 ResNet-152(152 層),曾經的 ImageNet 圖片分類競賽優勝者,大約有 6000 萬個引數。最新的網路結構如 DenseNet,可以在提高準確度的同時縮減引數數量。


    VGG


    在討論網路結構孰優孰劣之前,讓我們先以 VGG-16 為例來嘗試理解 Faster-RCNN 是如何工作的。


    像玩樂高一樣拆解Faster R-CNN:詳解目標檢測的實現過程

    VGG 網路結構


    VGG,其名字來自於在 ImageNet ILSVRC 2014 競賽中使用此網路的小組組名,首次釋出於論文」Very Deep Convolutional Networks for Large-Scale Image Recognition」, 作者是 Karen Simonyan 和 Andrew Zisserman。以今天的標準來看這個網路談不上深度,但是在釋出之際 VGG16 比當時常用的網路要多一倍的層數,其推動了「深度 → 更強大效能 → 更好結果」的浪潮(只要訓練是可行的)。


    當使用 VGG 進行分類任務時,其輸入是 224×224×3 的張量 (表示一個 224×224 畫素大小的 RGB 圖片)。在分類任務中輸入圖片的尺寸是固定的,因為網路最後一部分的全連線層需要固定長度的輸入。在接入全連線層前,通常要將最後一層卷積的輸出展開成一維張量。


    因為要使用卷積網路中間層的輸出,所以輸入圖片的尺寸不再有限制。至少,在這個模組中不再是問題,因為只有卷積層參與計算。讓我們深入瞭解一下底層的細節,看看具體要使用哪一層卷積網路的輸出。Faster R-CNN 論文中沒有具體指定使用哪一層;但是在官方的實現中可以觀察到,作者使用的是 conv5/conv5_1 這一層 (caffe 程式碼)。


    每一層卷積網路都在前一層的資訊基礎上提取更加抽象的特徵。第一層通常學習到簡單的邊緣,第二層尋找目標邊緣的模式,以啟用後續卷積網路中更加複雜的形狀。最終,我們得到一個在空間維度上比原始圖片小很多,但表徵更深的卷積特徵圖。特徵圖的長和寬會隨著卷積層間的池化而縮小,深度會隨著卷積層濾波器的數量而增加。

    像玩樂高一樣拆解Faster R-CNN:詳解目標檢測的實現過程

    從圖片到卷積特徵圖


    卷積特徵圖將圖片的所有資訊編碼到深度的維度上,同時保留著原始圖片上目標物體的相對位置資訊。例如,如果圖片左上角有一個紅色矩形,經過卷積層的啟用,那麼紅色矩形的位置資訊仍然保留在卷積特徵圖的左上角。


    VGG vs ResNet


    如今,ResNet 已經取代大多數 VGG 網路作為提取特徵的基礎框架。Faster-RCNN 的三位聯合作者 (Kaiming He, Shaoqing Ren 和 Jian Sun) 也是論文「Deep Residual Learning for Image (https://arxiv.org/abs/1512.03385) Recognition」的作者,這篇論文最初介紹了 ResNets 這一框架。


    ResNet 對比 VGG 的優勢在於它是一個更深層、大型的網路,因此有更大的容量去學習所需要的資訊。這些結論在圖片分類任務中可行,在目標探測的問題中也應該同樣有效。


    ResNet 在使用殘差連線和批歸一化的方法後更加易於訓練,這些方法在 VGG 釋出的時候還沒有出現。


    錨點


    現在,我們將使用處理過後的特徵圖並建議目標區域,也就是用於分類任務的感興趣區域。之前提到過錨點是解決長度可變問題的一種方法,現在將詳細介紹。


    我們的目標是尋找圖片中的邊框。這些邊框是不同尺寸、不同比例的矩形。設想我們在解決問題前已知圖片中有兩個目標。那麼首先想到的應該是訓練一個網路,這個網路可以返回 8 個值:包含(xmin, ymin, xmax, ymax)的兩個元組,每個元組都用於定義一個目標的邊框座標。這個方法有著根本問題,例如,圖片可能是不同尺寸和比例的,因此訓練一個可以直接準確預測原始座標的模型是很複雜的。另一個問題是無效預測:當預測(xmin,xmax)和(ymin,ymax)時,應該強制設定 xmin 要小於 xmax,ymin 要小於 ymax。


    另一種更加簡單的方法是去預測參考邊框的偏移量。使用參考邊框(xcenter, ycenter, width, height),學習預測偏移量(Δxcenter,Δycenter,Δwidth,Δheight),因此我們只得到一些小數值的預測結果並挪動參考變數就可以達到更好的擬合結果。


    錨點是用固定的邊框置於不同尺寸和比例的圖片上,並且在之後目標位置的預測中用作參考邊框。


    我們在處理的卷積特徵圖的尺寸分別是 convwidth×convheight×convdepth,因此在卷積圖的 convwidth×convheight 上每一個點都生成一組錨點。很重要的一點是即使我們是在特徵圖上生成的錨點,這些錨點最終是要對映回原始圖片的尺寸。


    因為我們只用到了卷積和池化層,所以特徵圖的最終維度與原始圖片是呈比例的。數學上,如果圖片的尺寸是 w×h,那麼特徵圖最終會縮小到尺寸為 w/r 和 h/r,其中 r 是次級取樣率。如果我們在特徵圖上每個空間位置上都定義一個錨點,那麼最終圖片的錨點會相隔 r 個畫素,在 VGG 中,r=16。


    像玩樂高一樣拆解Faster R-CNN:詳解目標檢測的實現過程

    原始圖片的錨點中心


    為了選擇一組合適錨點,我們通常定義一組固定尺寸 (例如,64px、128px、256px,此處為邊框大小) 和比例 (例如,0.5、1、1.5,此處為邊框長寬比) 的邊框,使用這些變數的所有可能組合得到候選邊框 (這個例子中有 1 個錨點和 9 個邊框)。



    像玩樂高一樣拆解Faster R-CNN:詳解目標檢測的實現過程

    左側:錨點、中心:特徵圖空間單一錨點在原圖中的表達,右側:所有錨點在原圖中的表達


    區域建議網路

    像玩樂高一樣拆解Faster R-CNN:詳解目標檢測的實現過程

    RPN 採用卷積特徵圖並在影象上生成建議。


    像我們之前提到的那樣,RPN 接受所有的參考框(錨點)併為目標輸出一套好的建議。它通過為每個錨點提供兩個不同的輸出來完成。


    第一個輸出是錨點作為目標的概率。如果你願意,可以叫做「目標性得分」。注意,RPN 不關心目標的類別,只在意它實際上是不是一個目標(而不是背景)。我們將用這個目標性得分來過濾掉不好的預測,為第二階段做準備。第二個輸出是邊框迴歸,用於調整錨點以更好的擬合其預測的目標。


    RPN 是用完全卷積的方式高效實現的,用基礎網路返回的卷積特徵圖作為輸入。首先,我們使用一個有 512 個通道和 3x3 卷積核大小的卷積層,然後我們有兩個使用 1x1 卷積核的並行卷積層,其通道數量取決於每個點的錨點數量。

    像玩樂高一樣拆解Faster R-CNN:詳解目標檢測的實現過程

    RPN 架構的卷積實現,其中 k 是錨點的數量。


    對於分類層,我們對每個錨點輸出兩個預測值:它是背景(不是目標)的分數,和它是前景(實際的目標)的分數。


    對於迴歸或邊框調整層,我們輸出四個預測值:Δxcenter、Δycenter、Δwidth、Δheight,我們將會把這些值用到錨點中來得到最終的建議。


    使用最終的建議座標和它們的目標性得分,然後可以得到一套很好的對於目標的建議。


    訓練、目標和損失函式


    RPN 執行兩種不同型別的預測:二進位制分類和邊框迴歸調整。為了訓練,我們把所有的錨點分成兩類。一類是「前景」,它與真實目標重疊並且其 IoU(Intersection of Union)值大於 0.5;另一類是「背景」,它不與任何真實目標重疊或與真實目標的 IoU 值 小於 0.1。


    然後,我們對這些錨點隨機取樣,構成大小為 256 的 mini batch——維持前景錨點和背景錨點之間的平衡比例。


    RPN 用所有以 mini batch 篩選出來的錨點和二進位制交叉熵(binary cross entropy)來計算分類損失。然後它只用那些標記為前景的 mini batch 錨點來計算迴歸損失。為了計算迴歸的目標,我們使用前景錨點和最接近的真實目標,並計算將錨點轉化為目標所需的正確 Δ。


    論文中建議使用 Smooth L1 loss 來計算迴歸誤差,而不是用簡單的 L1 或 L2 loss。Smooth L1 基本上就是 L1,但是當 L1 的誤差足夠小,由確定的 σ 定義時,可以認為誤差幾乎是正確的且損失以更快的速率減小。


    使用 dynamic batches 是具有挑戰性的,這裡的原因很多。即使我們試圖維持前景錨點和背景錨點之間的平衡比例,但這並不總是可能的。根據影象上的真實目標以及錨點的大小和比例,可能會得到零前景錨點。在這種情況下,我們轉而使用對於真實框具有最大 IoU 值的錨點。這遠非理想情況,但是為了總是有前景樣本和目標可以學習,這還是挺實用的。


    後處理


    非極大抑制(Non-maximum suppression):由於錨點經常重疊,因此建議最終也會在同一個目標上重疊。為了解決重複建議的問題,我們使用一個簡單的演算法,稱為非極大抑制(NMS)。NMS 獲取按照分數排序的建議列表並對已排序的列表進行迭代,丟棄那些 IoU 值大於某個預定義閾值的建議,並提出一個具有更高分數的建議。


    雖然這看起來很簡單,但對 IoU 的閾值設定一定要非常小心。太低,你可能會丟失對目標的建議;太高,你可能會得到對同一個目標的很多建議。常用值是 0.6。


    建議選擇:應用 NMS 後,我們保留評分最高的 N 個建議。論文中使用 N=2000,但是將這個數字降低到 50 仍然可以得到相當好的結果。


    獨立應用程式


    RPN 可以獨立使用,而不需要第二階段的模型。在只有一類物件的問題中,目標性概率可以用作最終的類別概率。這是因為在這種情況下,「前景」=「目標類別」以及「背景」=「不是目標類別」。


    一些從獨立使用 RPN 中受益的機器學習問題的例子包括流行的(但仍然是具有挑戰性的)人臉檢測和文字檢測。


    僅使用 RPN 的優點之一是訓練和預測的速度都有所提高。由於 RPN 是一個非常簡單的僅使用卷積層的網路,所以預測時間比使用分類基礎網路更快。


    興趣區域池化


    在 RPN 步驟之後,我們有很多沒有分配類別的目標建議。我們接下來要解決的問題就是如何將這些邊框分類到我們想要的類別中。


    最簡單的方法是採用每個建議,裁剪出來,然後讓它通過預訓練的基礎網路。然後,我們可以用提取的特徵作為基礎影象分類器的輸入。這種方法的主要問題是執行所有 2000 個建議的計算效率和速度都是非常低的。


    Faster R-CNN 試圖通過複用現有的卷積特徵圖來解決或至少緩解這個問題。這是通過用興趣區域池化為每個建議提取固定大小的特徵圖實現的。R-CNN 需要固定大小的特徵圖,以便將它們分類到固定數量的類別中。

    像玩樂高一樣拆解Faster R-CNN:詳解目標檢測的實現過程

    興趣區域池化


    一種更簡單的方法(被包括 Luminoth 版本的 Faster R-CNN 在內的目標檢測實現方法所廣泛使用),是用每個建議來裁剪卷積特徵圖,然後用插值(通常是雙線性的)將每個裁剪調整為固定大小(14×14×convdepth)。裁剪之後,用 2x2 核大小的最大池化來獲得每個建議最終的 7×7×convdepth 特徵圖。

    選擇這些確切形狀的原因與下一模組(R-CNN)如何使用它有關,這些設定是根據第二階段的用途得到的。

    基於區域的卷積神經網路

    基於區域的卷積神經網路(R-CNN)是 Faster R-CNN 工作流的最後一步。從影象上獲得卷積特徵圖之後,用它通過 RPN 來獲得目標建議並最終為每個建議提取特徵(通過 RoI Pooling),最後我們需要使用這些特徵進行分類。R-CNN 試圖模仿分類 CNNs 的最後階段,在這個階段用一個全連線層為每個可能的目標類輸出一個分數。

    R-CNN 有兩個不同的目標:


    1. 將建議分到一個類中,加上一個背景類(用於刪除不好的建議)。

    2. 根據預測的類別更好地調整建議的邊框。

    在最初的 Faster R-CNN 論文中,R-CNN 對每個建議採用特徵圖,將它平坦化並使用兩個大小為 4096 的有 ReLU 啟用函式的全連線層。

    然後,它對每個不同的目標使用兩種不同的全連線層:

    • 一個有 N+1 個單元的全連線層,其中 N 是類的總數,另外一個是背景類。

    • 一個有 4N 個單元的全連線層。我們希望有一個迴歸預測,因此對 N 個類別中的每一個可能的類別,我們都需要 Δcenterx、Δcentery、Δwidth、Δheight。

    像玩樂高一樣拆解Faster R-CNN:詳解目標檢測的實現過程

    R-CNN 架構

    訓練和目標


    R-CNN 的目標與 RPN 的目標的計算方法幾乎相同,但是考慮的是不同的可能類別。我們採用建議和真實邊框,並計算它們之間的 IoU。

    那些有任何真實邊框的建議,只要其 IoU 大於 0.5,都被分配給那個真實資料。那些 IoU 在 0.1 和 0.5 之間的被標記為背景。與我們在為 RPN 分配目標時相反的是,我們忽略了沒有任何交集的建議。這是因為在這個階段,我們假設已經有好的建議並且我們對解決更困難的情況更有興趣。當然,這些所有的值都是可以為了更好的擬合你想找的目標型別而做調整的超引數。

    邊框迴歸的目標是計算建議和與其對應的真實框之間的偏移量,僅針對那些基於 IoU 閾值分配了類別的建議。

    我們隨機抽樣了一個尺寸為 64 的 balanced mini batch,其中我們有高達 25% 的前景建議(有類別)和 75% 的背景。

    按照我們對 RPN 損失所做的相同處理方式,現在的分類損失是一個多類別的交叉熵損失,使用所有選定的建議和用於與真實框匹配的 25% 建議的 Smooth L1 loss。由於 R-CNN 邊框迴歸的全連線網路的輸出對於每個類都有一個預測,所以當我們得到這種損失時必須小心。在計算損失時,我們只需要考慮正確的類。

    後處理

    與 RPN 相似,我們最終得到了很多已經分配了類別的目標,在返回它們之前需要進一步處理。

    為了實施邊框調整,我們必須考慮哪個類別具有對該建議的最高概率。我們也需要忽略具有最高概率的背景類的建議。

    在得到最終目標和忽略被預測為背景的目標之後,我們應用基於類的 NMS。這通過按類進行分組完成,通過概率對其排序,然後將 NMS 應用於每個獨立的組。

    對於我們最後的目標列表,我們也可以設定一個概率閾值並且對每個類限制目標的數量。

    訓練

    在最初的論文中,Faster R-CNN 是用多步法訓練的,獨立地訓練各部分並且在應用最終的全面訓練方法之前合併訓練的權重。之後,人們發現進行端到端的聯合訓練會帶來更好的結果。

    把完整的模型放在一起後,我們得到 4 個不同的損失,兩個用於 RPN,另外兩個用於 R-CNN。我們在 RPN 和 R-CNN 中有可訓練的層,我們也有可以訓練(微調)或不能訓練的基礎網路。

    是否訓練基礎網路的決定取決於我們想要學習的目標特性和可用的計算能力。如果我們想檢測與在原始資料集(用於訓練基礎網路)上的資料相似的目標,那麼除了嘗試壓縮我們能獲得的所有可能的效能外,其他做法都是沒有必要的。另一方面,為了擬合完整的梯度,訓練基礎網路在時間和必要的硬體上都是昂貴的。

    用加權和將四種不同的損失組合起來。這是因為相對於迴歸損失,我們可能希望給分類損失更大的權重,或者相比於 RPN 可能給 R-CNN 損失更大的權重。

    除了常規的損失之外,我們也有正則化損失,為了簡潔起見,我們可以跳過這部分,但是它們在 RPN 和 R-CNN 中都可以定義。我們用 L2 正則化一些層。根據正在使用哪個基礎網路,以及如果它經過訓練,也有可能進行正則化。

    我們用隨機梯度下降的動量演算法訓練,將動量值設定為 0.9。你可以輕鬆的用其他任何優化方法訓練 Faster R-CNN,而不會遇到任何大問題。

    學習率從 0.001 開始,然後在 50K 步後下降到 0.0001。這是通常最重要的超引數之一。當用 Luminoth 訓練時,我們經常從預設值開始,並以此開始做調整。

    評估

    在一些特定的 IoU 閾值下,使用標準平均精度均值(mAP)來完成評估(例如,mAP@0.5)。mAP 是源於資訊檢索的度量標準,並且常用於計算排序問題中的誤差和評估目標檢測問題。

    我們不會深入討論細節,因為這些型別的度量標準值得用一篇完整部落格來總結,但重要的是,當你錯過了你應該檢測到的框,以及當你發現一些不存在的東西或多次檢測到相同的東西時,mAP 會對此進行懲罰。

    結論

    到目前為止,你應該清楚 Faster R-CNN 的工作方式、設計目的以及如何針對特定的情況進行調整。如果你想更深入的瞭解它的工作原理,你應該看看 Luminoth 的實現。

    Faster R-CNN 是被證明可以用相同的原理解決複雜的計算機視覺問題的模型之一,在這個新的深度學習革命剛開始的時候,它就展現出如此驚人的結果。

    目前正在建立的新模型不僅用於目標檢測,還用於基於這種原始模型的語義分割、3D 目標檢測等等。有的借用 RPN,有的借用 R-CNN,還有的建立在兩者之上。因此,充分了解底層架構非常重要,從而可以解決更加廣泛的和複雜的問題。

    原文地址: https://tryolabs.com/blog/2018/01/18/faster-r-cnn-down-the-rabbit-hole-of-modern-object-detection/

    相關文章