def test_convolutional(): x = tensor.tensor4("x") num_channels = 4 num_filters = 3 batch_size = 5 filter_size = (3, 3) conv = Convolutional( filter_size, num_filters, num_channels, image_size=(17, 13), weights_init=Constant(1.0), biases_init=Constant(5.0), ) conv.initialize() y = conv.apply(x) func = function([x], y) x_val = numpy.ones((batch_size, num_channels, 17, 13), dtype=theano.config.floatX) assert_allclose( func(x_val), numpy.prod(filter_size) * num_channels * numpy.ones((batch_size, num_filters, 15, 11)) + 5 ) conv.image_size = (17, 13) conv.batch_size = 2 # This should have effect on get_dim assert conv.get_dim("output") == (num_filters, 15, 11)
def conv_layer(self, name, wt, bias, image_size): """Creates a Convolutional brick with the given name, weights, bias, and image_size.""" layer = Convolutional( name=name, filter_size=wt.shape[0:2], num_channels=wt.shape[2], # in num_filters=wt.shape[3], # out weights_init=Constant(0), # does not matter biases_init=Constant(0), # does not matter tied_biases=True, border_mode='valid', ) if image_size: layer.image_size = image_size layer.initialize() weights = self.to_bc01(wt) layer.parameters[0].set_value(weights.astype("float32")) # W layer.parameters[1].set_value(bias.squeeze().astype("float32")) # b return (layer, layer.get_dim("output")[1:3])
def test_convolutional(): x = tensor.tensor4('x') num_channels = 4 num_filters = 3 batch_size = 5 filter_size = (3, 3) conv = Convolutional(filter_size, num_filters, num_channels, image_size=(17, 13), weights_init=Constant(1.), biases_init=Constant(5.)) conv.initialize() y = conv.apply(x) func = function([x], y) x_val = numpy.ones((batch_size, num_channels, 17, 13), dtype=theano.config.floatX) assert_allclose( func(x_val), numpy.prod(filter_size) * num_channels * numpy.ones( (batch_size, num_filters, 15, 11)) + 5) conv.image_size = (17, 13) conv.batch_size = 2 # This should have effect on get_dim assert conv.get_dim('output') == (num_filters, 15, 11)
def test_no_input_size(): # suppose x is outputted by some RNN x = tensor.tensor4('x') filter_size = (1, 3) num_filters = 2 num_channels = 5 c = Convolutional(filter_size, num_filters, num_channels, tied_biases=True, weights_init=Constant(1.), biases_init=Constant(1.)) c.initialize() out = c.apply(x) assert c.get_dim('output') == (2, None, None) assert out.ndim == 4 c = Convolutional(filter_size, num_filters, num_channels, tied_biases=False, weights_init=Constant(1.), biases_init=Constant(1.)) assert_raises_regexp(ValueError, 'Cannot infer bias size \S+', c.initialize)
def conv_layer(self, name, wt, bias, image_size): """Creates a Convolutional brick with the given name, weights, bias, and image_size.""" layer = Convolutional( name=name, filter_size=wt.shape[0:2], num_channels=wt.shape[2], # in num_filters=wt.shape[3], # out weights_init=Constant(0), # does not matter biases_init=Constant(0), # does not matter tied_biases=True, border_mode="valid", ) if image_size: layer.image_size = image_size layer.initialize() weights = self.to_bc01(wt) layer.parameters[0].set_value(weights.astype("float32")) # W layer.parameters[1].set_value(bias.squeeze().astype("float32")) # b return (layer, layer.get_dim("output")[1:3])
class ConvolutionalActivation(Initializable): """A convolution followed by an activation function. Parameters ---------- activation : :class:`.BoundApplication` The application method to apply after convolution (i.e. the nonlinear activation function) See Also -------- :class:`Convolutional` : For the documentation of other parameters. """ @lazy(allocation=['filter_size', 'num_filters', 'num_channels']) def __init__(self, activation, filter_size, num_filters, num_channels, batch_size=None, image_size=None, step=(1, 1), border_mode='valid', tied_biases=False, **kwargs): self.convolution = Convolutional(name='conv'+ kwargs['name']) self.bn = BatchNorm(name='bn'+ kwargs['name']) self.activation = activation self.filter_size = filter_size self.num_filters = num_filters self.num_channels = num_channels self.batch_size = batch_size self.image_size = image_size self.step = step self.border_mode = border_mode self.tied_biases = tied_biases super(ConvolutionalActivation, self).__init__(**kwargs) self.children = [self.convolution, self.bn, self.activation] def _push_allocation_config(self): for attr in ['filter_size', 'num_filters', 'step', 'border_mode', 'batch_size', 'num_channels', 'image_size', 'tied_biases']: setattr(self.convolution, attr, getattr(self, attr)) setattr(self.bn, 'input_dim', self.num_filters) def get_dim(self, name): # TODO The name of the activation output doesn't need to be `output` return self.convolution.get_dim(name) def apply(self, input_): out = self.convolution.apply(input_) out = self.bn.apply(out) out = self.activation.apply(out) return out def inference(self, input_): out = self.convolution.apply(input_) out = self.bn.inference(out) out = self.activation.apply(out) return out
class ConvolutionalActivation(Sequence, Initializable): """A convolution followed by an activation function. Parameters ---------- activation : :class:`.BoundApplication` The application method to apply after convolution (i.e. the nonlinear activation function) See Also -------- :class:`Convolutional` for the other parameters. """ @lazy(allocation=['filter_size', 'num_filters', 'num_channels']) def __init__(self, activation, filter_size, num_filters, num_channels, batch_size=None, image_size=None, step=(1, 1), border_mode='valid', **kwargs): self.convolution = Convolutional() self.filter_size = filter_size self.num_filters = num_filters self.num_channels = num_channels self.batch_size = batch_size self.image_size = image_size self.step = step self.border_mode = border_mode super(ConvolutionalActivation, self).__init__( application_methods=[self.convolution.apply, activation], **kwargs) def _push_allocation_config(self): for attr in [ 'filter_size', 'num_filters', 'step', 'border_mode', 'batch_size', 'num_channels', 'image_size' ]: setattr(self.convolution, attr, getattr(self, attr)) def get_dim(self, name): # TODO The name of the activation output doesn't need to be `output` return self.convolution.get_dim(name)
class ConvolutionalActivation(Sequence, Initializable): """A convolution followed by an activation function. Parameters ---------- activation : :class:`.BoundApplication` The application method to apply after convolution (i.e. the nonlinear activation function) See Also -------- :class:`Convolutional` for the other parameters. """ @lazy(allocation=['filter_size', 'num_filters', 'num_channels']) def __init__(self, activation, filter_size, num_filters, num_channels, batch_size=None, image_size=None, step=(1, 1), border_mode='valid', **kwargs): self.convolution = Convolutional() self.filter_size = filter_size self.num_filters = num_filters self.num_channels = num_channels self.batch_size = batch_size self.image_size = image_size self.step = step self.border_mode = border_mode super(ConvolutionalActivation, self).__init__( application_methods=[self.convolution.apply, activation], **kwargs) def _push_allocation_config(self): for attr in ['filter_size', 'num_filters', 'step', 'border_mode', 'batch_size', 'num_channels', 'image_size']: setattr(self.convolution, attr, getattr(self, attr)) def get_dim(self, name): # TODO The name of the activation output doesn't need to be `output` return self.convolution.get_dim(name)
o = X.reshape((X.shape[0], 1, 28, 28)) l = Convolutional(filter_size=(5, 5), num_filters=32, num_channels=1, image_size=(28, 28), weights_init=IsotropicGaussian(std=0.01), biases_init=IsotropicGaussian(std=0.01, mean=1.0), use_bias=True, border_mode="valid", step=(1, 1)) l.initialize() o = l.apply(o) l = BatchNormalizationConv(input_shape=l.get_dim("output"), B_init=IsotropicGaussian(std=0.01), Y_init=IsotropicGaussian(std=0.01)) l.initialize() o = l.apply(o) o = Rectifier().apply(o) l = MaxPooling(pooling_size=(2, 2), step=(2, 2), input_dim=l.get_dim("output")) l.initialize() o = l.apply(o) #ll = Dropout(p_drop=0.5) #ll.initialize() #o = ll.apply(o)
class ResidualConvolutional(Initializable): @lazy(allocation=['filter_size', 'num_filters', 'num_channels']) def __init__(self, filter_size, num_filters, num_channels, batch_size=None, mid_noise=False, out_noise=False, tied_noise=False, tied_sigma=False, noise_rate=None, noise_batch_size=None, prior_noise_level=None, image_size=(None, None), step=(1, 1), **kwargs): self.filter_size = filter_size self.num_filters = num_filters self.batch_size = batch_size self.num_channels = num_channels self.image_size = image_size self.mid_noise = mid_noise self.noise_batch_size = noise_batch_size self.noise_rate = noise_rate self.step = step self.border_mode = 'half' self.tied_biases = True depth = 2 self.b0 = SpatialBatchNormalization(name='b0') self.r0 = Rectifier(name='r0') self.n0 = (SpatialNoise(name='n0', noise_rate=self.noise_rate, tied_noise=tied_noise, tied_sigma=tied_sigma, prior_noise_level=prior_noise_level) if mid_noise else None) self.c0 = Convolutional(name='c0') self.b1 = SpatialBatchNormalization(name='b1') self.r1 = Rectifier(name='r1') self.n1 = (SpatialNoise(name='n1', noise_rate=self.noise_rate, tied_noise=tied_noise, tied_sigma=tied_sigma, prior_noise_level=prior_noise_level) if out_noise else None) self.c1 = Convolutional(name='c1') kwargs.setdefault('children', []).extend([c for c in [ self.c0, self.b0, self.r0, self.n0, self.c1, self.b1, self.r1, self.n1] if c is not None]) super(ResidualConvolutional, self).__init__(**kwargs) def get_dim(self, name): if name == 'input_': return ((self.num_channels,) + self.image_size) if name == 'output': return self.c1.get_dim(name) return super(ResidualConvolutionalUnit, self).get_dim(name) @property def num_output_channels(self): return self.num_filters def _push_allocation_config(self): self.b0.input_dim = self.get_dim('input_') self.b0.push_allocation_config() if self.r0: self.r0.push_allocation_config() if self.n0: self.n0.noise_batch_size = self.noise_batch_size self.n0.num_channels = self.num_channels self.n0.image_size = self.image_size self.c0.filter_size = self.filter_size self.c0.batch_size = self.batch_size self.c0.num_channels = self.num_channels self.c0.num_filters = self.num_filters self.c0.border_mode = self.border_mode self.c0.image_size = self.image_size self.c0.step = self.step self.c0.use_bias = False self.c0.push_allocation_config() c0_shape = self.c0.get_dim('output') self.b1.input_dim = c0_shape self.b1.push_allocation_config() self.r1.push_allocation_config() if self.n1: self.n1.noise_batch_size = self.noise_batch_size self.n1.num_channels = self.num_filters self.n1.image_size = c0_shape[1:] self.c1.filter_size = self.filter_size self.c1.batch_size = self.batch_size self.c1.num_channels = self.num_filters self.c1.num_filters = self.num_filters self.c1.border_mode = self.border_mode self.c1.image_size = c0_shape[1:] self.c1.step = (1, 1) self.c1.use_bias = False self.c1.push_allocation_config() @application(inputs=['input_'], outputs=['output']) def apply(self, input_): shortcut = input_ # Batchnorm, then Relu, then Convolution first_conv = self.b0.apply(input_) first_conv = self.r0.apply(first_conv) if self.n0: first_conv = self.n0.apply(first_conv) first_conv = self.c0.apply(first_conv) # Batchnorm, then Relu, then Convolution (second time) second_conv = self.b1.apply(first_conv) second_conv = self.r1.apply(second_conv) if self.n1: second_conv = self.n1.apply(second_conv) residual = second_conv # Apply stride and zero-padding to match shortcut to output if self.step and self.step != (1, 1): shortcut = shortcut[:,:,::self.step[0],::self.step[1]] if self.num_filters > self.num_channels: padshape = (residual.shape[0], self.num_filters - self.num_channels, residual.shape[2], residual.shape[3]) shortcut = tensor.concatenate( [shortcut, tensor.zeros(padshape, dtype=residual.dtype)], axis=1) elif self.num_filters < self.num_channels: shortcut = shortcut[:,:self.num_channels,:,:] response = shortcut + residual return response
class NoisyConvolutional(Initializable, Feedforward, Random): """Convolutional transformation sent through a learned noisy channel. Parameters (same as Convolutional) """ @lazy(allocation=[ 'filter_size', 'num_filters', 'num_channels', 'noise_batch_size' ]) def __init__(self, filter_size, num_filters, num_channels, noise_batch_size, image_size=(None, None), step=(1, 1), border_mode='valid', tied_biases=True, prior_mean=0, prior_noise_level=0, **kwargs): self.convolution = Convolutional() self.mask = Convolutional(name='mask') children = [self.convolution, self.mask] kwargs.setdefault('children', []).extend(children) super(NoisyConvolutional, self).__init__(**kwargs) self.filter_size = filter_size self.num_filters = num_filters self.num_channels = num_channels self.noise_batch_size = noise_batch_size self.image_size = image_size self.step = step self.border_mode = border_mode self.tied_biases = tied_biases self.prior_mean = prior_mean self.prior_noise_level = prior_noise_level def _push_allocation_config(self): self.convolution.filter_size = self.filter_size self.convolution.num_filters = self.num_filters self.convolution.num_channels = self.num_channels # self.convolution.batch_size = self.batch_size self.convolution.image_size = self.image_size self.convolution.step = self.step self.convolution.border_mode = self.border_mode self.convolution.tied_biases = self.tied_biases self.mask.filter_size = (1, 1) self.mask.num_filters = self.num_filters self.mask.num_channels = self.num_filters # self.mask.batch_size = self.batch_size self.mask.image_size = self.convolution.get_dim('output')[1:] # self.mask.step = self.step # self.mask.border_mode = self.border_mode self.mask.tied_biases = self.tied_biases def _allocate(self): out_shape = self.convolution.get_dim('output') N = shared_floatx_zeros((self.noise_batch_size, ) + out_shape, name='N') add_role(N, NOISE) self.parameters.append(N) @application(inputs=['input_'], outputs=['output']) def apply(self, input_, application_call): """Apply the linear transformation followed by masking with noise. Parameters ---------- input_ : :class:`~tensor.TensorVariable` The input on which to apply the transformations Returns ------- output : :class:`~tensor.TensorVariable` The transformed input """ from theano.printing import Print pre_noise = self.convolution.apply(input_) # noise_level = self.mask.apply(input_) noise_level = (self.prior_noise_level - tensor.clip(self.mask.apply(pre_noise), -16, 16)) noise_level = copy_and_tag_noise(noise_level, self, LOG_SIGMA, 'log_sigma') # Allow incomplete batches by just taking the noise that is needed noise = self.parameters[0][:noise_level.shape[0], :, :, :] # noise = self.theano_rng.normal(noise_level.shape) kl = (self.prior_noise_level - noise_level + 0.5 * (tensor.exp(2 * noise_level) + (pre_noise - self.prior_mean)**2) / tensor.exp(2 * self.prior_noise_level) - 0.5) application_call.add_auxiliary_variable(kl, roles=[NITS], name='nits') return pre_noise + tensor.exp(noise_level) * noise def get_dim(self, name): if name == 'input_': return self.convolution.get_dim(name) if name == 'output': return self.convolution.get_dim(name) if name == 'nits': return self.convolution.get_dim('output') return super(NoisyConvolutional, self).get_dim(name) @property def num_output_channels(self): return self.num_filters
class ResidualConvolutional(Initializable): @lazy(allocation=['filter_size', 'num_filters', 'num_channels']) def __init__(self, filter_size, num_filters, num_channels, batch_size=None, mid_noise=False, out_noise=False, tied_noise=False, tied_sigma=False, noise_rate=None, noise_batch_size=None, prior_noise_level=None, image_size=(None, None), step=(1, 1), **kwargs): self.filter_size = filter_size self.num_filters = num_filters self.batch_size = batch_size self.num_channels = num_channels self.image_size = image_size self.mid_noise = mid_noise self.noise_batch_size = noise_batch_size self.noise_rate = noise_rate self.step = step self.border_mode = 'half' self.tied_biases = True depth = 2 self.b0 = SpatialBatchNormalization(name='b0') self.r0 = Rectifier(name='r0') self.n0 = (SpatialNoise(name='n0', noise_rate=self.noise_rate, tied_noise=tied_noise, tied_sigma=tied_sigma, prior_noise_level=prior_noise_level) if mid_noise else None) self.c0 = Convolutional(name='c0') self.b1 = SpatialBatchNormalization(name='b1') self.r1 = Rectifier(name='r1') self.n1 = (SpatialNoise(name='n1', noise_rate=self.noise_rate, tied_noise=tied_noise, tied_sigma=tied_sigma, prior_noise_level=prior_noise_level) if out_noise else None) self.c1 = Convolutional(name='c1') kwargs.setdefault('children', []).extend([ c for c in [ self.c0, self.b0, self.r0, self.n0, self.c1, self.b1, self.r1, self.n1 ] if c is not None ]) super(ResidualConvolutional, self).__init__(**kwargs) def get_dim(self, name): if name == 'input_': return ((self.num_channels, ) + self.image_size) if name == 'output': return self.c1.get_dim(name) return super(ResidualConvolutionalUnit, self).get_dim(name) @property def num_output_channels(self): return self.num_filters def _push_allocation_config(self): self.b0.input_dim = self.get_dim('input_') self.b0.push_allocation_config() if self.r0: self.r0.push_allocation_config() if self.n0: self.n0.noise_batch_size = self.noise_batch_size self.n0.num_channels = self.num_channels self.n0.image_size = self.image_size self.c0.filter_size = self.filter_size self.c0.batch_size = self.batch_size self.c0.num_channels = self.num_channels self.c0.num_filters = self.num_filters self.c0.border_mode = self.border_mode self.c0.image_size = self.image_size self.c0.step = self.step self.c0.use_bias = False self.c0.push_allocation_config() c0_shape = self.c0.get_dim('output') self.b1.input_dim = c0_shape self.b1.push_allocation_config() self.r1.push_allocation_config() if self.n1: self.n1.noise_batch_size = self.noise_batch_size self.n1.num_channels = self.num_filters self.n1.image_size = c0_shape[1:] self.c1.filter_size = self.filter_size self.c1.batch_size = self.batch_size self.c1.num_channels = self.num_filters self.c1.num_filters = self.num_filters self.c1.border_mode = self.border_mode self.c1.image_size = c0_shape[1:] self.c1.step = (1, 1) self.c1.use_bias = False self.c1.push_allocation_config() @application(inputs=['input_'], outputs=['output']) def apply(self, input_): shortcut = input_ # Batchnorm, then Relu, then Convolution first_conv = self.b0.apply(input_) first_conv = self.r0.apply(first_conv) if self.n0: first_conv = self.n0.apply(first_conv) first_conv = self.c0.apply(first_conv) # Batchnorm, then Relu, then Convolution (second time) second_conv = self.b1.apply(first_conv) second_conv = self.r1.apply(second_conv) if self.n1: second_conv = self.n1.apply(second_conv) residual = second_conv # Apply stride and zero-padding to match shortcut to output if self.step and self.step != (1, 1): shortcut = shortcut[:, :, ::self.step[0], ::self.step[1]] if self.num_filters > self.num_channels: padshape = (residual.shape[0], self.num_filters - self.num_channels, residual.shape[2], residual.shape[3]) shortcut = tensor.concatenate( [shortcut, tensor.zeros(padshape, dtype=residual.dtype)], axis=1) elif self.num_filters < self.num_channels: shortcut = shortcut[:, :self.num_channels, :, :] response = shortcut + residual return response
o = X.reshape((X.shape[0], 1, 28, 28)) l = Convolutional(filter_size=(5, 5), num_filters=32, num_channels=1, image_size=(28,28), weights_init=IsotropicGaussian(std=0.01), biases_init=IsotropicGaussian(std=0.01, mean=1.0), use_bias=True, border_mode="valid", step=(1,1)) l.initialize() o = l.apply(o) l = BatchNormalizationConv(input_shape=l.get_dim("output"), B_init=IsotropicGaussian(std=0.01), Y_init=IsotropicGaussian(std=0.01)) l.initialize() o = l.apply(o) o = Rectifier().apply(o) l = MaxPooling(pooling_size=(2, 2), step=(2, 2), input_dim=l.get_dim("output")) l.initialize() o = l.apply(o) #ll = Dropout(p_drop=0.5) #ll.initialize()
class NoisyConvolutional(Initializable, Feedforward, Random): """Convolutional transformation sent through a learned noisy channel. Parameters (same as Convolutional) """ @lazy(allocation=[ 'filter_size', 'num_filters', 'num_channels', 'noise_batch_size']) def __init__(self, filter_size, num_filters, num_channels, noise_batch_size, image_size=(None, None), step=(1, 1), border_mode='valid', tied_biases=True, prior_mean=0, prior_noise_level=0, **kwargs): self.convolution = Convolutional() self.mask = Convolutional(name='mask') children = [self.convolution, self.mask] kwargs.setdefault('children', []).extend(children) super(NoisyConvolutional, self).__init__(**kwargs) self.filter_size = filter_size self.num_filters = num_filters self.num_channels = num_channels self.noise_batch_size = noise_batch_size self.image_size = image_size self.step = step self.border_mode = border_mode self.tied_biases = tied_biases self.prior_mean = prior_mean self.prior_noise_level = prior_noise_level def _push_allocation_config(self): self.convolution.filter_size = self.filter_size self.convolution.num_filters = self.num_filters self.convolution.num_channels = self.num_channels # self.convolution.batch_size = self.batch_size self.convolution.image_size = self.image_size self.convolution.step = self.step self.convolution.border_mode = self.border_mode self.convolution.tied_biases = self.tied_biases self.mask.filter_size = (1, 1) self.mask.num_filters = self.num_filters self.mask.num_channels = self.num_filters # self.mask.batch_size = self.batch_size self.mask.image_size = self.convolution.get_dim('output')[1:] # self.mask.step = self.step # self.mask.border_mode = self.border_mode self.mask.tied_biases = self.tied_biases def _allocate(self): out_shape = self.convolution.get_dim('output') N = shared_floatx_zeros((self.noise_batch_size,) + out_shape, name='N') add_role(N, NOISE) self.parameters.append(N) @application(inputs=['input_'], outputs=['output']) def apply(self, input_, application_call): """Apply the linear transformation followed by masking with noise. Parameters ---------- input_ : :class:`~tensor.TensorVariable` The input on which to apply the transformations Returns ------- output : :class:`~tensor.TensorVariable` The transformed input """ from theano.printing import Print pre_noise = self.convolution.apply(input_) # noise_level = self.mask.apply(input_) noise_level = (self.prior_noise_level - tensor.clip(self.mask.apply(pre_noise), -16, 16)) noise_level = copy_and_tag_noise( noise_level, self, LOG_SIGMA, 'log_sigma') # Allow incomplete batches by just taking the noise that is needed noise = self.parameters[0][:noise_level.shape[0], :, :, :] # noise = self.theano_rng.normal(noise_level.shape) kl = ( self.prior_noise_level - noise_level + 0.5 * ( tensor.exp(2 * noise_level) + (pre_noise - self.prior_mean) ** 2 ) / tensor.exp(2 * self.prior_noise_level) - 0.5 ) application_call.add_auxiliary_variable(kl, roles=[NITS], name='nits') return pre_noise + tensor.exp(noise_level) * noise def get_dim(self, name): if name == 'input_': return self.convolution.get_dim(name) if name == 'output': return self.convolution.get_dim(name) if name == 'nits': return self.convolution.get_dim('output') return super(NoisyConvolutional, self).get_dim(name) @property def num_output_channels(self): return self.num_filters