科普:目标检测Anchor是什么?怎么科学设置?[附代码]
文章來源于AIZOO,作者元峰
在基于anchor的目標檢測網絡(Faster RCNN、SSD、YOLO v2&v3等)中,一個至關重要的步驟就是科學的設置anchor,可以說,Anchor設置的合理與否,極大的影響著最終模型檢測性能的好壞。本文,我們將以質樸的語言介紹Anchor導致是什么,以及如何科學的設置anchor。
對于目標檢測新手來說,一個比較常見的誤區就是拿到模型,直接無修改的在自己的數據集上訓練,最終可能導致模型雖然有一定效果,但是mAP指標可能低于別人的十幾個點,這里很有可能就是anchor設置的不合理。筆者記得在之前面試應屆生的時候,也有不少學生不能清晰的表達anchor是什么,以及怎么科學的設置。筆者開源人臉口罩檢測模型和數據后,也有不少同行和學生在自己的網絡上訓練,通過與他們的交流,我發現很多人都遇到了不知道anchor怎么設置,或者設置不科學的問題。
今天,我們講解一下anchor,因為這篇文章面向新手,所以筆者爭取用質樸(講人話)的語言進行簡單的介紹,同時,我們也將相關代碼上傳到了Github,大家可以在自己的數據集上可視化數據分布(鏈接見文末)。
在介紹Anchor之前,我們先介紹一下傳統的人臉識別算法,是怎么檢測出圖片中的人臉的。以下圖為例,如果我們要檢測圖中小女孩的人臉位置,一個比較簡單暴力的方法就是滑窗,我們使用不同大小、不同長寬比的候選框在整幅圖像上進行窮盡式的滑窗,然后提取窗口內的特征(例如Haar、LBP、Hog等特征),再送入分類器(SVM、Adaboost等)判斷該窗口內包含的是否為人臉。這種方法簡單易理解,但是這類方法受限于手動設計的特征,召回率和準確率通常不是很高。
在深度學習時代,大名鼎鼎的RCNN和Fast RCNN依舊依賴滑窗來產生候選框,也就是Selective Search算法,該算法優化了候選框的生成策略,但仍舊會產生大量的候選框,導致即使Fast RCNN算法,在GPU上的速度也只有三、四幀每秒。直到Faster RCNN的出現,提出了RPN網絡,使用RPN直接預測出候選框的位置。RPN網絡一個最重要的概念就是anchor,啟發了后面的SSD和YOLOv2等算法,雖然SSD算法稱之為default box,也有算法叫做prior box,其實都是同一個概念,他們都是anchor的別稱。
1
01
什么是Anchor?
那么,anchor到底是什么呢?如果我們用一句話概括——就是在圖像上預設好的不同大小,不同長寬比的參照框。(其實非常類似于上面的滑窗法所設置的窗口大小)
下圖來自《動手學深度學習》中的例子,假設一個256x256大小的圖片,經過64、128和256倍下采樣,會產生4x4、2x2、1x1大小的特征圖,我們在這三個特征圖上每個點上都設置三個不同大小的anchor。當然,這只是一個例子,實際的SSD模型,在300x300的輸入下,anchor數量也特別多,其在38x38、19x19、10x10、5x5、3x3、1x1的六個特征圖上,每個點分別設置4、6、6、6、6、4個不同大小和長寬比的anchor,所以一共有38x38x4+ 19x19x6+ 10x10x6+ 5x5x6+ 3x3x4+ 1x1x4= 8732個anchor。
借助神經網絡強大的擬合能力,我們不再需要計算Haar、Hog等特征,直接讓神經網絡輸出,每個anchor是否包含(或者說與物體有較大重疊,也就是IoU較大)物體,以及被檢測物體相對本anchor的中心點偏移以及長寬比例。以下圖為例:
一般的目標檢測網絡可能有成千上萬個anchor,例如標準SSD在300x300輸入下有8732個anchor,在500x500下anchor數量過萬。我們拿上圖中的三個anchor舉例,神經網絡的輸出,也就是每個anchor認為自己是否含有物體的概率,物體中心點與anchor自身的中心點位置的偏移量,以及相對于anchor寬高的比例。因為anchor的位置都是固定的,所以就可以很容易的換算出來實際物體的位置。以圖中的小貓為例,紅色的anchor就以99%的概率認為它是一只貓,并同時給出了貓的實際位置相對于該anchor的偏移量,這樣,我們將輸出解碼后就得到了實際貓的位置,如果它能通過NMS(非最大抑制)篩選,它就能順利的輸出來。但是,綠色的anchor就認為它是貓的概率就很小,紫色的anchor雖然與貓有重疊,但是概率只有26%。
其實SSD的推理很簡單,就是根據anchor進行位置解碼,然后進行NMS過程,就完成了(更詳細的推理介紹,請查看我們這篇文章 如何在瀏覽器運行深度神經網絡?以人臉口罩識別為例進行講解)。在訓練的時候,也就是給每張圖片的物體的Bounding Box,相對于anchor進行編碼,如果物體的Bounding Box與某個anchor的IoU較大,例如大于0.5就認為是正樣本,否則是負樣本(當然,也有算法將大于0.7的設為正樣本,小于0.3的算負樣本,中間的不計算損失)。
以SSD作者給出的示例圖為例,圖中有一只貓和一只狗,這只貓在8x8的特征圖上所設置anchor中,有兩個(藍色部分)與貓的IoU較大,可以認為是正樣本,而對于狗,在4x4的特征圖上的設置的anchor,有一個(紅色部分)與狗的IoU較大,可以認為是正樣本。其他的,都算作負樣本。在實際中,因為anchor非常密集,所以SSD算法中,會有多個anchor與物體的IoU大于閾值,所以可能多個anchor都是對應同一個物體的正樣本(例如這只貓,就可能有不止2個匹配的正樣本)。
看到這里大家應該比較明白了,在訓練的時候,需要anchor的大小和長寬比與待檢測的物體尺度基本一致,才可能讓anchor與物體的IoU為正樣本,否則,可能anchor為正樣本的數目特別少,就會導致漏檢很多。
我們舉個例子,如果您要檢測道路兩邊的電線桿,電線桿的寬高比可能不止1:10,而且特別細。如果您設置的anchor長寬比為1:1、1:2、 2:1、?1:3、 3:1這五個不同的長寬比,那可能到導致在訓練的時候,沒有哪個anchor與電線桿的IoU大于0.5,導致全部為負樣本,那么,這樣的anchor設置,模型怎么可能檢測出來電線桿呢?(雖然我們在實現SSD算法的時候,即使某個物體與所有anchor的IoU都不大于0.5的閾值,也會可憐可憐它,給它強行分配一個IoU最大的anchor,即使IoU只有0.3,但是這樣,每個物體只能分配一個,而且寬高偏移量還比較大,導致回歸不準。
到這里,大家應該知道了,對于目標檢測,anchor合理設置大小和寬高比,可以說非常重要。那么,如何科學的設置anchor呢?
1
02?
如何科學的設置Anchor
在FasterRCNN的RPN網絡部分,anchor為三個尺度{128, 256, 512},三個比例{1:1, 1:2, 2:1},所以一共9組anchor。
在SSD論文中,作者使用6組定位層,每個定位層分別有6個anchor(不過第一和最后一個定位層只有4個)。一個尺度,分別有1:1、1:2、2:1、1:3、3:1五個不同寬高比,再加一個后面特征圖的anchor尺度與該特征圖的尺度相乘再開根號,也就是:
同樣是1:1比例,所以一共5+1=6組anchor。
關于anchor的寬度,是尺度(scale,簡寫為s)乘以長寬比(aspect ratio,簡寫為ar)的根方,而高度,則是除以ar的根方。
在SSD中,作者提到了anchor尺度大小(scale)的計算方法,也就是從最小的0.2,到最大的0.9,中間四個定位層的大小是等間隔采樣得到的。
但是,但是,大家查看SSD開源的代碼,作者給出的得anchor大小并不是這么計算得到的。而是30、60、111、162、213、264(再加一個315)這7個尺度。我想,這應該是作者根據數據集的物體框大小的分布而設置的。因為上面我們介紹了,anchor只有跟你要檢測的物體的大小和長寬比更貼近,才能讓模型的效果更好。
YOLOv3在三個不同尺度,每個尺度三個不同大小的anchor,一共九組。這位退出CV圈的Joseph Redmon大神則是在YOLOv2版本開始使用kmeans方法聚類得到合適的anchor。
可見,三大框架的作者,在實際的公開數據集上,都是根據數據的實際分布來設置的,所以,我們在自己的數據集上訓練目標檢測網絡時,一定!不要!拿到開源代碼就是一頓跑,拿起鍵盤就是干。
1
03?
代碼示例?
我們將代碼開源放到了Github上。以人臉檢測數據集Wider Face為例,因為人臉從下巴到額頭,寬高比大約為1:1.4左右。在我們的開源代碼中,將example.py 開頭設置文件路徑和要聚類的簇,以及是否將物體坐標相對于圖像寬高尺度歸一化。
然后代碼會自動讀取所有的xml文件中的物體坐標,然后運行kmeans聚類,并將結果畫出來。我們可以看到數據分布如下:
其中黑色點是隨機選的2000個物體框的大小,紅色三角為聚類結果,可能太密集了,不易查看,但代碼會輸出建議的25組anchor大小:
建議anchor大小寬度?????????高度???????高寬比10.000 12.000 1.210.000 14.000 1.414.000 12.000 0.912.000 14.000 1.212.000 16.000 1.313.000 16.000 1.212.000 18.000 1.514.000 19.000 1.416.000 19.000 1.217.000 22.000 1.319.000 22.000 1.218.000 27.000 1.523.000 29.000 1.323.000 32.000 1.428.000 32.000 1.135.000 44.000 1.341.000 51.000 1.248.000 67.000 1.449.000 67.000 1.455.000 65.000 1.259.000 69.000 1.280.000 80.000 1.080.000 82.000 1.092.000??????108.00?????1.2204.00??????246.00?????1.2可以看到,建議的anchor高寬比都是1.3左右,另外,還有數據框的分布統計圖如下:
可以看到人臉高寬比例多數都在1.4 : 1左右。所以,對于Wider Face人臉檢測,可以將anchor 設置為1:1、1.4:1、 1.7:1,而沒必要設置3:1、1:3這種明顯不合適的比例(畢竟,臉再長,也很少是3:1這么夸張的比例吧)。對于anchor的大小,可以查看上圖的寬度和高度統計,參考聚類結果,設置合理的大小。
注意事項
對于檢測網絡,有的實現,是用沒有歸一化的坐標,例如anchor設置為(30, 42)這種尺度大小,但是,有的算法實現,是將坐標和物體框的寬高比,除以圖片的寬和高。這里,就需要注意了。如果您的圖片都是正方形的,那歸一化后寬高比沒有變化,如果是1080P這種分辨率的攝像頭,那么長寬比是16:9了。本來就小的寬度,再除以1920,而高度除以1080,會導致歸一化后的人臉高度是寬度的2倍左右。例如下圖,圖片寬度約為高度的兩倍,歸一化后,人臉寬度相比高度要更小很多。
我們將代碼中歸一化選項打開:
再次運行,可以看到統計的高寬比如下圖,可以看到高寬比最集中的是2:1(未歸一化時是1.4:1),因為WiderFace數據,多數圖片也是寬度大于高度的寬圖。
歸一化的建議anchor大小如下,可以看到高寬比相比上面未歸一化的,明顯要更大一些。
所以,如果是使用歸一化的anchor大小,需要考慮圖片的寬高比例問題。
同樣,即使您使用的是未歸一化的anchor大小,但是如果您將圖像直接resize成正方形大小,對于寬幅的圖像,也會面臨同樣的問題,我們將上面的圖resize成500x500的正方形,如下,可以看到高寬比進一步加大。當然,如果您的做法是將短邊通過padding補零的方式,使圖像為正方形,則不存在這個問題的。
好了,總結一下,對于目標檢測的anchor 設置,一定要根據您的數據分布設置合理的anchor,另外,也要考慮是否是歸一化的anchor大小,或者是否做了改變圖像長寬比的resize。
本文的Github代碼地址:
https://github.com/AIZOOTech/object-detection-anchors
總結
以上是生活随笔為你收集整理的科普:目标检测Anchor是什么?怎么科学设置?[附代码]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从文本分类来看图卷积神经网络
- 下一篇: WSDM Cup 2020 引用意图识别