卷積神經(jīng)網(wǎng)絡(luò)感受野計(jì)算指南
點(diǎn)擊上方“小白學(xué)視覺(jué)”,選擇加"星標(biāo)"或“置頂”
重磅干貨,第一時(shí)間送達(dá)
作者:Dang Ha The Hien
編譯:ronghuaiyang
之前分享過(guò)一篇文章,是關(guān)于感受野的,今天這篇文章是專門(mén)講解如何計(jì)算感受野的,可以和之前那篇結(jié)合起來(lái)看,之前那篇文章我也再推送一次給大家。
感受野可能是卷積神經(jīng)網(wǎng)絡(luò)(CNNs)中最重要的概念之一,值得更多的關(guān)注。所有最先進(jìn)的物體識(shí)別方法都圍繞這一思想設(shè)計(jì)它們的模型體系結(jié)構(gòu)。然而,據(jù)我所知,目前還沒(méi)有一個(gè)完整的指南,如何計(jì)算和可視化感受野的CNN信息。這篇文章通過(guò)介紹一種新的方法來(lái)填補(bǔ)這一空白,這種方法可以在CNN中可視化特征圖,公開(kāi)感受野信息,同時(shí)提供一個(gè)完整的感受野計(jì)算,可以用于任何CNN架構(gòu)。我還實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的程序來(lái)演示計(jì)算,這樣任何人都可以開(kāi)始計(jì)算感受野,并更好地了解他們正在使用的CNN的架構(gòu)。
感受野 定義為輸入空間中某個(gè)CNN特性正在查看(即受其影響)的區(qū)域。特征的感受野可以通過(guò)其中心位置和大小來(lái)描述。然而,并不是感受野中的所有像素對(duì)于其對(duì)應(yīng)的CNN特征都是同等重要的。在感受野內(nèi),像素越靠近中心,對(duì)輸出特征的計(jì)算貢獻(xiàn)越大。這意味著一個(gè)特征不僅關(guān)注輸入圖像中的一個(gè)特定區(qū)域(即它的感受野),而且指數(shù)級(jí)地更加關(guān)注該區(qū)域的中心。這一重要見(jiàn)解將在另一篇博客文章中進(jìn)一步解釋。目前,我們的重點(diǎn)是計(jì)算特定感受野的位置和大小。
圖1顯示了一些感受野示例。將C與kernel size k = 3x3, padding size p = 1x1, stride s = 2x2 *在輸入map 5x5上進(jìn)行卷積,得到輸出feature map 3x3(綠色map)。在3x3 feature map上應(yīng)用相同的卷積,得到2x2feature map(橙色map)。每個(gè)維度中輸出特性的數(shù)量可以使用以下公式計(jì)算,具體說(shuō)明如下。

注意,在本文中,為了簡(jiǎn)化,我假設(shè)CNN架構(gòu)是對(duì)稱的,而輸入圖像是正方形的。所以這兩個(gè)維度對(duì)于所有變量都有相同的值。如果CNN架構(gòu)或輸入圖像是非對(duì)稱的,則可以分別計(jì)算每個(gè)維度的feature map屬性。

圖1的左列顯示了一種可視化CNN feature map的常用方法。在這個(gè)可視化過(guò)程中,盡管通過(guò)查看特征圖,我們知道它包含了多少特征。不可能知道每個(gè)特征觀察的位置在哪里(它的感受野的中心位置),以及這個(gè)區(qū)域有多大(它的感受野大小)。圖1的右欄顯示了固定尺寸的CNN可視化,它通過(guò)保持所有feature map的大小不變并等于輸入map來(lái)解決這個(gè)問(wèn)題。每個(gè)特征都被標(biāo)記在其感受野位置的中心。因?yàn)閒eature map中的所有特征都具有相同大小的感受野,所以我們可以簡(jiǎn)單地在一個(gè)特征周圍畫(huà)一個(gè)包圍框來(lái)表示它的感受野大小。我們不需要將這個(gè)邊界框一直映射到輸入層,因?yàn)閒eature map已經(jīng)在輸入層用相同大小來(lái)表示了。圖2顯示了另一個(gè)使用相同卷積的例子,但應(yīng)用于更大的輸入映射- 7x7。我們可以用3D(左)或2D(右)繪制固定大小的CNN feature maps。注意,圖2中感受野的大小增長(zhǎng)得非常快,以至于第二個(gè)特性層的中心特征的感受野幾乎覆蓋了整個(gè)輸入map。這是一個(gè)重要的見(jiàn)解,它被用來(lái)改進(jìn)一個(gè)深度CNN的設(shè)計(jì)。

圖2:另一個(gè)固定大小的CNN feature map表示。同樣的卷積C應(yīng)用于i = 7x7的更大的輸入映射。我圍繞中心特征繪制了感受野邊界框,并刪除了填充網(wǎng)格以獲得更清晰的視圖。固定大小的CNN feature map可以顯示為3D(左)或2D(右)。
要計(jì)算每一層的感受野,除了每個(gè)維度的特征數(shù)n外,還需要跟蹤每一層的一些額外信息。其中包括當(dāng)前感受野大小r,兩個(gè)相鄰特征(或跳轉(zhuǎn))之間的距離j,和左上角特征(第一個(gè)特征)的中心坐標(biāo)start 。注意,特征的中心坐標(biāo)被定義為其感受野的中心坐標(biāo),如上面的固定大小的CNN feature map所示。當(dāng)與kernel size k, padding size p, stride size s進(jìn)行卷積時(shí),輸出層的屬性可以通過(guò)以下公式計(jì)算:

第一個(gè)方程根據(jù)輸入特征個(gè)數(shù)和卷積性質(zhì)計(jì)算輸出特征個(gè)數(shù)。這與上面中給出的方程相同。
第二個(gè)方程計(jì)算輸出特征圖中的jump,它等于輸入映射中的jump乘以應(yīng)用卷積時(shí)跳過(guò)的輸入特征的數(shù)量(步長(zhǎng))。
第三個(gè)方程計(jì)算輸出feature map的接感受野大小,等于k 個(gè)輸入特征所覆蓋的區(qū)域(k-1)*j_in,加上邊界上輸入feature的感受野所覆蓋的額外區(qū)域。
第四個(gè)方程計(jì)算第一個(gè)輸出特征的感受野的中心位置,等于第一個(gè)輸入特征的中心位置 + 第一個(gè)輸入特征的中心位置到第一個(gè)卷積 (k - 1) / 2 * j_in的距離 - padding空間p * j_in。注意,在這兩種情況下,我們都需要將輸入feature map的jump相乘,以得到實(shí)際的距離/空間。
第一層是輸入層,它總是有n =圖像大小,r = 1, j = 1, start = 0.5。注意,在圖3中,我使用的坐標(biāo)系中,輸入層的第一個(gè)特征的中心位于0.5。通過(guò)遞歸應(yīng)用上述四個(gè)方程,我們可以計(jì)算出CNN中所有feature map的感受野信息。圖3顯示了這些方程如何工作的示例。

我還創(chuàng)建了一個(gè)小型python程序,它計(jì)算給定CNN體系結(jié)構(gòu)中所有層的感受野信息。它還允許你輸入任何特征圖的名稱和該特征圖中特征的索引,并返回相應(yīng)感受野的大小和位置。下圖顯示了使用AlexNet時(shí)的輸出示例。代碼在本文末尾提供。

# [filter size, stride, padding]
#Assume the two dimensions are the same
#Each kernel requires the following parameters:
# - k_i: kernel size
# - s_i: stride
# - p_i: padding (if padding is uneven, right padding will higher than left padding; "SAME" option in tensorflow)
#
#Each layer i requires the following parameters to be fully represented:
# - n_i: number of feature (data layer has n_1 = imagesize )
# - j_i: distance (projected to image pixel distance) between center of two adjacent features
# - r_i: receptive field of a feature in layer i
# - start_i: position of the first feature's receptive field in layer i (idx start from 0, negative means the center fall into padding)
import math
convnet = [[11,4,0],[3,2,0],[5,1,2],[3,2,0],[3,1,1],[3,1,1],[3,1,1],[3,2,0],[6,1,0], [1, 1, 0]]
layer_names = ['conv1','pool1','conv2','pool2','conv3','conv4','conv5','pool5','fc6-conv', 'fc7-conv']
imsize = 227
def outFromIn(conv, layerIn):
n_in = layerIn[0]
j_in = layerIn[1]
r_in = layerIn[2]
start_in = layerIn[3]
k = conv[0]
s = conv[1]
p = conv[2]
n_out = math.floor((n_in - k + 2*p)/s) + 1
actualP = (n_out-1)*s - n_in + k
pR = math.ceil(actualP/2)
pL = math.floor(actualP/2)
j_out = j_in * s
r_out = r_in + (k - 1)*j_in
start_out = start_in + ((k-1)/2 - pL)*j_in
return n_out, j_out, r_out, start_out
def printLayer(layer, layer_name):
print(layer_name + ":")
print("\t n features: %s \n \t jump: %s \n \t receptive size: %s \t start: %s " % (layer[0], layer[1], layer[2], layer[3]))
layerInfos = []
if __name__ == '__main__':
#first layer is the data layer (image) with n_0 = image size; j_0 = 1; r_0 = 1; and start_0 = 0.5
print ("-------Net summary------")
currentLayer = [imsize, 1, 1, 0.5]
printLayer(currentLayer, "input image")
for i in range(len(convnet)):
currentLayer = outFromIn(convnet[i], currentLayer)
layerInfos.append(currentLayer)
printLayer(currentLayer, layer_names[i])
print ("------------------------")
layer_name = raw_input ("Layer name where the feature in: ")
layer_idx = layer_names.index(layer_name)
idx_x = int(raw_input ("index of the feature in x dimension (from 0)"))
idx_y = int(raw_input ("index of the feature in y dimension (from 0)"))
n = layerInfos[layer_idx][0]
j = layerInfos[layer_idx][1]
r = layerInfos[layer_idx][2]
start = layerInfos[layer_idx][3]
assert(idx_x < n)
assert(idx_y < n)
print ("receptive field: (%s, %s)" % (r, r))
print ("center: (%s, %s)" % (start+idx_x*j, start+idx_y*j))

英文原文:https://medium.com/mlreview/a-guide-to-receptive-field-arithmetic-for-convolutional-neural-networks-e0f514068807
好消息!
小白學(xué)視覺(jué)知識(shí)星球
開(kāi)始面向外開(kāi)放啦??????
下載1:OpenCV-Contrib擴(kuò)展模塊中文版教程 在「小白學(xué)視覺(jué)」公眾號(hào)后臺(tái)回復(fù):擴(kuò)展模塊中文教程,即可下載全網(wǎng)第一份OpenCV擴(kuò)展模塊教程中文版,涵蓋擴(kuò)展模塊安裝、SFM算法、立體視覺(jué)、目標(biāo)跟蹤、生物視覺(jué)、超分辨率處理等二十多章內(nèi)容。 下載2:Python視覺(jué)實(shí)戰(zhàn)項(xiàng)目52講 在「小白學(xué)視覺(jué)」公眾號(hào)后臺(tái)回復(fù):Python視覺(jué)實(shí)戰(zhàn)項(xiàng)目,即可下載包括圖像分割、口罩檢測(cè)、車道線檢測(cè)、車輛計(jì)數(shù)、添加眼線、車牌識(shí)別、字符識(shí)別、情緒檢測(cè)、文本內(nèi)容提取、面部識(shí)別等31個(gè)視覺(jué)實(shí)戰(zhàn)項(xiàng)目,助力快速學(xué)校計(jì)算機(jī)視覺(jué)。 下載3:OpenCV實(shí)戰(zhàn)項(xiàng)目20講 在「小白學(xué)視覺(jué)」公眾號(hào)后臺(tái)回復(fù):OpenCV實(shí)戰(zhàn)項(xiàng)目20講,即可下載含有20個(gè)基于OpenCV實(shí)現(xiàn)20個(gè)實(shí)戰(zhàn)項(xiàng)目,實(shí)現(xiàn)OpenCV學(xué)習(xí)進(jìn)階。 交流群
歡迎加入公眾號(hào)讀者群一起和同行交流,目前有SLAM、三維視覺(jué)、傳感器、自動(dòng)駕駛、計(jì)算攝影、檢測(cè)、分割、識(shí)別、醫(yī)學(xué)影像、GAN、算法競(jìng)賽等微信群(以后會(huì)逐漸細(xì)分),請(qǐng)掃描下面微信號(hào)加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺(jué)SLAM“。請(qǐng)按照格式備注,否則不予通過(guò)。添加成功后會(huì)根據(jù)研究方向邀請(qǐng)進(jìn)入相關(guān)微信群。請(qǐng)勿在群內(nèi)發(fā)送廣告,否則會(huì)請(qǐng)出群,謝謝理解~

