Skip to content

Commit c49206a

Browse files
committed
Add mode and alternative border parameters to CUDNN conv.
- The `mode` now defaults to `cross`, which is what all other packages use and thus it allows loading their weights without needing to fiddle with mirroring/flipping them correctly. - Adds an alternative `border` parameter for these two reasons: 1. So that we have a flexible shortcut for 'same' 2. So that Theano can use some tricks for 'valid' and 'full' The old interface is still available and used since `border=None` by default.
1 parent e6a7ef0 commit c49206a

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

DeepFried2/layers/SpatialConvolutionCUDNN.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,31 @@
88

99

1010
class SpatialConvolutionCUDNN(Module):
11-
def __init__(self, n_input_plane, n_output_plane, k_w, k_h, d_w=1, d_h=1, pad_w=0, pad_h=0, with_bias=True, initW=xavier(), initB=const(0)):
11+
def __init__(self, n_input_plane, n_output_plane, k_w, k_h, d_w=1, d_h=1, pad_w=0, pad_h=0, mode='cross', with_bias=True, initW=xavier(), initB=const(0), border=None):
12+
# mode='cross' is the default in Lasagne[1], Torch[2], matConvNet[3], Caffee[4].
13+
#
14+
# 1: https://github.com/Lasagne/Lasagne/blob/63d44a0d/lasagne/layers/dnn.py#L299
15+
# 2: https://github.com/soumith/cudnn.torch/blob/840f0228/SpatialConvolution.lua#L83
16+
# 3: https://github.com/vlfeat/matconvnet/blob/b7dd9c96/matlab/src/bits/impl/nnconv_cudnn.cu#L133
17+
# 4: https://github.com/BVLC/caffe/blob/50ab52cb/include/caffe/util/cudnn.hpp#L104
18+
#
19+
# `border` is an alternative way to specify `pad_w` and `pad_h` so that Theano strings can be used. Better documentation to follow soon.
1220
Module.__init__(self)
1321
self.n_input_plane = n_input_plane
1422
self.n_output_plane = n_output_plane
1523
self.k_w = k_w
1624
self.k_h = k_h
1725
self.d_w = d_w
1826
self.d_h = d_h
19-
self.pad_w = pad_w
20-
self.pad_h = pad_h
27+
self.mode = mode
2128
self.with_bias = with_bias
2229

30+
# 'same' is a (common) shortcut for "zero-padding so that outshape == inshape".
31+
self.border = border or (pad_h, pad_w)
32+
if self.border == 'same':
33+
assert self.k_w % 2 == 1 and self.k_h % 2 == 1, "'same' convolution only supports odd filter sizes."
34+
self.border = ((self.k_h-1)//2, (self.k_w-1)//2)
35+
2336
w_shape = (n_output_plane, n_input_plane, k_h, k_w)
2437
w_fan = (n_input_plane*k_w*k_h, n_output_plane*k_w*k_h)
2538

@@ -30,8 +43,9 @@ def __init__(self, n_input_plane, n_output_plane, k_w, k_h, d_w=1, d_h=1, pad_w=
3043
def symb_forward(self, symb_input):
3144
conv_output = _dnn.dnn_conv(img=symb_input,
3245
kerns=self.weight,
33-
border_mode=(self.pad_h, self.pad_w),
34-
subsample=(self.d_h, self.d_w))
46+
border_mode=self.border,
47+
subsample=(self.d_h, self.d_w),
48+
conv_mode=self.mode)
3549

3650
if self.with_bias:
3751
return conv_output + self.bias.dimshuffle('x', 0, 'x', 'x')

examples/MNIST/model.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ def net():
2020
def lenet():
2121
model = df.Sequential()
2222
model.add(df.Reshape(-1, 1, 28, 28))
23-
model.add(df.SpatialConvolutionCUDNN(1, 32, 5, 5, 1, 1, 2, 2, with_bias=False))
23+
model.add(df.SpatialConvolutionCUDNN(1, 32, 5, 5, 1, 1, border='same', with_bias=False))
2424
model.add(df.BatchNormalization(32))
2525
model.add(df.ReLU())
2626
model.add(df.SpatialMaxPoolingCUDNN(2, 2))
2727

28-
model.add(df.SpatialConvolutionCUDNN(32, 64, 5, 5, 1, 1, 2, 2, with_bias=False))
28+
model.add(df.SpatialConvolutionCUDNN(32, 64, 5, 5, 1, 1, border='same', with_bias=False))
2929
model.add(df.BatchNormalization(64))
3030
model.add(df.ReLU())
3131
model.add(df.SpatialMaxPoolingCUDNN(2, 2))

0 commit comments

Comments
 (0)