原文:http://blog.csdn.net/WoPawn/article/details/52463853
&創新點
規避R-CNN中冗余的特征提取操作,只對整張圖像全區域進行一次特征提取;
用 RoI pooling 層取代最后一層 max pooling層,同時引入候選框信息,提取相應候選框特征;
Fast R-CNN 網絡末尾采用並行的不同的全連接層,可同時輸出分類結果和窗口回歸結果,實現end-to-end的多任務訓練【候選提取除外】,也不需要額外的特征存儲空間【R-CNN中這部分特征是供SVM和Bounding-box regression進行訓練的】;
采用SVD對Fast R-CNN網絡末尾並行的全連接層進行分解,減少計算復雜度,加快檢測速度。
&問題是什么
- R-CNN網絡訓練、測試速度都很慢:R-CNN網絡中,一張圖經由selective search算法提取約2k個候選框【這2k個候選框大量重疊】,而所有候選框變形后都要輸入AlexNet CNN網絡提取特征【即約2k次特征提取】,會出現上述重疊區域多次重復提取特征,提取特征操作冗余;
- R-CNN網絡訓練、測試繁瑣:R-CNN網絡訓練過程分為ILSVRC 2012樣本下有監督預訓練、PASCAL VOC 2007該特定樣本下的微調、20類即20個SVM分類器訓練、20類即20個Bounding-box 回歸器訓練,該訓練流程繁瑣復雜;同理測試過程也包括提取候選框、提取CNN特征、SVM分類和Bounding-box 回歸等步驟,過於繁瑣;
- R-CNN網絡訓練需要大量存儲空間:20類即20個SVM分類器和20類即20個Bounding-box 回歸器在訓練過程中需要大量特征作為訓練樣本,這部分從CNN提取的特征會占用大量存儲空間;
- R-CNN網絡需要對候選框進行形變操作后【形變為227×227 size】再輸入CNN網絡提取特征,其實像AlexNet CNN等網絡在提取特征過程中對圖像的大小並無要求,只是在提取完特征進行全連接操作的時候才需要固定特征尺寸【6*6*256】【R-CNN中將輸入圖像形變為227×227可正好滿足AlexNet CNN網絡最后的特征尺寸要求】,然后才使用SVM分類器分類,R-CNN需要進行形變操作的問題在Fast R-CNN已經不存在,具體見下。
&如何解決問題
測試過程
Fast R-CNN的網絡結構如下圖所示。
- 任意size圖片輸入CNN網絡,經過若干卷積層與池化層,得到特征圖;
- 在任意size圖片上采用selective search算法提取約2k個候選框;
- 根據原圖中候選框到特征圖映射關系,在特征圖中找到每個候選框對應的特征框【深度和特征圖一致】,並在RoI池化層中將每個特征框池化到H×W【VGG-16網絡是7×7】的size;
- 固定H×W【VGG-16網絡是7×7】大小的特征框經過全連接層得到固定大小的特征向量;
- 第4步所得特征向量經由各自的全連接層【由SVD分解實現】,分別得到兩個輸出向量:一個是softmax的分類得分,一個是Bounding-box窗口回歸;
- 利用窗口得分分別對每一類物體進行非極大值抑制剔除重疊候選框,最終得到每個類別中回歸修正后的得分最高的窗口。
解釋分析
整個測試過程為什么可以只進行一次CNN特征提取操作?
先看R-CNN網絡,它首先采用selective search算法提取約2k個候選框,並對所有候選框都進行了CNN特征提取操作,會出現重疊區域多次重復提取特征,這些操作非常耗時、耗空間。事實上我們並不需要對每個候選框都進行CNN特征提取操作,只需要對原始的整張圖片進行1次CNN特征提取操作即可,因為selective search算法提取的候選框屬於整張圖片,因此對整張圖片提取出特征圖后,再找出相應候選框在特征圖中對應的區域,這樣就可以避免冗余的特征提取操作,節省大量時間。
為什么要將每個候選框對應的特征框池化到H×W 的size?如何實現?
問題4中已經指出像AlexNet CNN等網絡在提取特征過程中對圖像的大小並無要求,只是在提取完特征進行全連接操作的時候才需要固定特征尺寸,利用這一點,Fast R-CNN可輸入任意size圖片,並在全連接操作前加入RoI池化層,將候選框對應特征圖中的特征框池化到H×W 的size,以便滿足后續操作對size的要求;
具體如何實現呢?
首先假設建議框對應特征圖中的特征框大小為h*w,將其划分H*W個子窗口,每個子窗口大小為h/H*w/W,然后對每個子窗口采用max pooling下采樣操作,每個子窗口只取一個最大值,則特征框最終池化為H×W的size【特征框各深度同理】,這將各個大小不一的特征框轉化為大小統一的數據輸入下一層。
為什么要采用SVD分解實現Fast R-CNN網絡中最后的全連接層?具體如何實現?
圖像分類任務中,用於卷積層計算的時間比用於全連接層計算的時間多,而在目標檢測任務中,selective search算法提取的建議框比較多【約2k】,幾乎有一半的前向計算時間被花費於全連接層,就Fast R-CNN而言,RoI池化層后的全連接層需要進行約2k次【每個建議框都要計算】,因此在Fast R-CNN中可以采用SVD分解加速全連接層計算;
具體如何實現呢?
① 物體分類和窗口回歸都是通過全連接層實現的,假設全連接層輸入數據為x,輸出數據為y,全連接層參數為W,尺寸為u×v,那么該層全連接計算為:
計算復雜度為u×v;
② 若將W進行SVD分解,並用前t個特征值近似代替,即:
那么原來的前向傳播分解成兩步:
計算復雜度為u×t+v×t,若t<min(u,v),則這種分解會大大減少計算量;
在實現時,相當於把一個全連接層拆分為兩個全連接層,第一個全連接層不含偏置,第二個全連接層含偏置;實驗表明,SVD分解全連接層能使mAP只下降0.3%的情況下提升30%的速度,同時該方法也不必再執行額外的微調操作。
文中僅采用selective search算法提取約2k個候選區域,那候選區域越多越好嗎?
文中利用selective search算法提取1k~10k中10種數目【1k,2k…】的候選區域進行訓練測試,發現隨着候選區域個數的增加,mAP成先增加后緩慢下滑的趨勢,這表明更多的候選區域會有損精度;與此同時,作者也做了召回率【所謂召回率即候選區域為真的窗口與Ground Truth的比值【IoU大於閾值即為真】】分析實驗,發現隨着候選區域個數的增加,召回率並沒有和mAP成很好的相關性,而是一直不斷增加,也就是說更高的召回率並不意味着更高的mAP;
文中也以selective search算法提取的2k個候選區域為基礎,每次增加1000 × {2, 4, 6, 8, 10, 32, 45}個密集box【滑動窗口方法】進行訓練測試,發現mAP比只有selective search方法的2k候選區域下降幅度更大,最終達到53%。
如何處理尺度不變性問題?即如何使24×24和1080×720的車輛同時在一個訓練好的網絡中都能正確識別?
文中提及兩種方式處理:brute-force(單一尺度)和image pyramids(多尺度)。單一尺度直接在訓練和測試階段將image定死為某種scale,直接輸入網絡訓練就好,然后期望網絡自己能夠學習到scale-invariance的表達;多尺度在訓練階段隨機從圖像金字塔【縮放圖片的scale得到,相當於擴充數據集】中采樣訓練,測試階段將圖像縮放為金字塔中最為相似的尺寸進行測試;
可以看出,多尺度應該比單一尺度效果好。作者在5.2節對單一尺度和多尺度分別進行了實驗,不管哪種方式下都定義圖像短邊像素為s,單一尺度下s=600【維持長寬比進行縮放】,長邊限制為1000像素;多尺度s={480,576,688,864,1200}【維持長寬比進行縮放】,長邊限制為2000像素,生成圖像金字塔進行訓練測試;實驗結果表明AlexNet【S for small】、VGG_CNN_M_1024【M for medium】下單一尺度比多尺度mAP差1.2%~1.5%,但測試時間上卻快不少,VGG-16【L for large】下僅單一尺度就達到了66.9%的mAP【由於GPU顯存限制多尺度無法實現】,該實驗證明了深度神經網絡善於直接學習尺度不變形,對目標的scale不敏感。
為什么不沿用R-CNN中的形式繼續采用SVM進行分類?
為什么R-CNN中采用SVM分類而不直接用CNN網絡輸出端進行分類已經在R-CNN博客中說明【RCNN使用的是類似於HOG、SIFT的不針對特定任務的基礎特征】,針對Fast R-CNN,文中分別進行實驗並對比了采用SVM和采用softmax的mAP結果,不管AlexNet【S for small】、VGG_CNN_M_1024【M for medium】、VGG-16【L for large】中任意網絡,采用softmax的mAP都比采用SVM的mAP高0.1%~0.8%,這是由於softmax在分類過程中引入了類間競爭,分類效果更好;
Fast R-CNN去掉了SVM這一步,所有的特征都暫存在顯存中,就不需要額外的磁盤空間。
訓練過程
有監督預訓練
樣本來源 | ILSVRC 20XX |
ILSVRC 20XX樣本只有類別標簽,有1000種物體;
文中采用AlexNet【S for small】、VGG_CNN_M_1024【M for medium】、VGG-16【L for large】這三種網絡分別進行訓練測試,下面僅以VGG-16舉例。
特定樣本下的微調
樣本 | 比例 | 來源:PASCAL VOC |
正樣本 | 25% | 與某類Ground Truth相交IoU∈[0.5,1]的候選框 |
負樣本 | 75% | 與20類Ground Truth相交IoU中最大值∈[0.1,0.5)的候選框 |
PASCAL VOC數據集中既有物體類別標簽,也有物體位置標簽,有20種物體;
正樣本僅表示前景,負樣本僅表示背景;
回歸操作僅針對正樣本進行;
該階段訓練集擴充方式:50%概率水平翻轉;
在調優訓練時,每一個mini-batch中首先加入N張完整圖片,而后加入從N張圖片中選取的R個候選框。這R個候選框可以復用N張圖片前5個階段的網絡特征。 實際選擇N=2, R=128。
微調前,需要對有監督預訓練后的模型進行3步轉化:
①RoI池化層取代有監督預訓練后的VGG-16網絡最后一層池化層;
②兩個並行層取代上述VGG-16網絡的最后一層全連接層和softmax層,並行層之一是新全連接層1+原softmax層1000個分類輸出修改為21個分類輸出【20種類+背景】,並行層之二是新全連接層2+候選區域窗口回歸層,如下圖所示;
③上述網絡由原來單輸入:一系列圖像修改為雙輸入:一系列圖像和這些圖像中的一系列候選區域;
SGD超參數選擇:
除了修改增加的層,原有的層參數已經通過預訓練方式初始化;
用於分類的全連接層以均值為0、標准差為0.01的高斯分布初始化,用於回歸的全連接層以均值為0、標准差為0.001的高斯分布初始化,偏置都初始化為0;
針對PASCAL VOC 2007和2012訓練集,前30k次迭代全局學習率為0.001,每層權重學習率為1倍,偏置學習率為2倍,后10k次迭代全局學習率更新為0.0001;
動量設置為0.9,權重衰減設置為0.0005。
解釋分析
Fast R-CNN如何采樣進行SGD訓練,和R-CNN、SPPnet中SGD采樣方式有什么區別和優勢?
R-CNN和SPPnet中采用RoI-centric sampling:從所有圖片的所有候選區域中均勻取樣,這樣每個SGD的mini-batch中包含了不同圖像的樣本,不同圖像之間不能共享卷積計算和內存,運算開銷大;
Fast R-CNN中采用image-centric sampling: mini-batch采用層次采樣,即先對圖像采樣【N個】,再在采樣到的圖像中對候選區域采樣【每個圖像中采樣R/N個,一個mini-batch共計R個候選區域樣本】,同一圖像的候選區域卷積共享計算和內存,降低了運算開銷;
image-centric sampling方式采樣的候選區域來自於同一圖像,相互之間存在相關性,可能會減慢訓練收斂的速度,但是作者在實際實驗中並沒有出現這樣的擔憂,反而使用N=2,R=128的image-centric sampling方式比R-CNN收斂更快。
這里解釋一下為什么SPPnet不能更新spatial pyramid pooling層前面的卷積層,而只能更新后面的全連接層?
博主沒有看過SPPnet的論文,有網友解釋說卷積特征是線下計算的,從而無法在微調階段反向傳播誤差;另一種解釋是,反向傳播需要計算每一個RoI感受野的卷積層梯度,通常所有RoI會覆蓋整個圖像,如果用RoI-centric sampling方式會由於計算too much整幅圖像梯度而變得又慢又耗內存。
訓練數據越多效果越好嗎?
實驗 | 訓練集 | 測試集 | mAP |
實驗1 | VOC 2007訓練集 | VOC 2007測試集 | 66.9% |
實驗1 | VOC 2007+VOC 2012訓練集 | VOC 2007測試集 | 70.0% |
實驗2 | VOC 2012訓練集 | VOC 2010測試集 | 66.1% |
實驗2 | VOC 2007+VOC 2012訓練集+VOC2007測試集 | VOC 2010測試集 | 68.8% |
實驗3 | VOC 2012訓練集 | VOC 2012測試集 | 65.7% |
實驗3 | VOC 2007+VOC 2012訓練集+VOC2007測試集 | VOC 2012測試集 | 68.4% |
文中分別在VOC 2007、VOC 2010、VOC 2012測試集上測試,發現訓練數據越多,效果確實更好。這里微調時采用100k次迭代,每40k次迭代學習率都縮小10倍。
哪些層參數需要被微調?
SPPnet論文中采用ZFnet【AlexNet的改進版】這樣的小網絡,其在微調階段僅對全連接層進行微調,就足以保證較高的精度,作者文中采用VGG-16【L for large】網路,若僅僅只對全連接層進行微調,mAP會從66.9%降低到61.4%, 所以文中也需要對RoI池化層之前的卷積層進行微調;
那么問題來了?向前微調多少層呢?所有的卷積層都需要微調嗎?
作者經過實驗發現僅需要對conv3_1及以后卷積層【即9-13號卷積層】進行微調,才使得mAP、訓練速度、訓練時GPU占用顯存三個量得以權衡;
作者說明所有AlexNet【S for small】、VGG_CNN_M_1024【M for medium】的實驗結果都是從conv2往后微調,所有VGG-16【L for large】的實驗結果都是從conv3_1往后微調。
Fast R-CNN如何進行多任務訓練?多任務訓練有效果嗎?
Fast R-CNN網絡分類損失和回歸損失如下圖所示【僅針對一個RoI即一類物體說明】,黃色框表示訓練數據,綠色框表示輸入目標:
RoI池化層如何進行反向求導訓練?
首先看普通max pooling層如何求導,設xi為輸入層節點,yi為輸出層節點,那么損失函數L對輸入層節點xi的梯度為:

其中判決函數δ(i,j)表示輸入i節點是否被輸出j節點選為最大值輸出。不被選中【δ(i,j)=false】有兩種可能:xi不在yi范圍內,或者xi不是最大值。若選中【δ(i,j)=true 】則由鏈式規則可知損失函數L相對xi的梯度等於損失函數L相對yi的梯度×(yi對xi的梯度->恆等於1),故可得上述所示公式;
對於RoI max pooling層,設xi為輸入層的節點,yri 為第r個候選區域的第j個輸出節點,一個輸入節點可能和多個輸出節點相關連,如下圖所示,輸入節點7和兩個候選區域輸出節點相關連;
該輸入節點7的反向傳播如下圖所示。對於不同候選區域,節點7都存在梯度,所以反向傳播中損失函數L對輸入層節點xi的梯度為損失函數L對各個有可能的候選區域r【xi被候選區域r的第j個輸出節點選為最大值 】輸出yri梯度的累加,具體如下公式所示:
判決函數[i=i∗(r,j)]表示i節點是否被候選區域r的第j個輸出節點選為最大值輸出,若是,則由鏈式規則可知損失函數L相對xi的梯度等於損失函數L相對yrj的梯度×(yrj對xi的梯度->恆等於1),上圖已然解釋該輸入節點可能會和不同的yrj有關系,故損失函數L相對xi的梯度為求和形式。
&還存在什么問題
Fast R-CNN中采用selective search算法提取候選區域,而目標檢測大多數時間都消耗在這里【selective search算法候選區域提取需要2~3s,而提特征分類只需要0.32s】,這無法滿足實時應用需求,而且Fast R-CNN並沒有實現真正意義上的端到端訓練模式【候選區域是使用selective search算法先提取出來的】;
那有沒有可能使用CNN直接產生候選區域並對其分類呢?Faster R-CNN框架就是符合這樣需求的目標檢測框架,請看Faster R-CNN博客。
&配置
這里選擇 https://github.com/microsoft/caffe 微軟的Caffe以在Windows下編譯
1. 修改 caffe-master\windows\libcaffe\libcaffe.vcxproj, 添加:
<ClCompile Include="..\..\src\caffe\layers\roi_pooling_layer.cpp" /> <ClInclude Include="..\..\include\caffe\layers\roi_pooling_layer.hpp" /> <CudaCompile Include="..\..\src\caffe\layers\roi_pooling_layer.cu" />
重新編譯