-
Notifications
You must be signed in to change notification settings - Fork 6
/
ReceptiveFieldCalculator.py
82 lines (69 loc) · 2.84 KB
/
ReceptiveFieldCalculator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# [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)
# Source: https://medium.com/mlreview/a-guide-to-receptive-field-arithmetic-for-convolutional-neural-networks-e0f514068807
import math
convnet = [[10, 4, 0], # [filter size, stride, padding]
[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 = 500
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 = "conv1"
layer_idx = layer_names.index(layer_name)
idx_x = 99 #int(raw_input("index of the feature in x dimension (from 0)"))
idx_y = 98 #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))