Skip to content

Commit 2c49115

Browse files
committed
Merge pull request keras-team#1792 from neggert/pool-border-same
Implement border_mode="same" for pool2d in Theano
2 parents 784d81d + bbaa66c commit 2c49115

File tree

2 files changed

+25
-14
lines changed

2 files changed

+25
-14
lines changed

keras/backend/theano_backend.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -768,10 +768,10 @@ def conv3d(x, kernel, strides=(1, 1, 1), border_mode='valid', dim_ordering='th',
768768
def pool2d(x, pool_size, strides=(1, 1), border_mode='valid',
769769
dim_ordering='th', pool_mode='max'):
770770
if border_mode == 'same':
771-
# TODO: add implementation for border_mode="same"
772-
raise Exception('border_mode="same" not supported with Theano.')
771+
w_pad = pool_size[0] - 2 if pool_size[0] % 2 == 1 else pool_size[0] - 1
772+
h_pad = pool_size[1] - 2 if pool_size[1] % 2 == 1 else pool_size[1] - 1
773+
padding = (w_pad, h_pad)
773774
elif border_mode == 'valid':
774-
ignore_border = True
775775
padding = (0, 0)
776776
else:
777777
raise Exception('Invalid border mode: ' + str(border_mode))
@@ -784,17 +784,25 @@ def pool2d(x, pool_size, strides=(1, 1), border_mode='valid',
784784

785785
if pool_mode == 'max':
786786
pool_out = downsample.max_pool_2d(x, ds=pool_size, st=strides,
787-
ignore_border=ignore_border,
787+
ignore_border=True,
788788
padding=padding,
789789
mode='max')
790790
elif pool_mode == 'avg':
791791
pool_out = downsample.max_pool_2d(x, ds=pool_size, st=strides,
792-
ignore_border=ignore_border,
792+
ignore_border=True,
793793
padding=padding,
794794
mode='average_exc_pad')
795795
else:
796796
raise Exception('Invalid pooling mode: ' + str(pool_mode))
797797

798+
if border_mode == 'same':
799+
expected_width = (x.shape[2] + strides[0] - 1) // strides[0]
800+
expected_height = (x.shape[3] + strides[1] - 1) // strides[1]
801+
802+
pool_out = pool_out[:, :,
803+
: expected_width,
804+
: expected_height]
805+
798806
if dim_ordering == 'tf':
799807
pool_out = pool_out.dimshuffle((0, 2, 3, 1))
800808
return pool_out

tests/keras/layers/test_convolutional.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -191,17 +191,20 @@ def test_averagepooling_2d():
191191
stack_size = 7
192192
input_nb_row = 11
193193
input_nb_col = 12
194-
pool_size = (3, 3)
195194

196195
input = np.ones((nb_samples, stack_size, input_nb_row, input_nb_col))
197-
for strides in [(1, 1), (2, 2)]:
198-
layer = convolutional.AveragePooling2D(strides=strides,
199-
border_mode='valid',
200-
pool_size=pool_size)
201-
layer.input = K.variable(input)
202-
for train in [True, False]:
203-
K.eval(layer.get_output(train))
204-
layer.get_config()
196+
for border_mode in ['valid', 'same']:
197+
for pool_size in [(2, 2), (3, 3), (4, 4), (5, 5)]:
198+
for strides in [(1, 1), (2, 2)]:
199+
layer = convolutional.AveragePooling2D(strides=strides,
200+
border_mode=border_mode,
201+
pool_size=pool_size)
202+
layer.input = K.variable(input)
203+
for train in [True, False]:
204+
out = K.eval(layer.get_output(train))
205+
if border_mode == 'same' and strides == (1, 1):
206+
assert input.shape == out.shape
207+
layer.get_config()
205208

206209

207210
@pytest.mark.skipif(K._BACKEND != 'theano', reason="Requires Theano backend")

0 commit comments

Comments
 (0)