Пример #1
0
    def initialize_transformer(self, rng):
        """
        This function initializes the transformer of the class. Re-running
        this function will reset the transformer.

        Parameters
        ----------
        rng : object
            random number generator object.
        """
        if self.irange is not None:
            assert self.sparse_init is None
            self.transformer = conv2d.make_random_conv2D(
                irange=self.irange,
                input_space=self.input_space,
                output_space=self.detector_space,
                kernel_shape=self.kernel_shape,
                subsample=self.kernel_stride,
                border_mode=self.border_mode,
                rng=rng)
        elif self.sparse_init is not None:
            self.transformer = conv2d.make_sparse_random_conv2D(
                num_nonzero=self.sparse_init,
                input_space=self.input_space,
                output_space=self.detector_space,
                kernel_shape=self.kernel_shape,
                subsample=self.kernel_stride,
                border_mode=self.border_mode,
                rng=rng)
Пример #2
0
    def initialize_transformer(self, rng):
        """
        This function initializes the transformer of the class. Re-running
        this function will reset the transformer.

        Parameters
        ----------
        rng : object
            random number generator object.
        """
        if self.irange is not None:
            assert self.sparse_init is None
            self.transformer = conv2d.make_random_conv2D(
                    irange=self.irange,
                    input_space=self.input_space,
                    output_space=self.detector_space,
                    kernel_shape=self.kernel_shape,
                    subsample=self.kernel_stride,
                    border_mode=self.border_mode,
                    rng=rng)
        elif self.sparse_init is not None:
            self.transformer = conv2d.make_sparse_random_conv2D(
                    num_nonzero=self.sparse_init,
                    input_space=self.input_space,
                    output_space=self.detector_space,
                    kernel_shape=self.kernel_shape,
                    subsample=self.kernel_stride,
                    border_mode=self.border_mode,
                    rng=rng)
Пример #3
0
    def initialize_transformer(self, rng):
        """
        This function initializes the transformer of the class. Re-running
        this function will reset the transformer.

        X is how I generally call the sparse code variables. 
        Thus, X_space has its dimmensions

        Parameters
        ----------
        rng : object
            random number generator object.
        """

        if self.irange is not None:
            assert self.sparse_init is None
            self.transformer = conv2d.make_random_conv2D(
                    irange=self.irange,
                    input_space=self.x_space,
                    output_space=self.input_space.components[0],
                    kernel_shape=self.kernel_shape,
                    subsample=self.kernel_stride,
                    border_mode=self.border_mode,
                    rng=rng)
        elif self.sparse_init is not None:
            self.transformer = conv2d.make_sparse_random_conv2D(
                    num_nonzero=self.sparse_init,
                    input_space=self.X_space,
                    output_space=self.detector_space,
                    kernel_shape=self.kernel_shape,
                    subsample=self.kernel_stride,
                    border_mode=self.border_mode,
                    rng=rng)
Пример #4
0
    def set_input_space(self, space):
        """ Note: this resets parameters! """

        self.input_space = space
        rng = self.mlp.rng

        if self.border_mode == 'valid':
            output_shape = [
                (self.input_space.shape[0] - self.kernel_shape[0]) /
                self.kernel_stride[0] + 1,
                (self.input_space.shape[1] - self.kernel_shape[1]) /
                self.kernel_stride[1] + 1
            ]
        elif self.border_mode == 'full':
            output_shape = [
                (self.input_space.shape[0] + self.kernel_shape[0]) /
                self.kernel_stride[0] - 1,
                (self.input_space.shape[1] + self.kernel_shape[1]) /
                self.kernel_stride_stride[1] - 1
            ]

        self.output_space = self.detector_space = Conv2DSpace(
            shape=output_shape,
            num_channels=self.output_channels,
            axes=('b', 'c', 0, 1))

        if self.irange is not None:
            assert self.sparse_init is None
            self.transformer = conv2d.make_random_conv2D(
                irange=self.irange,
                input_space=self.input_space,
                output_space=self.detector_space,
                kernel_shape=self.kernel_shape,
                batch_size=self.mlp.batch_size,
                subsample=self.kernel_stride,
                border_mode=self.border_mode,
                rng=rng)
        elif self.sparse_init is not None:
            self.transformer = conv2d.make_sparse_random_conv2D(
                num_nonzero=self.sparse_init,
                input_space=self.input_space,
                output_space=self.detector_space,
                kernel_shape=self.kernel_shape,
                batch_size=self.mlp.batch_size,
                subsample=self.kernel_stride,
                border_mode=self.border_mode,
                rng=rng)
        W, = self.transformer.get_params()
        W.name = 'W'

        self.b = sharedX(self.detector_space.get_origin() + self.init_bias)
        self.b.name = 'b'

        print 'Input shape: ', self.input_space.shape
        print 'Output space: ', self.output_space.shape
Пример #5
0
 def test_make_random_conv2D(self):
     """
     Create a random convolution and check whether the shape, axes and
     input space are all what we expect
     """
     output_space = Conv2DSpace((2, 2), 1)
     conv2d = make_random_conv2D(1, self.input_space, output_space,
                                 (2, 2), 1)
     f = theano.function([self.image_tensor],
                         conv2d.lmul(self.image_tensor))
     assert f(self.image).shape == (1, 2, 2, 1)
     assert conv2d.input_space == self.input_space
     assert conv2d.output_axes == output_space.axes
Пример #6
0
 def test_make_random_conv2D(self):
     """
     Create a random convolution and check whether the shape, axes and
     input space are all what we expect
     """
     output_space = Conv2DSpace((2, 2), 1)
     conv2d = make_random_conv2D(1, self.input_space, output_space,
                                 (2, 2), 1)
     f = theano.function([self.image_tensor],
                         conv2d.lmul(self.image_tensor))
     assert f(self.image).shape == (1, 2, 2, 1)
     assert conv2d.input_space == self.input_space
     assert conv2d.output_axes == output_space.axes
Пример #7
0
    def set_input_space(self, space):
        """ Note: this resets parameters! """

        self.input_space = space
        rng = self.mlp.rng

        if self.border_mode == 'valid':
            output_shape = [(self.input_space.shape[0] - self.kernel_shape[0]) / self.kernel_stride[0] + 1,
                (self.input_space.shape[1] - self.kernel_shape[1]) / self.kernel_stride[1] + 1]
        elif self.border_mode == 'full':
            output_shape = [(self.input_space.shape[0] +  self.kernel_shape[0]) / self.kernel_stride[0] - 1,
                    (self.input_space.shape[1] + self.kernel_shape[1]) / self.kernel_stride_stride[1] - 1]

        self.output_space = self.detector_space = Conv2DSpace(shape=output_shape,
                num_channels = self.output_channels,
                axes = ('b', 'c', 0, 1))

        if self.irange is not None:
            assert self.sparse_init is None
            self.transformer = conv2d.make_random_conv2D(
                    irange = self.irange,
                    input_space = self.input_space,
                    output_space = self.detector_space,
                    kernel_shape = self.kernel_shape,
                    batch_size = self.mlp.batch_size,
                    subsample = self.kernel_stride,
                    border_mode = self.border_mode,
                    rng = rng)
        elif self.sparse_init is not None:
            self.transformer = conv2d.make_sparse_random_conv2D(
                    num_nonzero = self.sparse_init,
                    input_space = self.input_space,
                    output_space = self.detector_space,
                    kernel_shape = self.kernel_shape,
                    batch_size = self.mlp.batch_size,
                    subsample = self.kernel_stride,
                    border_mode = self.border_mode,
                    rng = rng)
        W, = self.transformer.get_params()
        W.name = 'W'

        self.b = sharedX(self.detector_space.get_origin() + self.init_bias)
        self.b.name = 'b'

        print 'Input shape: ', self.input_space.shape
        print 'Output space: ', self.output_space.shape
Пример #8
0
    def __init__(self, input_space, output_channels, pool_shape, batch_size=None, detector_axes=('b', 'c', 0, 1), 
                    kernel_shape=(2,2), kernel_stride=(1, 1), border_mode='valid', 
                    transformer=None, h_bias=None, v_bias=None, numpy_rng=None,theano_rng=None):
        """
        vis_space: Conv2DSpace
        transformer: pylearn2.linear.Conv2D instance
        h_bias: vector, 大小等于输出的feature maps数,每个分量对应一个feature map
        v_bias: vector, 大小等于输入的feature maps数,每个分量对应一个feature map
        pool_shape:
        pool_stride: 根据Honglak Lee的原文,pool区域无交叠,于是要求pool_stride=pool_shape,因此暂时不单独设置pool_stride参数
        需要注意,对于卷积RBM,其隐层对应于卷积后的detector_layer,而输出则对应与pool_layer,因此相对于普通RBM只有输入和输出两个space,CRBM有三个space
        """
        Model.__init__(self) # self.names_to_del = set(); self._test_batch_size = 2
        Block.__init__(self) # self.fn = None; self.cpu_only = False
        
        self.kernel_shape = kernel_shape
        self.kernel_stride = kernel_stride
        self.pool_shape = pool_shape
        self.pool_stride = pool_shape
        self.border_mode = border_mode
        
        self.batch_size = batch_size
        self.force_batch_size = batch_size
        
        input_shape = input_space.shape
        input_channels = input_space.num_channels
        if self.border_mode == 'valid':
            detector_shape = [(input_shape[0] - kernel_shape[0])/int(kernel_stride[0]) + 1, (input_shape[1] - kernel_shape[1])/kernel_stride[1] + 1]
        elif self.border_mode == 'full':
            detector_shape = [(input_shape[0] + kernel_shape[0])/int(kernel_stride[0]) - 1, (input_shape[1] + kernel_shape[1])/kernel_stride[1] - 1]
        
        assert isinstance(input_space, Conv2DSpace)
        self.input_space = input_space # add input_space
        self.detector_space = Conv2DSpace(shape=detector_shape, num_channels=output_channels, axes=detector_axes) # add detector_space
        
        #当前只考虑detector layer的feature map可以被pool_shape无交叠完整分割的情况
        #今后需要补充:边缘补齐的情况
        output_shape = (detector_shape[0] / pool_shape[0], detector_shape[1] / pool_shape[1])
        self.output_space = Conv2DSpace(shape=output_shape, num_channels=output_channels, axes=detector_axes) # add output_space

        self.n_vis = numpy.prod(input_space.shape) * input_space.num_channels
        self.n_hid = detector_shape[0] * detector_shape[1] * output_channels

        if numpy_rng is None:
            # create a number generator
            numpy_rng = numpy.random.RandomState(seed=19900418)
        self.numpy_rng = numpy_rng

        if theano_rng is None:
            theano_rng = RandomStreams(numpy_rng.randint(2 ** 30))
        self.theano_rng = theano_rng

        if transformer is None:
            irange = 4 * numpy.sqrt(6. / (self.n_hid + self.n_vis))
            transformer = make_random_conv2D(irange=irange, input_space=self.input_space, output_space=self.detector_space, 
                                             kernel_shape = self.kernel_shape, batch_size = self.batch_size, 
                                             subsample = kernel_stride,border_mode = self.border_mode, rng=self.numpy_rng)
        else:
            assert isinstance(transformer, Conv2D)

        if h_bias is None:
            # create shared variable for hidden units bias
            h_bias = theano.shared(value=numpy.zeros(self.detector_space.num_channels, dtype=theano.config.floatX), name='h_bias', borrow=True)

        if v_bias is None:
            # create shared variable for visible units bias
            v_bias = theano.shared(value=numpy.zeros(self.input_space.num_channels, dtype=theano.config.floatX), name='v_bias', borrow=True)

        self.transformer = transformer
        self.h_bias = h_bias
        self.v_bias = v_bias

        self._params = safe_union(self.transformer.get_params(), [self.h_bias, self.v_bias])
Пример #9
0
    def set_input_space(self, space):

        self.input_space = space

        if not isinstance(space, Conv2DSpace):
            raise BadInputSpaceError("ConvRectifiedLinear.set_input_space "
                                     "expected a Conv2DSpace, got " +
                                     str(space) + " of type " +
                                     str(type(space)))

        rng = self.mlp.rng

        if self.border_mode == 'valid':
            output_shape = [
                (self.input_space.shape[0] - self.kernel_shape[0]) /
                self.kernel_stride[0] + 1,
                (self.input_space.shape[1] - self.kernel_shape[1]) /
                self.kernel_stride[1] + 1
            ]
        elif self.border_mode == 'full':
            output_shape = [
                (self.input_space.shape[0] + self.kernel_shape[0]) /
                self.kernel_stride[0] - 1,
                (self.input_space.shape[1] + self.kernel_shape[1]) /
                self.kernel_stride[1] - 1
            ]

        self.detector_space = Conv2DSpace(shape=output_shape,
                                          num_channels=self.output_channels,
                                          axes=('b', 'c', 0, 1))

        if self.irange is not None:
            assert self.sparse_init is None
            self.transformer = conv2d.make_random_conv2D(
                irange=self.irange,
                input_space=self.input_space,
                output_space=self.detector_space,
                kernel_shape=self.kernel_shape,
                batch_size=self.mlp.batch_size,
                subsample=self.kernel_stride,
                border_mode=self.border_mode,
                rng=rng)
        elif self.sparse_init is not None:
            self.transformer = conv2d.make_sparse_random_conv2D(
                num_nonzero=self.sparse_init,
                input_space=self.input_space,
                output_space=self.detector_space,
                kernel_shape=self.kernel_shape,
                batch_size=self.mlp.batch_size,
                subsample=self.kernel_stride,
                border_mode=self.border_mode,
                rng=rng)

        W, = self.transformer.get_params()
        W.name = 'W'
        self.b = sharedX(
            np.zeros(((self.num_pieces * self.output_channels), )) +
            self.init_bias)
        self.b.name = 'b'

        print 'Input shape: ', self.input_space.shape
        print 'Detector space: ', self.detector_space.shape

        assert self.pool_type in ['max', 'mean']

        dummy_batch_size = self.mlp.batch_size
        if dummy_batch_size is None:
            dummy_batch_size = 2
        dummy_detector = sharedX(
            self.detector_space.get_origin_batch(dummy_batch_size))

        #dummy_p = dummy_p.eval()
        self.output_space = Conv2DSpace(shape=[400, 1],
                                        num_channels=self.output_channels,
                                        axes=('b', 'c', 0, 1))

        W = rng.uniform(-self.irange, self.irange,
                        (426, (self.num_pieces * self.output_channels)))
        W = sharedX(W)
        W.name = self.layer_name + "_w"
        self.transformer = MatrixMul(W)

        print 'Output space: ', self.output_space.shape
Пример #10
0
    def set_input_space(self, space):
        """ Note: this resets parameters! """

        self.input_space = space
        rng = self.mlp.rng

        if self.border_mode == "valid":
            output_shape = [
                self.input_space.shape[0] - self.kernel_shape[0] + 1,
                self.input_space.shape[1] - self.kernel_shape[1] + 1,
            ]
        elif self.border_mode == "full":
            output_shape = [
                self.input_space.shape[0] + self.kernel_shape[0] - 1,
                self.input_space.shape[1] + self.kernel_shape[1] - 1,
            ]

        self.detector_space = Conv2DSpace(shape=output_shape, num_channels=self.output_channels, axes=("b", "c", 0, 1))

        if self.irange is not None:
            assert self.sparse_init is None
            self.transformer = conv2d.make_random_conv2D(
                irange=self.irange,
                input_space=self.input_space,
                output_space=self.detector_space,
                kernel_shape=self.kernel_shape,
                batch_size=self.mlp.batch_size,
                subsample=(1, 1),
                border_mode=self.border_mode,
                rng=rng,
            )
        elif self.sparse_init is not None:
            self.transformer = conv2d.make_sparse_random_conv2D(
                num_nonzero=self.sparse_init,
                input_space=self.input_space,
                output_space=self.detector_space,
                kernel_shape=self.kernel_shape,
                batch_size=self.mlp.batch_size,
                subsample=(1, 1),
                border_mode=self.border_mode,
                rng=rng,
            )
        W, = self.transformer.get_params()
        W.name = "W"

        self.b = sharedX(self.detector_space.get_origin() + self.init_bias)
        self.b.name = "b"

        print "Input shape: ", self.input_space.shape
        print "Detector space: ", self.detector_space.shape

        if self.mlp.batch_size is None:
            raise ValueError(
                "Tried to use a convolutional layer with an MLP that has "
                "no batch size specified. You must specify the batch size of the "
                "model because theano requires the batch size to be known at "
                "graph construction time for convolution."
            )

        assert self.pool_type in ["max", "mean"]

        dummy_detector = sharedX(self.detector_space.get_origin_batch(self.mlp.batch_size))
        if self.pool_type == "max":
            dummy_p = max_pool(
                bc01=dummy_detector,
                pool_shape=self.pool_shape,
                pool_stride=self.pool_stride,
                image_shape=self.detector_space.shape,
                output_channels=self.output_channels,
            )
        elif self.pool_type == "mean":
            dummy_p = mean_pool(
                bc01=dummy_detector,
                pool_shape=self.pool_shape,
                pool_stride=self.pool_stride,
                image_shape=self.detector_space.shape,
            )
        dummy_p = dummy_p.eval()
        self.tmp_output_space = Conv2DSpace(
            shape=[dummy_p.shape[2], dummy_p.shape[3]], num_channels=1, axes=("b", "c", 0, 1)  # self.output_channels,
        )

        if self.crop_border:
            self.output_space = self.input_space
        else:
            self.output_space = self.tmp_output_space

        print "Output space: ", self.output_space.shape
    def set_input_space(self, space):

        self.input_space = space

        if not isinstance(space, Conv2DSpace):
            raise BadInputSpaceError("ConvRectifiedLinear.set_input_space "
                                     "expected a Conv2DSpace, got " +
                                     str(space) + " of type " +
                                     str(type(space)))

        rng = self.mlp.rng

        if self.border_mode == 'valid':
            output_shape = [(self.input_space.shape[0]-self.kernel_shape[0]) /
                            self.kernel_stride[0] + 1,
                            (self.input_space.shape[1]-self.kernel_shape[1]) /
                            self.kernel_stride[1] + 1]
        elif self.border_mode == 'full':
            output_shape = [(self.input_space.shape[0]+self.kernel_shape[0]) /
                            self.kernel_stride[0] - 1,
                            (self.input_space.shape[1]+self.kernel_shape[1]) /
                            self.kernel_stride[1] - 1]

        self.detector_space = Conv2DSpace(shape=output_shape,
                                          num_channels=self.output_channels,
                                          axes=('b', 'c', 0, 1))

        if self.irange is not None:
            assert self.sparse_init is None
            self.transformer = conv2d.make_random_conv2D(
                irange=self.irange,
                input_space=self.input_space,
                output_space=self.detector_space,
                kernel_shape=self.kernel_shape,
                batch_size=self.mlp.batch_size,
                subsample=self.kernel_stride,
                border_mode=self.border_mode,
                rng=rng)
        elif self.sparse_init is not None:
            self.transformer = conv2d.make_sparse_random_conv2D(
                num_nonzero=self.sparse_init,
                input_space=self.input_space,
                output_space=self.detector_space,
                kernel_shape=self.kernel_shape,
                batch_size=self.mlp.batch_size,
                subsample=self.kernel_stride,
                border_mode=self.border_mode,
                rng=rng)

        W, = self.transformer.get_params()
        W.name = 'W'
        self.b = sharedX(np.zeros(((self.num_pieces*self.output_channels),)) + self.init_bias)
        self.b.name = 'b'

        print 'Input shape: ', self.input_space.shape
        print 'Detector space: ', self.detector_space.shape

        assert self.pool_type in ['max', 'mean']

        dummy_batch_size = self.mlp.batch_size
        if dummy_batch_size is None:
            dummy_batch_size = 2
        dummy_detector = sharedX(
            self.detector_space.get_origin_batch(dummy_batch_size))
            
            
        #dummy_p = dummy_p.eval()
        self.output_space = Conv2DSpace(shape=[1, 1],
                                        num_channels=self.output_channels,
                                        axes=('b', 'c', 0, 1))
										
        W = rng.uniform(-self.irange,self.irange,(426, (self.num_pieces*self.output_channels)))
        W = sharedX(W)
        W.name = self.layer_name + "_w"
        self.transformer = MatrixMul(W)
		
        print 'Output space: ', self.output_space.shape
Пример #12
0
    def set_input_space(self, space):
        """ Note: this resets parameters! """

        self.input_space = space
        rng = self.mlp.rng

        if self.border_mode == 'valid':
            output_shape = [(self.input_space.shape[0] - self.kernel_shape[0]) / self.kernel_stride[0] + 1,
                (self.input_space.shape[1] - self.kernel_shape[1]) / self.kernel_stride[1] + 1]
        elif self.border_mode == 'full':
            output_shape = [(self.input_space.shape[0] +  self.kernel_shape[0]) / self.kernel_stride[0] - 1,
                    (self.input_space.shape[1] + self.kernel_shape[1]) / self.kernel_stride_stride[1] - 1]

        self.detector_space = Conv2DSpace(shape=output_shape,
                num_channels = self.output_channels,
                axes = ('b', 'c', 0, 1))

        if not (self.can_alter_transformer and hasattr(self, "transformer")
                and self.transformer is not None):

            if self.irange is not None:
                self.transformer = conv2d.make_random_conv2D(
                        irange = self.irange,
                        input_space = self.input_space,
                        output_space = self.detector_space,
                        kernel_shape = self.kernel_shape,
                        batch_size = self.mlp.batch_size,
                        subsample = self.kernel_stride,
                        border_mode = self.border_mode,
                        rng = rng)
        else:
            filters_shape = self.transformer._filters.get_value().shape
            if (self.input_space.filters_shape[-2:-1] != self.kernel_shape or
                    self.input_space.filters_shape != filters_shape):
                raise ValueError("The filters and input space don't have compatible input space.")
            if self.input_space.num_channels != filters_shape[1]:
                raise ValueError("The filters and input space don't have compatible number of channels.")

        W, = self.transformer.get_params()
        W.name = 'W'

        if not (self.can_alter_biases and hasattr(self, "b")
                and self.b is not None):
            self.b = sharedX(self.detector_space.get_origin() + self.init_bias)
            self.b.name = 'b'

        print 'Input shape: ', self.input_space.shape
        print 'Detector space: ', self.detector_space.shape


        dummy_batch_size = self.mlp.batch_size
        if dummy_batch_size is None:
            dummy_batch_size = 2
        dummy_detector = sharedX(self.detector_space.get_origin_batch(dummy_batch_size))

        if self.pool_type is not None:
            assert self.pool_type in ['max', 'mean']
            if self.pool_type == 'max':
                dummy_p = max_pool(bc01=dummy_detector, pool_shape=self.pool_shape,
                        pool_stride=self.pool_stride,
                        image_shape=self.detector_space.shape)
            elif self.pool_type == 'mean':
                dummy_p = mean_pool(bc01=dummy_detector, pool_shape=self.pool_shape,
                        pool_stride=self.pool_stride,
                        image_shape=self.detector_space.shape)
            dummy_p = dummy_p.eval()
            self.output_space = Conv2DSpace(shape=[dummy_p.shape[2], dummy_p.shape[3]],
                    num_channels = self.output_channels, axes = ('b', 'c', 0, 1) )
        else:
            dummy_detector = dummy_detector.eval()
            self.output_space = Conv2DSpace(shape=[dummy_detector.shape[2], dummy_detector.shape[3]],
                    num_channels = self.output_channels, axes = ('b', 'c', 0, 1) )

        print 'Output space: ', self.output_space.shape
    def set_input_space(self, space):
        """ Note: this resets parameters! """

        self.input_space = space
        rng = self.mlp.rng

        if self.border_mode == 'valid':
            output_shape = [
                self.input_space.shape[0] - self.kernel_shape[0] + 1,
                self.input_space.shape[1] - self.kernel_shape[1] + 1
            ]
        elif self.border_mode == 'full':
            output_shape = [
                self.input_space.shape[0] + self.kernel_shape[0] - 1,
                self.input_space.shape[1] + self.kernel_shape[1] - 1
            ]

        self.detector_space = Conv2DSpace(shape=output_shape,
                                          num_channels=self.output_channels,
                                          axes=('b', 'c', 0, 1))

        if self.irange is not None:
            assert self.sparse_init is None
            self.transformer = conv2d.make_random_conv2D(
                irange=self.irange,
                input_space=self.input_space,
                output_space=self.detector_space,
                kernel_shape=self.kernel_shape,
                batch_size=self.mlp.batch_size,
                subsample=(1, 1),
                border_mode=self.border_mode,
                rng=rng)
        elif self.sparse_init is not None:
            self.transformer = conv2d.make_sparse_random_conv2D(
                num_nonzero=self.sparse_init,
                input_space=self.input_space,
                output_space=self.detector_space,
                kernel_shape=self.kernel_shape,
                batch_size=self.mlp.batch_size,
                subsample=(1, 1),
                border_mode=self.border_mode,
                rng=rng)
        W, = self.transformer.get_params()
        W.name = 'W'

        self.b = sharedX(self.detector_space.get_origin() + self.init_bias)
        self.b.name = 'b'

        print 'Input shape: ', self.input_space.shape
        print 'Detector space: ', self.detector_space.shape

        if self.mlp.batch_size is None:
            raise ValueError(
                "Tried to use a convolutional layer with an MLP that has "
                "no batch size specified. You must specify the batch size of the "
                "model because theano requires the batch size to be known at "
                "graph construction time for convolution.")

        assert self.pool_type in ['max', 'mean']

        dummy_detector = sharedX(
            self.detector_space.get_origin_batch(self.mlp.batch_size))
        if self.pool_type == 'max':
            dummy_p = max_pool(bc01=dummy_detector,
                               pool_shape=self.pool_shape,
                               pool_stride=self.pool_stride,
                               image_shape=self.detector_space.shape)
        elif self.pool_type == 'mean':
            dummy_p = mean_pool(bc01=dummy_detector,
                                pool_shape=self.pool_shape,
                                pool_stride=self.pool_stride,
                                image_shape=self.detector_space.shape)
        dummy_p = dummy_p.eval()
        self.output_space = Conv2DSpace(
            shape=[dummy_p.shape[2], dummy_p.shape[3]],
            num_channels=self.output_channels,
            axes=('b', 'c', 0, 1))

        print 'Output space: ', self.output_space.shape