def get_output_shape_for(self, input_shape): if self.output_size is not None: size = self.output_size if isinstance(self.output_size, T.Variable): size = (None, None) return input_shape[0], self.num_filters, size[0], size[1], size[2] # If self.output_size is not specified, return the smallest shape # when called from the constructor, self.crop is still called self.pad: crop = getattr(self, 'crop', getattr(self, 'pad', None)) crop = crop if isinstance(crop, tuple) else (crop, ) * self.n batchsize = input_shape[0] return ((batchsize, self.num_filters) + tuple( conv_input_length(input, filter, stride, p) for input, filter, stride, p in zip( input_shape[2:], self.filter_size, self.stride, crop)))
def test_conv_input_length(): from lasagne.layers.conv import conv_input_length # using the examples from https://github.com/vdumoulin/conv_arithmetic # no padding, no strides assert conv_input_length(2, 3, 1, 'valid') == 4 assert conv_input_length(2, 3, 1, 0) == 4 # padding, no strides assert conv_input_length(6, 4, 1, 2) == 5 # no padding, strides assert conv_input_length(2, 3, 2, 0) == 5 # padding, strides assert conv_input_length(3, 3, 2, 'same') == 5 # full convolution assert conv_input_length(3, 3, 2, 'full') == 3 with pytest.raises(ValueError) as exc: conv_input_length(3, 5, 3, '_nonexistent_mode') assert "Invalid pad: " in exc.value.args[0]