Pytorch VOC2012(Faster RCNN)

本篇文章介紹了Faster RCNN的基本原理和思路,參考地址爲知乎

Faster RCNN基本結構

經過R-CNN和Fast RCNN的積澱,Ross B. Girshick在2016年提出了新的Faster RCNN,在結構上,Faster RCNN已經將特徵抽取(feature extraction),proposal提取,bounding box regression(rect refine),classification都整合在了一個網絡中,使得綜合性能有較大提高,在檢測速度方面尤爲明顯。

依作者看來,如圖1,Faster RCNN其實可以分爲4個主要內容:

圖1 Faster RCNN基本結構(來自原論文)
  1. Conv layers。作爲一種CNN網絡目標檢測方法,Faster RCNN首先使用一組基礎的conv+relu+pooling層提取image的feature maps。該feature maps被共享用於後續RPN層和全連接層。
  2. Region Proposal Networks。RPN網絡用於生成region proposals。該層通過softmax判斷anchors屬於positive或者negative,再利用bounding box regression修正anchors獲得精確的proposals。
  3. Roi Pooling。該層收集輸入的feature maps和proposals,綜合這些信息後提取proposal feature maps,送入後續全連接層判定目標類別。
  4. Classification。利用proposal feature maps計算proposal的類別,同時再次bounding box regression獲得檢測框最終的精確位置。

所以本文以上述4個內容作爲切入點介紹Faster R-CNN網絡。

圖2展示了python版本中的VGG16模型中的網絡結構,可以清晰的看到該網絡對於一副任意大小PxQ的圖像,首先縮放至固定大小MxN,然後將MxN圖像送入網絡

  1. Conv layers中包含了13個conv層+13個relu層+4個pooling層(其實就是VGG16的網絡結構);
  2. RPN網絡首先經過3x3卷積,再分別生成positive anchors和對應bounding box regression偏移量,然後計算出proposals;
  3. Roi Pooling層則利用proposals從feature maps中提取proposal feature送入後續全連接和softmax網絡作classification
  4. classification分類proposal到底是什麼類別,同時再次bounding box regression獲得檢測框最終的精確位置。
圖2 Faster RCNN具體網絡結構

注:
本文不會討論任何關於R-CNN家族的歷史,分析清楚最新的Faster R-CNN就夠了,並不需要追溯到那麼久。實話說我也不瞭解R-CNN,更不關心。有空不如看看新算法。

1 Conv layers

Conv layers包含了conv,pooling,relu三種層。以python版本中的VGG16模型中的網絡結構爲例(如圖3),Conv layers部分共有13個conv層,13個relu層,4個pooling層(如圖4)。

圖3 VGG網絡結構
圖4 VGG 11/13/16/19具體網絡結構

這裏有一個非常容易被忽略但是又無比重要的信息,在Conv layers中:

  1. 所有的conv層都是:kernel_size=3,pad=1,stride=1,所以conv層不改變輸入和輸出矩陣大小;
  2. 所有的pooling層都是:kernel_size=2,pad=0,stride=2 ,所以這樣每個經過pooling層的MxN矩陣,都會變爲(M/2)x(N/2)大小

總結:conv和relu層不改變輸入輸出大小,只有pooling層使輸出長寬都變爲輸入的1/2。那麼,一個MxN大小的矩陣經過Conv layers固定變爲(M/16)x(N/16)!這樣Conv layers生成的feature map中都可以和原圖對應起來。

2 Region Proposal Networks(RPN)

經典的檢測方法生成檢測框都非常耗時,如OpenCV adaboost使用滑動窗口+圖像金字塔生成檢測框;或如R-CNN使用SS(Selective Search)方法生成檢測框。而Faster RCNN則拋棄了傳統的滑動窗口和SS方法,直接使用RPN生成檢測框,這也是Faster R-CNN的巨大優勢,能極大提升檢測框的生成速度。

圖5 RPN網絡結構

RPN部分的輸入、輸出如下:

  • 輸入:feature map、物體標籤,即訓練集中所有物體的類別與邊框位置。
  • 輸出:Proposal、分類Loss、迴歸Loss,其中,Proposal作爲生成的區域,供後續模塊分類與迴歸。兩部分損失用作優化網絡。

2.1 Anchors

理解Anchor是理解RPN乃至Faster RCNN的關鍵。Faster RCNN先提供一些先驗的邊框,然後再去篩選與修正,這樣在Anchor的基礎上做物體檢測要比從無到有的直接擬合物體的邊框容易一些。

Anchor的本質是在原圖大小上的一系列的矩形框,但Faster RCNN將這一系列的矩形框和feature map進行了關聯。具體做法是,首先對feature map進行3×3的卷積操作,得到的每一個點的維度是512維,這512維的數據對應着原始圖片上的很多不同的大小與寬高區域的特徵,這些區域的中心點都相同。如果下採樣率爲默認的16,則每一個點的座標乘以16即可得到對應的原圖座標。

爲適應不同物體的大小與寬高,在作者的論文中,默認在每一個點上抽取了9種Anchors,具體Scale爲{8,16,32},Ratio爲{0.5,1,2},將這9種Anchors的大小反算到原圖上,即得到不同的原始Proposal,如圖6所示。而後通過分類網絡與迴歸網絡得到每一個Anchor的前景背景概率和偏移量,前景背景概率用來判斷Anchor是前景的概率,迴歸網絡則是將預測偏移量作用到Anchor上使得Anchor更接近於真實物體座標。

圖6 Anchors示意圖

那麼這9個anchors是做什麼的呢?借用Faster RCNN論文中的原圖,如圖7,遍歷Conv layers計算獲得的feature maps,爲每一個點都配備這9種anchors作爲初始的檢測框。這樣做獲得檢測框很不準確,不用擔心,後面還有2次迴歸可以修正檢測框位置。

圖7 anchors示意圖

解釋一下上面這張圖的數字。

  1. 在原文中使用的是ZF Net(ILSVRC2013分類任務的冠軍,使用反捲積對CNN的中間特徵圖進行可視化分析,通過分析特徵行爲找到提升模型的辦法,微調Alexnet提升了表現。)其Conv Layers中最後的conv5層num_output=256,對應生成256張特徵圖,所以相當於feature map每個點都是256-dimensions
  2. 在conv5之後,做了rpn_conv/3x3卷積且num_output=256,相當於每個點又融合了周圍3x3的空間信息(猜測這樣做也許更魯棒?反正我沒測試),同時256-d不變(如圖4和圖7中的紅框)
  3. 假設在conv5 feature map中每個點上有k個anchor(默認k=9),而每個anhcor要分前景和背景,所以每個點由256d feature轉化爲cls=2k scores(二分類嘛);而每個anchor都有(x, y, w, h)對應4個偏移量,所以reg=4k coordinates(迴歸的四個值)
  4. 補充一點,全部anchors拿去訓練太多了,訓練程序會在合適的anchors中隨機選取128個postive anchors+128個negative anchors進行訓練(後面再說)

注意,在本文講解中使用的VGG conv5 num_output=512,所以是512d,其他類似

言歸正傳,其實RPN最終就是在原圖尺度上,設置了密密麻麻的候選Anchor。然後用cnn去判斷哪些Anchor是裏面有目標的前景,哪些是沒目標的背景。所以,僅僅是個二分類而已

那麼Anchor一共有多少個?原圖800x600,VGG下采樣16倍,feature map每個點設置9個Anchor,所以:

ceil(600/16)ceil(800/16)9=37509=16650ceil(600/16) * ceil(800/16) * 9 = 37 * 50 * 9 = 16650

其中ceil()表示向上取整,是因爲VGG輸出的feature map size= 37*50。

圖8 生成的Anchors

2.2 RPN的真值與預測量

理解RPN的預測量與真值分別是什麼,也是理解RPN原理的關鍵。對於物體檢測任務來講,模型需要預測每一個物體的類別及其出現的位置,即類別、中心點座標x與y、寬w與高h這5個量。由於有了Anchor這個先驗框,RPN可以預測Anchor的類別作爲預測邊框的類別,並且可以預測真實的邊框相對於Anchor的偏移量,而不是直接預測邊框的中心點座標x與y、寬高w與h。

舉個例子,如圖9所示,輸入圖像中有3個Anchors與兩個標籤,從位置來看,Anchor A、C分別和標籤M、N有一定的重疊,而Anchor B位置更像是背景。

圖9 圖像中Anchor與標籤的關係

首先介紹模型的真值。對於類別的真值,由於RPN只負責區域生成,保證recall,而沒必要細分每一個區域屬於哪一個類別,因此只需要前景與背景兩個類別(二分類),前景即有物體,背景則沒有物體。

RPN通過計算Anchor與標籤的IoU來判斷一個Anchor是屬於前景還是背景。IoU的含義是兩個框的公共部分佔所有部分的比例,即重合比例。在圖9中,Anchor A與標籤M的IoU計算公式如式如下:

IoU(A,M)=AMAM\operatorname{IoU}(A, M)=\frac{A \cap M}{A \cup M}

當IoU大於一定值時,該Anchor的真值爲前景,低於一定值時,該Anchor的真值爲背景。

然後是偏移量的真值。如圖10所示綠色框爲飛機的Ground Truth(GT),紅色爲提取的positive anchors,即便紅色的框被分類器識別爲飛機,但是由於紅色的框定位不準,這張圖相當於沒有正確的檢測出飛機。所以我們希望採用一種方法對紅色的框進行微調,使得positive anchors和GT更加接近。

圖10

對於窗口一般使用四維向量 (x,y,w,hx,y,w,h)表示,分別表示窗口的中心點座標和寬高。對於圖 11,紅色的框A代表原始的positive Anchors,綠色的框G代表目標的GT,我們的目標是尋找一種關係,使得輸入原始的anchor A經過映射得到一個跟真實窗口G更接近的迴歸窗口G’,即:

  • 給定anchor A=(Ax,Ay,Aw,Ah)A = (A_x , A_y , A_w , A_h)GT=(Gx,Gy,Gw,Gh)GT = (G_x , G_y , G_w , G_h)
  • 尋找一種變換F,使得:F(Ax,Ay,Aw,Ah)=(Gx,Gy,Gw,Gh)(Gx,Gy,Gw,Gh)=GTF (A_x , A_y , A_w , A_h) = (G_x' , G_y' , G_w' , G_h') ≈ (G_x , G_y , G_w , G_h) = GT
圖11

那麼經過何種變換F才能從圖11中的anchor A變爲G’呢? 比較簡單的思路就是:

  • 先做平移Gx=Awdx(A)+AxG_x' = A_w · d_x(A) + A_xGy=Ahdy(A)+AyG_y' = A_h · d_y(A) + A_y
  • 再做縮放Gw=Awexp(dw(A))G_w' = A_w · exp(d_w(A))Gh=Ahexp(dh(A))G_h' = A_h ·exp (d_h(A))

注:
其實我覺得接下來就沒必要再細講了,迴歸嘛!大家應該都是搞過機器學習的,這裏就是用的迴歸最基本的思想
。懂得就直接跳過這一節。

觀察上面4個公式發現,需要學習的是dx(A),dy(A),dw(A),,dh(A)d_x(A) , d_y(A) , d_w(A), ,d_h(A) 這四個變換。當輸入的anchor A與GT相差較小時,可以認爲這種變換是一種線性變換, 那麼就可以用線性迴歸來建模對窗口進行微調(注意,只有當anchors A和GT比較接近時,才能使用線性迴歸模型,否則就是複雜的非線性問題了)。對應於Faster RCNN原文,平移量(tx,tyt_x, t_y)與尺度因子(tw,tht_w, t_h)如下:

tx=(GxAx)Awty=(GyAy)Ahtw=ln(GyAy)Awth=ln(GyAy)Ah\begin{aligned} t_{x} &=\frac{\left(G_{x}-A_{x}\right)}{A_{w}} \\ t_{y} &=\frac{\left(G_{y}-A_{y}\right)}{A_{h}} \\ t_{w} &=\frac{\ln \left(G_{y}-A_{y}\right)}{A_{w}} \\ t_{h} &=\frac{\ln \left(G_{y}-A_{y}\right)}{A_{h}} \end{aligned}

接下來的問題就是如何通過線性迴歸獲得dx(A),dy(A),dw(A),,dh(A)d_x(A) , d_y(A) , d_w(A), ,d_h(A) 了。

2.3 RPN卷積網絡

爲了實現上述的預測,RPN搭建瞭如圖5、圖12所示的網絡結構。具體實現時,在feature map上首先用3×3的卷積進行更深的特徵提取,然後利用1×1的卷積分別實現分類網絡和迴歸網絡。

圖5 RPN網絡結構
圖12 RPN網絡計算流程

在物體檢測中,通常我們將有物體的位置稱爲前景,沒有物體的位置稱爲背景。在分類網絡分支中,首先使用1×1卷積輸出18×37×50的特徵,由於每個點默認有9個Anchors,並且每個Anchor只預測其屬於前景還是背景,因此通道數爲18。隨後利用torch.view()函數將特徵映射到2×333(9*37)×50,這樣第一維僅僅是一個Anchor的前景背景得分,並送到Softmax函數中進行概率計算,得到的特徵再變換到18×37×50的維度,最終輸出的是每個Anchor屬於前景與背景的概率。

在迴歸分支中,利用1×1卷積輸出36×37×50的特徵,第一維的36包含9個Anchors的預測,每一個Anchor有4個數據,分別代表了每一個Anchor的中心點橫縱座標及寬高這4個量相對於真值的偏移量。

2.4 RPN真值的求取

上一節的RPN分類與迴歸網絡得到的是模型的預測值,而爲了計算預測的損失,還需要得到分類與偏移預測的真值,具體指的是每一個Anchor是否對應着真實物體,以及每一個Anchor對應物體的真實偏移值。求真值的具體實現過程如圖13所示,主要包含4步,下面具體介紹。

圖13 RPN真值求取過程

1. Anchor生成

這部分與前面Anchor的生成過程一樣,可以得到37×50×9=16650個Anchors。由於按照這種方式生成的Anchor會有一些邊界在圖像邊框外,因此還需要把這部分超過圖像邊框的Anchors過濾掉。

2. Anchor與標籤的匹配
爲了計算Anchor的損失,在生成Anchor之後,我們還需要得到每個Anchor的類別,由於RPN的作用是建議框生成,而非詳細的分類,因此只需要區分正樣本與負樣本,即每個Anchor是屬於正樣本還是負樣本。前面已經介紹了通過計算Anchor與標籤的IoU來判斷是正樣本還是負樣本。在具體實現時,需要計算每一個Anchor與每一個標籤的IoU,因此會得到一個IoU矩陣,具體的判斷標準如下:

  1. 對於任何一個Anchor,與所有標籤的最大IoU小於0.3,則視爲負樣本。
  2. 對於任何一個標籤,與其有最大IoU的Anchor視爲正樣本。
  3. 對於任何一個Anchor,與所有標籤的最大IoU大於0.7,則視爲正樣本。

需要注意的是,上述三者的順序不能隨意變動,要保證一個Anchor既符合正樣本,也符合負樣本時,賦予正樣本。並且爲了保證這一階段的召回率,允許多個Anchors對應一個標籤,而不允許一個標籤對應多個Anchors。

3. Anchor的篩選
由於Anchor的總數量接近於2萬,並且大部分Anchor的標籤都是背景,如果都計算損失的話則正、負樣本失去了均衡,不利於網絡的收斂。在此,RPN默認選擇256個Anchors進行損失的計算,其中最多不超過128個的正樣本。如果數量超過了限定值,則進行隨機選取。當然,這裏的256與128都可以根據實際情況進行調整,而不是固定死的。

4. 求解迴歸偏移真值

上一步將每個Anchor賦予正樣本或者負樣本代表了預測類別的真值,而回歸部分的偏移量真值還需要利用Anchor與對應的標籤求解得到,具體公式見式:
tx=(GxAx)Awty=(GyAy)Ahtw=ln(GyAy)Awth=ln(GyAy)Ah\begin{aligned} t_{x} &=\frac{\left(G_{x}-A_{x}\right)}{A_{w}} \\ t_{y} &=\frac{\left(G_{y}-A_{y}\right)}{A_{h}} \\ t_{w} &=\frac{\ln \left(G_{y}-A_{y}\right)}{A_{w}} \\ t_{h} &=\frac{\ln \left(G_{y}-A_{y}\right)}{A_{h}} \end{aligned}

得到偏移量的真值後,將其保存在bbox_targets中。與此同時,還需要求解兩個權值矩陣bbox_inside_weights和bbox_outside_weights,前者是用來設置正樣本回歸的權重,正樣本設置爲1,負樣本設置爲0,因爲負樣本對應的是背景,不需要進行迴歸;後者的作用則是平衡RPN分類損失與迴歸損失的權重,在此設置爲1/256。

2.5 損失函數的計算

有了網絡預測值與真值,接下來就可以計算損失了。RPN的損失函數包含分類與迴歸兩部分。
L({Pi},{ti})=1NclsiLcls(pi,pi)+λ1NregiPiLreg(ti,ti)L\left(\left\{P_{i}\right\},\left\{t_{i}\right\}\right)=\frac{1}{N_{c{l s}}} \sum_{i} L_{c{l s}}\left(p_{i}, p_{i}^{*}\right)+\lambda \frac{1}{N_{r e g}} \sum_{i} P_{i}^{*} L_{r{e g}}\left(t_{i}, t_{i}^{*}\right)

ΣiLcls(pi,pi)Σ_{i} L_{c{l s}}(p_{i}, p_{i}^{*})代表了256個篩選出的Anchors的分類損失,PiP_i爲每一個Anchor的類別真值,pip^*_i爲每一個Anchor的預測類別。由於RPN的作用是選擇出Proposal,並不要求細分出是哪一類前景,因此在這一階段是二分類,使用的是交叉熵損失。值得注意的是,在F.cross_entropy()函數中集成了Softmax的操作,因此應該傳入得分,而非經過Softmax之後的預測值。

iPiLreg(ti,ti)\sum_{i} P_{i}^{*} L_{reg}\left(t_{i}, t_{i}^{*}\right)代表了迴歸損失。迴歸損失使用了smoothL1smooth_{L1}函數。
Lreg(ti,ti)=ix,y,w,hsmoothL1(titi)smoothL1(x)={0.5x2 if x<1x0.5 otherwise \begin{aligned} &L_{r e g}\left(t_{i}, t_{i}^{*}\right)=\sum_{i \in x, y, w, h} \operatorname{smooth}_{L 1}\left(t_{i}-t_{i}^{*}\right)\\ &\text {smooth}_{L 1}(x)=\left\{\begin{array}{ll} 0.5 x^{2} & \text { if }|x|<1 \\ |x|-0.5 & \text { otherwise } \end{array}\right. \end{aligned}

smoothL1smooth_{L1}函數結合了1階與2階損失函數,原因在於,當預測偏移量與真值差距較大時,使用2階函數時導數太大,模型容易發散而不容易收斂,因此在大於1時採用了導數較小的1階損失函數。

2.6 NMS與生成Proposal

完成了損失的計算,RPN的另一個功能就是區域生成,即生成較好的Proposal,以供下一個階段進行細分類與迴歸。NMS生成Proposal的主要過程如圖14所示。

圖14 RPN生成Proposal的過程

Proposal Layer forward 按照以下順序依次處理:

首先生成大小固定的全部Anchors,然後將網絡中得到的迴歸偏移作用到Anchor上使Anchor更加貼近於真值,並修剪超出圖像尺寸的Proposal,得到最初的建議區域。在這之後,按照分類網絡輸出的得分對Anchor排序,保留前12000個得分高的Anchors。由於一個物體可能會有多個Anchors重疊對應,因此再應用非極大值抑制(NMS)將重疊的框去掉,最後在剩餘的Proposal中再次根據RPN的預測得分選擇前2000個,作爲最終的Proposal,輸出到下一個階段。

2.7 篩選Proposal得到RoI

在訓練時,上一步生成的Proposal數量爲2000個,其中仍然有很多背景框,真正包含物體的仍佔少數,因此完全可以針對Proposal進行再一步篩選,過程與RPN中篩選Anchor的過程類似,利用標籤與Proposal構建IoU矩陣,通過與標籤的重合程度選出256個正負樣本。

這一步有3個作用:

  1. 篩選出了更貼近真實物體的RoI,使送入到後續網絡的物體正、負樣本更均衡,避免了負樣本過多,正樣本過少的情況。
  2. 減少了送入後續全連接網絡的數量,有效減少了計算量。
  3. 篩選Proposal得到RoI的過程中,由於使用了標籤來篩選,因此也爲每一個RoI賦予了正、負樣本的標籤,同時可以在此求得RoI變換到對應標籤的偏移量,這樣就求得了RCNN部分的真值。

具體實現時,首先計算Proposal與所有的物體標籤的IoU矩陣,然後根據IoU矩陣的值來篩選出符合條件的正負樣本。

篩選標準如下:

  1. 對於任何一個Proposal,其與所有標籤的最大IoU如果大於等於0.5,則視爲正樣本。
  2. 對於任何一個Proposal,其與所有標籤的最大IoU如果大於等於0且小於0.5,則視爲負樣本。

經過上述標準的篩選,選出的正、負樣本數量不一,在此設定正、負樣本的總數爲256個,其中正樣本的數量爲p個。爲了控制正、負樣本的比例基本滿足1:3,在此正樣本數量p不超過64,如果超過了64則從正樣本中隨機選取64個。剩餘的數量256-p爲負樣本的數量,如果超過了256-p則從負樣本中隨機選取256-p個。

經過上述操作後,選出了最終的256個RoI,並且每一個RoI都賦予了正樣本或者負樣本的標籤。在此也可以進一步求得每一個RoI的真值,即屬於哪一個類別及對應真值物體的偏移量。

3 RoI pooling層

上述步驟得到了256個RoI,以及每一個RoI對應的類別與偏移量真值,爲了計算損失,還需要計算每一個RoI的預測量。

前面的VGGNet網絡已經提供了整張圖像的feature map,因此自然聯想到可以利用此feature map,將每一個RoI區域對應的特徵提取出來,然後接入一個全連接網絡,分別預測其RoI的分類與偏移量。

然而,由於RoI是由各種大小寬高不同的Anchors經過偏移修正、篩選等過程生成的,因此其大小不一且帶有浮點數,然而後續相連的全連接網絡要求輸入特徵大小維度固定,這就需要有一個模塊,能夠把各種維度不同的RoI變換到維度相同的特徵,以滿足後續全連接網絡的要求,於是RoI Pooling就產生了。

對RoI進行池化的思想在SPPNet中就已經出現了,只不過在Fast RCNN中提出的RoI Pooling算法利用最近鄰差值算法將池化過程進行了簡化,而在隨後的Mask RCNN中進一步提出了RoI Align的算法,利用雙線性插值,進一步提升了算法精度。

圖2 RoI pooling

在此我們舉一個例子來講解這幾種算法的思想,假設當前RoI大小爲332×332,使用VGGNet的全連接層,其所需的特徵向量維度爲512×7×7,由於目前的特徵圖通道數爲512,Pooling的過程就是如何獲得7×7大小區域的特徵。

3.1 RoI Pooling簡介

RoI Pooling的實現過程如圖15所示,假設當前的RoI爲圖4.9中左側圖像的邊框,大小爲332×332,爲了得到這個RoI的特徵圖,首先需要將該區域映射到全圖的特徵圖上,由於下採樣率爲16,因此該區域在特徵圖上的座標直接除以16並取整,而對應的大小爲332/16=20.75。在此,RoI Pooling的做法是直接將浮點數量化爲整數,取整爲20×20,也就得到了該RoI的特徵,即圖15中第3步的邊框。

圖2 RoI pooling的實現過程示例

3.2

4 Classification

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章