深入理解anchor


在博客SSD原理解讀-從入門到精通中提到了anchor作用:通過anchor設置每一層實際響應的區域,使得某一層對特定大小的目標響應。很多人肯定有這麼一個疑問:那anchor到底可以設置到多大呢?,本文嘗試對anchor的大小進行了一系列的探索,同時借鑑了SSD的anchor機制,提出了MTCNN中的anchor機制,能夠顯著提高MTCNN的精度。



理論感受野大小的計算

由於本文在討論anchor大小的時候,都是與理論感受野大小相關的,這裏有必要說一下理論感受野大小的計算。關於理論感受野大小的計算,有一篇很好的文章:A guide to receptive field arithmetic for Convolutional Neural Networks,國內也有這篇文章的翻譯,在網上都可以找到。關於這篇文章就不展開說了。這裏直接給出我用的計算感受野大小的python代碼,直接修改網絡參數就可以計算理論感受野大小,非常方便。

def outFromIn(isz, net, layernum):
    totstride = 1
    insize = isz
    for layer in range(layernum):
        fsize, stride, pad = net[layer]
        outsize = (insize - fsize + 2*pad) / stride + 1
        insize = outsize
        totstride = totstride * stride
    return outsize, totstride

def inFromOut(net, layernum):
    RF = 1
    for layer in reversed(range(layernum)):
        fsize, stride, pad = net[layer]
        RF = ((RF -1)* stride) + fsize
    return RF

# 計算感受野和步長,[11,4,0]:[卷積核大小,步長,pad]
def ComputeReceptiveFieldAndStride():
    net_struct = {'PNet': {'net':[[3,2,0],[2,2,0],[3,1,0],[3,2,0],[1,1,0]],'name':['conv1','pool1','conv2','conv3','conv4-3']}}
    imsize = 512
    print ("layer output sizes given image = %dx%d" % (imsize, imsize))
    for net in net_struct.keys():
            print ('************net structrue name is %s**************'% net)
            for i in range(len(net_struct[net]['net'])):
                p = outFromIn(imsize,net_struct[net]['net'], i+1)
                rf = inFromOut(net_struct[net]['net'], i+1)
                print ("Layer Name = %s, Output size = %3d, Stride = %3d, RF size = %3d" % (net_struct[net]['name'][i], p[0], p[1], rf))

運行結果如下
在這裏插入圖片描述
除了通過公式計算,還有一種更加方便的可以用於手工計算的方式。這裏給出幾條規則:

  1. 初始featuremap層的感受野是1
  2. 每經過一個convkxk s1(卷積核大小爲k,步長爲1)的卷積層,感受野 r = r+ (k - 1),常用k=3感受野 r = r + 2,k=5感受野r= r + 4
  3. 每經過一個convkxk s2的卷積層或max/avg pooling層,感受野 r = (r x 2) + (k -2),常用卷積核k=3, s=2,感受野 r = r x 2 + 1,卷積核k=7, s=2, 感受野r = r x 2 + 5
  4. 每經過一個maxpool2x2 s2的max/avg pooling下采樣層,感受野 r = r x 2
  5. 經過conv1x1 s1,ReLU,BN,dropout等元素級操作不會改變感受野
  6. 經過FC層和GAP層,感受野就是整個輸入圖像
  7. 全局步長等於經過所有層的步長累乘

具體在計算的時候,採用bottom-up的方式。
要計算哪一層的感受野,就將該層的輸出設置爲1,然後依次向前計算,比如下圖中的網絡結構中,要計算pool3的感受野,將pool3的輸出設置爲1,就可以得到conv1的輸入大小爲30x30,也就是P3的感受野大小爲30。
在這裏插入圖片描述
按照這個算法,我們可以算出SSD300中conv4-3的理論感受野:
r =(((1 +2 +2+2+2 )x2 +2+2+2 )x2 +2+2 )x2 +2+2 = 108
注意:由於conv4-3後面接了3x3的卷積核做分類和迴歸,所以在計算感受野大小的時候,需要將用於分類和迴歸的3x3的卷積核也考慮進去。


經典SSD網絡anchor的設置

下面我們來看一下經典網絡中anchor大小是如何設置的

在這裏插入圖片描述
其中( )中的數字表示:anchor/理論感受野,下文中使用該數值表示anchor的大小。
在這裏插入圖片描述
注:SFD:Single Shot Scale-invariant Face Detector

於老師開源的檢測器:ShiqiYu/libfacedetection中anchor的設置
在這裏插入圖片描述

在這裏插入圖片描述

觀察SSD,SFD,YuFace,RPN中的anchor設計,我們可以看出anchor的大小基本在[0.1,0.7]之間。RPN網絡比較特別,anchor的大小超出了感受野大小。


anchor大小的探索

下面我做了一系列實驗探索anchor大小的範圍,分別在數據集A和數據集B上,使用SFD_VGG16和SSD_YuFaceNet兩個模型,所有層的anchor大小分別設計爲0.1~0.9,觀察模型的AP和loss大小。
注:SFD_VGG16和SSD_YuFaceNet分別使用的是SFD開源的網絡和ShiqiYu/libfacedetection開源的網絡

AP

數據集A:
在這裏插入圖片描述
數據集B:
在這裏插入圖片描述

loss

數據集A:
在這裏插入圖片描述

數據集B:
在這裏插入圖片描述

實驗分析

通過對經典網絡的分析,以及實驗的結果,可以觀察到以下現象:

  1. anchor可以設置的範圍較大,從實驗結果來看,0.05~1.0基本都可以收斂,這也解釋了爲什麼FasterRCNN中的RPN網絡anchor大小可以超過感受野。從loss來看,anchor太大或者大小收斂效果都不好,甚至會出現不收斂的情況。這一點也很好理解,如果anchor太大,導致目標上下文信息較少,而如果anchor太小,又會導致沒有足夠多的信息。
  2. 綜合AP的值以及loss的大小,我們可以看出,anchor在0.2~0.7之間收斂效果較好,這個結論與SSD經典網絡的設置基本一致。這個範圍既可以保證目標有足夠多的上下文信息,也不會因爲目標太小沒有足夠多的信息。

注:由於目前實驗數據還不夠充分,這個範圍可能並不準確,歡迎大家留言討論。


滑動窗口,感受野與anchor的關係

首先區分一下這幾個比較容易混淆的概念:

  1. 滑動窗口:使得某一層輸出大小爲1的輸入大小就是該層的滑動窗口大小。比如MTCNN中PNet,滑動窗口大小爲12x12
  2. 理論感受野:影響某個神經元輸出的輸入區域,也就是該層能夠感知到的區域
  3. 有效感受野:理論感受野中間對輸出有重要影響的區域
  4. anchor:預先設置的每一層實際響應的區域

滑動窗口大小和理論感受野是一個網絡的固有屬性,一旦網絡結構確定了,這兩個參數就確定了,有效感受野是可以通過訓練改變的,anchor是通過人工手動設置的。理論感受野,有效感受野,滑動窗口是對齊的, anchor設置過程中也要與感受野對齊,否則會影響檢測效果。檢測層上每個像素點都會對應一個理論感受野,滑動窗口以及anchor。


MTCNN中的anchor機制

MTCNN訓練機制的問題

熟悉MTCNN的朋友應該都知道,訓練MTCNN的時候需要事先生成三類樣本:positive,part,negative.這三類樣本是根據groundtruth的IOU來區分的,原論文中的設置是IOU<0.3的爲negative,IOU>0.65的爲positve,0.4<IOU<0.65的爲part。
在這裏插入圖片描述
上圖中生成的positive樣本爲,圖中紅色框爲groundtruth,藍色框爲候選框
在這裏插入圖片描述
其中迴歸任務迴歸的就是兩者之間的offset
在這裏插入圖片描述

迴歸的4個偏移量(公式不唯一):

(x1x1)/w(x1-x1’)/w

(y1y1)/h(y1-y1’)/h

(x2x2)/w(x2-x2’)/w

(y2y2)/h(y2-y2’)/h
對於小目標或者類似頭肩這種目標,會出現一些問題
在這裏插入圖片描述
生成的positive樣本如下:
在這裏插入圖片描述
基本上是一塊黑色區域,沒有太多有效信息。
對於小目標:
在這裏插入圖片描述
生成的positive是
在這裏插入圖片描述
這樣的圖像,這些圖像是非常不利於訓練的,而且MTCNN在訓練的時候輸入分辨率都比較小(比如12,24,48),將這些生成的圖像resize到12,24或者48之後會導致有效信息更少,爲了解決這個問題,我們需要包含目標更多的上下文信息,會更加容易識別。
在這裏插入圖片描述

MTCNN中的anchor機制

借鑑SSD中anchor的思想,提出了MTCNN中的anchor

SSD在訓練過程中通過anchor與groundtruth的匹配來確定每一個anchor的類別,具體匹配過程:計算與每個anchor的IOU最大(>閾值)的那個groundtruth,如果找到了,那麼該anchor就匹配到了這個groundtruth,該anchor就是positive樣本,anchor的類別就是該groundtruth的類別,迴歸的offset就是anchor與groundtruth之間的偏移量。由於SSD的anchor通常都比理論感受野小,所以SSD會包含較多的上下文信息,如下圖所示。
在這裏插入圖片描述
聯想到MTCNN,在生成訓練樣本的時候,我們可以將候選框當成anchor,生成positive的過程就是SSD中的匹配過程,由於需要包含更多上下文信息,最後會對anchor進行擴邊生成最後的訓練樣本 。
在這裏插入圖片描述
紅色區域就是anchor也就是生成的positive樣本,整個黑色區域就是對anchor做擴邊後生成的訓練樣本,可以看到包含了更多的上下文信息。

實驗結果與分析

在多種數據集上對anchor機制進行了實驗。
數據集1:
在這裏插入圖片描述
數據集2:在這裏插入圖片描述
從實驗結果我們可以看出,anchor機制可以顯著提高檢測器的精度。


結束語

關於anchor其實還有很多地方值得探索,本文只是總結了一下最近工作中對anchor的一些最新的認識,就當拋磚引玉,大家如果有關於anchor更好的解讀歡迎一起討論。


非常感謝您的閱讀,如果您覺得這篇文章對您有幫助,歡迎掃碼進行讚賞。

這裏寫圖片描述

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