From 43736166a473cd0eea04e18c85d0501d567bf61e Mon Sep 17 00:00:00 2001 From: fchollet Date: Thu, 16 Jul 2015 14:18:05 +0900 Subject: [PATCH] Touch-ups to 'same' border mode --- docs/sources/layers/convolutional.md | 2 +- keras/layers/convolutional.py | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/sources/layers/convolutional.md b/docs/sources/layers/convolutional.md index 0eb9018f6..7cc13d153 100644 --- a/docs/sources/layers/convolutional.md +++ b/docs/sources/layers/convolutional.md @@ -58,7 +58,7 @@ Convolution operator for filtering windows of two-dimensional inputs. - __init__: name of initialization function for the weights of the layer (see: [initializations](../initializations.md)), or alternatively, Theano function to use for weights initialization. This parameter is only relevant if you don't pass a `weights` argument. - __activation__: name of activation function to use (see: [activations](../activations.md)), or alternatively, elementwise Theano function. If you don't specify anything, no activation is applied (ie. "linear" activation: a(x) = x). - __weights__: list of numpy arrays to set as initial weights. - - __border_mode__: 'valid' or 'full'. see scipy.signal.convolve2d. + - __border_mode__: 'valid', 'full', or 'same'. See scipy.signal.convolve2d. - __subsample__: tuple of length 2. Factor by which to subsample output. Also called strides elsewhere. - __W_regularizer__: instance of [WeightRegularizer](../regularizers.md) (eg. L1 or L2 regularization), applied to the main weights matrix. - __b_regularizer__: instance of [WeightRegularizer](../regularizers.md), applied to the bias. diff --git a/keras/layers/convolutional.py b/keras/layers/convolutional.py index 59effc5b9..f69978325 100644 --- a/keras/layers/convolutional.py +++ b/keras/layers/convolutional.py @@ -16,8 +16,10 @@ class Convolution1D(Layer): border_mode='valid', subsample_length=1, W_regularizer=None, b_regularizer=None, activity_regularizer=None, W_constraint=None, b_constraint=None): - super(Convolution1D,self).__init__() + if border_mode not in {'valid', 'full'}: + raise Exception('Invalid border mode for Convolution1D:', border_mode) + super(Convolution1D,self).__init__() self.nb_filter = nb_filter self.input_dim = input_dim self.filter_length = filter_length @@ -104,6 +106,9 @@ class Convolution2D(Layer): border_mode='valid', subsample=(1, 1), W_regularizer=None, b_regularizer=None, activity_regularizer=None, W_constraint=None, b_constraint=None): + if border_mode not in {'valid', 'full', 'same'}: + raise Exception('Invalid border mode for Convolution2D:', border_mode) + super(Convolution2D,self).__init__() self.init = initializations.get(init) self.activation = activations.get(activation) @@ -140,19 +145,18 @@ class Convolution2D(Layer): def get_output(self, train): X = self.get_input(train) - temp_mode = self.border_mode - if temp_mode == 'same': - temp_mode = 'full' # just for the conv2d in the line below - # output will be bigger but then we crop from it + border_mode = self.border_mode + if border_mode == 'same': + border_mode = 'full' + conv_out = theano.tensor.nnet.conv.conv2d(X, self.W, - border_mode=temp_mode, subsample=self.subsample) + border_mode=border_mode, subsample=self.subsample) output = self.activation(conv_out + self.b.dimshuffle('x', 0, 'x', 'x')) if self.border_mode == 'same': - clip_row = (self.nb_row - 1)//2 - clip_col = (self.nb_col - 1)//2 - output = output[:,:,clip_row:-clip_row,clip_col:-clip_col] - + clip_row = (self.nb_row - 1) // 2 + clip_col = (self.nb_col - 1) // 2 + output = output[:, :, clip_row:-clip_row, clip_col:-clip_col] return output def get_config(self): @@ -206,7 +210,3 @@ class ZeroPadding2D(Layer): def get_config(self): return {"name":self.__class__.__name__, "width":self.width} - -# class Convolution3D: TODO - -# class MaxPooling3D: TODO