http://www.telesens.co/2018/03/11/object-detection-and-classification-using-r-cnns/www.telesens.co
本文參考上文,做了部分翻譯和自己的了解,歡迎交流讨論!
使用RCNN進行目标檢測和分類
經典的RCNN系列(主要是RCNN,Fast-RCNN,Faster-RCNN,Mask-RCNN),是two-stage的經典目标檢測模型。本文希望從細節上把這些模型了解清楚(Mask-RCNN的不在本文中介紹,因為Mask-RCNN主要用于分割任務,其在Faster-RCNN的基礎上做了改進)
本文主要介紹Pytorch版本的Faster-RCNN,代碼見
https://github.com/ruotianluo/pytorch-faster-rcnngithub.com
文章内容如下:
- 圖像預處理
- 網絡結構
- 實作細節:訓練
- 錨框生成層
- 區域推薦層
- 推薦層
- 錨框目标層
- 計算分類層損失
- 推薦目标層
- 裁剪池化
- 分類層
- 實作細節:推理
- 附錄
- Resnet-50網絡架構
- 非極大抑制(NMS)
圖像預處理
訓練和推理過程的預處理方法不是一樣的,需要注意這一點!
具體而言就是歸一化的均值和方法分别是所有訓練集和測試集資料的均值
和方差。
網絡架構
一個RCNN神經網絡主要解決如下兩個問題:
- 從輸入圖像中擷取感興趣區域(Region of Interest - RoI)
- 識别RoI中目标類别,主要以計算機率的方法得到
RCNN包含三個子子產品:
- Head。也稱為backbone,即骨幹網絡。
- Region Proposal Network - RPN。RoI推薦網絡,一是推薦可能存在目标的bbox,二是初步糾正anchor的坐标
- 分類網絡。對于Faster-RCNN,有兩個分支,一是分類,二是bbox回歸,糾正錨框坐标。對于Mask-RCNN,有三個分支,在Faster-RCNN的基礎上增加了與FPN類似的反卷積網絡。
對于Head,一般是在ImageNe資料集上預訓練好的CNN模型。由于預訓練模型的淺層主要是基于邊緣和顔色來作為特點,泛化能力較好。預訓練模型的深層主要與特定任務相關,泛化能力較差。是以淺層的參數在訓練的過程中保持相對穩定不變,可以設定較低的學習率,而深層的參數在訓練的過程中需要針對資料集做較大修改,可以設定較高的學習率。
對于RPN,接收來自Head的輸入圖像特征,送入有CNN和MLP組成的RPN,生成推薦框RoI(來源于錨框,并初步實作了框坐标糾正)。然後根據推薦框對應到特征圖上的位置,裁剪特征圖(Crop Pooling,在Mask-RCNN中使用RoI Align代替了RoI pooling),得到輸出結果,送入分類網絡。
對于分類網絡,對每個RoI進行分類和框坐标回歸(二次框坐标修正)。
在原文
https://github.com/ruotianluo/pytorch-faster-rcnngithub.com
中提到了網絡初始化的問題,這裡我多寫幾種方法:
- Xavier初始化;
- He初始化;
- BN層的 初始化為零(主要是針對帶有skip-connection的子產品,因為這樣網絡的前向和後向傳播,在剛開始訓練的時候均經過skip-connnection,一般認為這麼做可以提高訓練效率)。(參見論文bag of tricks ...... from 李沐)
上圖把Head,RPN和分類網絡描述在一張圖中。其中
和
表示經過預處理過後的輸入圖像的寬度和高度。
對于head,輸入
分别表示輸入圖像的寬度、高度和通道數(3表示輸入圖像為RGB彩色圖像),輸入圖像經過Conv2D降采樣後變為
(64個寬度為
,高度為
的特征圖),經過類似操作,head的輸出為
(1024個寬度為
,高度為
的特征圖),這個就是輸入圖像的特征圖,有兩個作用,一是輸入到RPN中,另外一個根據RPN的推薦框來裁剪對應位置的特征圖,作為分類網絡的輸入。
對于分類網絡(Classification Network),接收裁剪好的特征圖,進行Pooling,變為統一長寬的特征圖(對于Faster-RCNN,為RoI Pooling,對于Mask-RCNN,為RoI Align),然後送到兩個分支。一個分支為分類網絡,另一個分支為邊界框回歸網絡。
實作細節:訓練
簡要介紹完網絡結構之後,我們詳細介紹下head, RPN和分類網絡的細節。
從網絡架構可知,訓練主要是要重新訓練分類網絡、RPN和微調head(可以考慮分開設定學習率)。
要訓練,首先要得到标簽。對于目标檢測而言,标簽就是一個輸入圖像中的目标框的位置坐标和目标框中的目标類别。對于VOC和COCO資料,一般以Json格式的檔案存儲,可以使用python的Json包來處理。對于COCO,還提供了pycocotools這樣的庫(真是友善呀,但是要學習一下這個庫的使用方法)。資料集介紹下:
- PASCAL VOC:VOC2007包含9963張圖像(包括訓練驗證測試),帶有24640個目标,目标種類為20類。種類為:
- Person: person
- Animal: bird, cat, cow, dog, horse, sheep
- Vehicle: aeroplane, bicycle, boat, bus, car, motorbike, train
- Indoor: bottle, chair, dining table, potted plant, sofa, tv/monitor
- COCO(Common object in Context): COCO資料集要大于VOC2007,包含操作200k的标簽圖像,類别又90類。
在原文https://github.com/ruotianluo/pytorch-faster-rcnn中提到使用VOC2007做訓練,如果計算資源有限的情況下,是一個選擇。
下面重點來了,先看看兩個麻煩一點的概念。
- Bounding Box Regression Coefficients
這裡的圖檔看的不是很清楚。我們直接描述,令
分别表示ground truth的左上角坐标和原始的左上角坐标,令
分别ground truth的寬度高度和原始的寬度高度。那麼回歸系數為:
,
,
,
這裡使用回歸系數,而不是直接回歸坐标,是為了防止回歸誤差太大,導緻回歸框超出圖像框的範圍。另外回歸系數不會受到仿射變換的影響。在原文中提到了使用回歸系數在計算分類損失的時候具有優點,但是我在這裡了解的不是很透徹,在講述分類損失的時候可以感受到使用回歸系數的優勢。
- Intersection over Union (IOU) Overlap
用交并比(IoU)來表示兩個框的重疊程度,主要用在候選框的挑選上。
上圖是訓練過程中需要執行的步驟。
- Anchor Generation Layer,錨框生成層:這個層會根據預先設定的基尺寸、尺寸比例、尺寸縮放來生成錨框。是以這個框是固定大小的,在實際使用中一般尺寸比例為基尺寸為 ,長寬比例為 ,尺寸縮放比例為[8, 16, 32]。
- Proposal Layer, 候選層:根據bbox系數修正錨框的坐标。根據錨框中的目标類型機率,和NMS算法來減少錨框數量(去掉IoU低于給定門檻值的錨框)。
- Anchor Target Layer, 錨框目标層:生成用于訓練RPN的錨框以及對應的前景/背景标簽和框系數。該層的作用僅僅用來訓練RPN,并不會輸出到分類網絡中。
- RPN Loss,RPN損失:該損失用來訓練RPN網絡,包括候選框的前景背景分類損失和框坐标回歸損失。
- Proposal Target Layer,候選目标層:該層是為了降低候選層輸出的候選框的數量,并且生成供分類網絡訓練用的标簽(包括框類别和坐标)。
- ROI Pooling Layer, ROI池化層:實作一個空間變換網絡,該網絡對候選框進行池化,使得不同大小的候選框可以得到相同尺寸的輸出。然後送到分類器分支和框回歸分支。
- 分類損失:與RPN損失類似,用來訓練分類網絡。在梯度反向傳播過程中,誤差也會流過RPN網絡,進而會調整RPN網絡的參數。分類網絡包括:目标分類損失和框回歸損失。
Anchor Generation Layer
錨框就是根據基尺寸、錨框長寬比例、錨框尺寸縮放比例來生成候選框,如上圖所示,會生成9個候選框。由此可知,這些候選框對所有的圖檔都是一樣的。這些錨框幾乎包含了圖檔中的所有目标,但是大多數錨框都是空的。RPN網絡的目标就是尋找有可能存在目标的錨框,并對錨框的坐标進行修正。
Region Proposal Layer
目标檢測方法中需要的區域推薦系統,稀疏方法有selective search,密集方法有deformable part models。對于Faster RCNN和Mask RCNN而言,RPL根據錨框生成方法得到大量的密集錨框,并根據錨框包含目标的機率進行打分,以及進行錨框坐标的校正。主要做兩件事情:
- 從一系列錨框中,識别出包含前景框的錨框和背景框的錨框
- 修正錨框的中心位置、長度和寬度。這裡是通過錨框坐标修正因子來實作的。
區域推薦層包含三個層:
- proposal layer 候選層
- anchor target layer 框目标層
- proposal target layer 候選目标層
RPN
head部分将圖檔卷積處理後,分别經過1x1卷積到兩個支路。一條支路為前景背景分類層,另一條支路為框回歸層。由圖可知,特征圖的尺寸為
,特征圖的每個點會生成9個候選框,是以候選框個數為
。于是前景背景二分類網絡的輸出為
,框回歸網絡的輸出為
。
Proposal Layer
候選層的輸入為所有的
個錨框。通過應用基于前景分類得分的非極大值抑制從錨框中減少部分候選框。另外也通過框回歸的坐标系數來校正候選框的坐标。
Anchor Target Layer
錨框目标層的目标是選出合适的錨框作為RPN網絡的訓練資料(這個也是讓我挺疑惑的地方,在推理網絡中生成訓練資料)。RPN網絡的目的:
- 識别一個區域是前景還是背景
- 對前景框回歸一個合理的坐标校正參數
下面作者認為讨論下RPN損失,有助于了解RPN網絡。
計算RPN損失
RPN的目标是生成好的候選框(包含前景分類和坐标回歸)。具體點,就是需要在錨框集合中,尋找到含目标可能性高的錨框,以及回歸出這些錨框對應的坐标變換系數(包含位置、寬度和高度)。RPN損失的設計也是基于以上目的,那我們看下是不是這樣的?
RPN損失是分類損失和回歸損失之和。分類損失使用交叉熵損失,框回歸使用真實回歸系數和預測系數之間的距離(RMSE)計算得到。真實回歸系數使用與錨框最近的标簽框計算得到,預測系數通過網絡預測得到。
Classification Losscross_entropy(predicted_class, actual_class)
Bounding Box Regression Loss回歸框損失隻計算了前景的回歸框損失。作者認為背景框的回歸損失沒有意義,因為背景回歸框沒有對應的标簽框。
其中
上式中的
需要人工設定,也可以成為超參數,一般設定為3。(PS: 這裡作者介紹了在Python實作中,前景錨框bbox_inside_weights,也就是掩膜陣列一般作為向量運算,一般不要用for-if循環,因為循環不友善并行計算)
是以,計算RPN損失需要兩個要素:
- 錨框的前景背景類别标簽和打分(和softmax機率有關)
- 對于前景錨框的目标回歸系數
下面介紹上面兩個要素如何擷取。
- 選擇有目标的錨框
- 計算錨框和标簽框的交并比(IOU)值,然後選擇好的前景框
按照IOU比選擇前景框,有下面兩種情況:
- type A:對于每個标簽框(ground truth bbox),所有的前景框是與标簽框IOU最大的錨框
- type B:前景框與标簽框的IOU會超過一個門檻值
如下圖所示。
在上圖中,隻有與标簽框的重疊區域超過一定門檻值(IOU超過一定門檻值)的錨框才被選擇下來(還有很多重複錨框,這個時候選擇NMS算法,選擇一個錨框作為結果)。這裡的門檻值非常重要,選擇合理的門檻值有助于提高RPN的效果。類似的,重疊區域小于一定門檻值(IOU超過一定門檻值)的錨框作為負樣本。需要注意的是,不是所有非正樣本(重疊區域大于一個指定門檻值)是負樣本,就是還有中間派,即不是正樣本,又不是負樣本。這類樣本被稱為“don't care”(不關心的樣本,哈哈!!!)。這些樣本不會用來計算RPN損失。
是以有兩個額外的門檻值,與前景背景框的數量有關。前景背景框的總數量我們需要定義,以及前景框的占比也需要事先定義。如果通過測試的前景框數量操作一定門檻值,則會随機将這些通過測試的前景框标記為“don't care”,對于背景框也是同樣的操作。
然後,計算前景框與其最重疊(IOU值最大)的真實框的框回歸系數。這個相對簡單,隻需要按照公式計算即可。
最後我們總結下anchor target layer。為記憶友善,我們列出該層的參數和輸入輸出配置:
參數:- TRAIN.RPN_POSITIVE_OVERLAP:預設為0.7。用于選擇正樣本的門檻值。如果錨框和ground truth框的IOU大于該值,則為正樣本。
- TRAIN.RPN_NEGATIVE_OVERLAP: 預設為0.3。用于選擇負樣本的門檻值。如果一個錨框和ground truth框的IOU小于該值,則為負樣本。錨框的IOU大于TRAIN.RPN_NEGATIVE_OVERLAP、小于TRAIN.RPN_POSITIVE_OVERLAP被标記為“don't care”。
- TRAIN.RPN_BATCHSIZE:預設為256。前景錨框和背景錨框的綜述。
- TRAIN.RPN_FG_FRACTION:預設為0.5。前景框在batch_size中的占比(預設值設定的很平衡)。如果前景框的數量大于TRAIN.RPN_BATCHSIZE*TRAIN.RPN_FG_FRACTION,将會随機選擇超過的部分為“don't care”。
- RPN網絡輸出(前景背景預測結果,框回歸系數)
- 錨框(通過anchor generation layer)
- ground truth框
- 經過第一次糾正的目标框和對應的類别标簽
- 目标回歸系數
其它層,比如proposal target layer,ROI pooling和分類層被用來生成計算分類損失的資料。下面我們将與anchor target layer類似,看看如何計算分類層損失,以及計算該損失需要哪些資料。