def test_make_random_conv2D(self): """ Make random filters """ default_axes = ('c', 0, 1, 'b') conv2d = make_random_conv2D(1, 16, default_axes, default_axes, 16, (2, 2)) f = theano.function([self.image_tensor], conv2d.lmul(self.image_tensor)) assert f(self.image).shape == (16, 2, 2, 1) assert conv2d.output_axes == default_axes
def set_input_space(self, space): """ Note: this resets parameters! """ self.input_space = space if not isinstance(self.input_space, Conv2DSpace): raise TypeError( "The input to a convolutional layer should be a Conv2DSpace, " " but layer " + self.layer_name + " got " + str(type(self.input_space)) ) # note: I think the desired space thing is actually redundant, # since LinearTransform will also dimshuffle the axes if needed # It's not hurting anything to have it here but we could reduce # code complexity by removing it self.desired_space = Conv2DSpace(shape=space.shape, channels=space.num_channels, axes=("c", 0, 1, "b")) ch = self.desired_space.num_channels rem = ch % 4 if ch > 3 and rem != 0: self.dummy_channels = 4 - rem else: self.dummy_channels = 0 self.dummy_space = Conv2DSpace( shape=space.shape, channels=space.num_channels + self.dummy_channels, axes=("c", 0, 1, "b") ) rng = self.mlp.rng output_shape = [ self.input_space.shape[0] + 2 * self.pad - self.kernel_shape[0] + 1, self.input_space.shape[1] + 2 * self.pad - self.kernel_shape[1] + 1, ] def handle_kernel_shape(idx): if self.kernel_shape[idx] < 1: raise ValueError( "kernel must have strictly positive size on all axes but has shape: " + str(self.kernel_shape) ) if output_shape[idx] <= 0: if self.fix_kernel_shape: self.kernel_shape[idx] = self.input_space.shape[idx] + 2 * self.pad assert self.kernel_shape[idx] != 0 output_shape[idx] = 1 warnings.warn("Had to change the kernel shape to make network feasible") else: raise ValueError("kernel too big for input (even with zero padding)") map(handle_kernel_shape, [0, 1]) self.detector_space = Conv2DSpace( shape=output_shape, num_channels=self.detector_channels, axes=("c", 0, 1, "b") ) def handle_pool_shape(idx): if self.pool_shape[idx] < 1: raise ValueError("bad pool shape: " + str(self.pool_shape)) if self.pool_shape[idx] > output_shape[idx]: if self.fix_pool_shape: assert output_shape[idx] > 0 self.pool_shape[idx] = output_shape[idx] else: raise ValueError("Pool shape exceeds detector layer shape on axis %d" % idx) map(handle_pool_shape, [0, 1]) assert self.pool_shape[0] == self.pool_shape[1] assert self.pool_stride[0] == self.pool_stride[1] assert all(isinstance(elem, py_integer_types) for elem in self.pool_stride) if self.pool_stride[0] > self.pool_shape[0]: if self.fix_pool_stride: warnings.warn("Fixing the pool stride") ps = self.pool_shape[0] assert isinstance(ps, py_integer_types) self.pool_stride = [ps, ps] else: raise ValueError("Stride too big.") assert all(isinstance(elem, py_integer_types) for elem in self.pool_stride) check_cuda() if self.irange is not None: self.transformer = conv2d_c01b.make_random_conv2D( irange=self.irange, input_axes=self.desired_space.axes, output_axes=self.detector_space.axes, input_channels=self.dummy_space.num_channels, output_channels=self.detector_space.num_channels, kernel_shape=self.kernel_shape, subsample=(1, 1), pad=self.pad, partial_sum=self.partial_sum, rng=rng, ) W, = self.transformer.get_params() W.name = "W" if self.tied_b: self.b = sharedX(np.zeros((self.detector_space.num_channels)) + self.init_bias) else: 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 assert self.detector_space.num_channels >= 16 dummy_detector = sharedX(self.detector_space.get_origin_batch(2)[0:16, :, :, :]) dummy_p = max_pool_c01b( c01b=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[1], dummy_p.shape[2]], num_channels=self.num_channels, axes=("c", 0, 1, "b") ) print "Output space: ", self.output_space.shape
def setup_deconv_detector_layer_c01b(layer, input_space, rng, irange="not specified"): """ layer. This function sets up only the detector layer. Does the following: * raises a RuntimeError if cuda is not available * sets layer.input_space to input_space * sets up addition of dummy channels for compatibility with cuda-convnet: - layer.dummy_channels: # of dummy channels that need to be added (You might want to check this and raise an Exception if it's not 0) - layer.dummy_space: The Conv2DSpace representing the input with dummy channels added * sets layer.detector_space to the space for the detector layer * sets layer.transformer to be a Conv2D instance * sets layer.b to the right value Parameters ---------- layer : object Any python object that allows the modifications described below and has the following attributes: * pad : int describing amount of zero padding to add * kernel_shape : 2-element tuple or list describing spatial shape of kernel * fix_kernel_shape : bool, if true, will shrink the kernel shape to make it feasible, as needed (useful for hyperparameter searchers) * detector_channels : The number of channels in the detector layer * init_bias : numeric constant added to a tensor of zeros to initialize the bias * tied_b : If true, biases are shared across all spatial locations input_space : WRITEME A Conv2DSpace to be used as input to the layer rng : WRITEME A numpy RandomState or equivalent """ if irange != "not specified": raise AssertionError( "There was a bug in setup_detector_layer_c01b." "It uses layer.irange instead of the irange parameter to the " "function. The irange parameter is now disabled by this " "AssertionError, so that this error message can alert you that " "the bug affected your code and explain why the interface is " "changing. The irange parameter to the function and this " "error message may be removed after April 21, 2014." ) # Use "self" to refer to layer from now on, so we can pretend we're # just running in the set_input_space method of the layer self = layer # Make sure cuda is available check_cuda(str(type(self))) # Validate input if not isinstance(input_space, Conv2DSpace): raise TypeError("The input to a convolutional layer should be a " "Conv2DSpace, but layer " + self.layer_name + " got " + str(type(self.input_space))) if not hasattr(self, 'detector_channels'): raise ValueError("layer argument must have a 'detector_channels' " "attribute specifying how many channels to put in " "the convolution kernel stack.") # Store the input space self.input_space = input_space # Make sure number of channels is supported by cuda-convnet # (multiple of 4 or <= 3) # If not supported, pad the input with dummy channels ch = self.detector_channels rem = ch % 4 if ch > 3 and rem != 0: raise NotImplementedError("Need to do dummy channels on the output") # self.dummy_channels = 4 - rem #else: # self.dummy_channels = 0 #self.dummy_space = Conv2DSpace( # shape=input_space.shape, # channels=input_space.num_channels + self.dummy_channels, # axes=('c', 0, 1, 'b') #) if hasattr(self, 'output_stride'): kernel_stride = self.output_stride else: assert False # not sure if I got the name right, remove this assert if I did kernel_stride = [1, 1] #o_sh = int(np.ceil((i_sh + 2. * self.pad - k_sh) / float(k_st))) + 1 #o_sh -1 = np.ceil((i_sh + 2. * self.pad - k_sh) / float(k_st)) #inv_ceil(o_sh -1) = (i_sh + 2. * self.pad - k_sh) / float(k_st) #float(k_st) inv_cel(o_sh -1) = (i_sh + 2 * self.pad -k_sh) # i_sh = k_st inv_ceil(o_sh-1) - 2 * self.pad + k_sh output_shape = \ [k_st * (i_sh - 1) - 2 * self.pad_out + k_sh for i_sh, k_sh, k_st in zip(self.input_space.shape, self.kernel_shape, kernel_stride)] if self.input_space.num_channels < 16: raise ValueError("Cuda-convnet requires the input to lmul_T to have " "at least 16 channels.") self.detector_space = Conv2DSpace(shape=output_shape, num_channels=self.detector_channels, axes=('c', 0, 1, 'b')) if hasattr(self, 'partial_sum'): partial_sum = self.partial_sum else: partial_sum = 1 if hasattr(self, 'sparse_init') and self.sparse_init is not None: self.transformer = \ checked_call(make_sparse_random_conv2D, OrderedDict([('num_nonzero', self.sparse_init), ('input_space', self.detector_space), ('output_space', self.input_space), ('kernel_shape', self.kernel_shape), ('pad', self.pad), ('partial_sum', partial_sum), ('kernel_stride', kernel_stride), ('rng', rng)])) else: self.transformer = make_random_conv2D( irange=self.irange, input_axes=self.detector_space.axes, output_axes=self.input_space.axes, input_channels=self.detector_space.num_channels, output_channels=self.input_space.num_channels, kernel_shape=self.kernel_shape, pad=self.pad_out, partial_sum=partial_sum, kernel_stride=kernel_stride, rng=rng, input_shape=self.detector_space.shape ) W, = self.transformer.get_params() W.name = self.layer_name + '_W' if self.tied_b: self.b = sharedX(np.zeros(self.detector_space.num_channels) + self.init_bias) else: self.b = sharedX(self.detector_space.get_origin() + self.init_bias) self.b.name = self.layer_name + '_b' logger.info('Input shape: {0}'.format(self.input_space.shape)) print layer.layer_name + ' detector space: {0}'.format(self.detector_space.shape)
def setup_deconv_detector_layer_c01b(layer, input_space, rng, irange="not specified"): """ layer. This function sets up only the detector layer. Does the following: * raises a RuntimeError if cuda is not available * sets layer.input_space to input_space * sets up addition of dummy channels for compatibility with cuda-convnet: - layer.dummy_channels: # of dummy channels that need to be added (You might want to check this and raise an Exception if it's not 0) - layer.dummy_space: The Conv2DSpace representing the input with dummy channels added * sets layer.detector_space to the space for the detector layer * sets layer.transformer to be a Conv2D instance * sets layer.b to the right value Parameters ---------- layer : object Any python object that allows the modifications described below and has the following attributes: * pad : int describing amount of zero padding to add * kernel_shape : 2-element tuple or list describing spatial shape of kernel * fix_kernel_shape : bool, if true, will shrink the kernel shape to make it feasible, as needed (useful for hyperparameter searchers) * detector_channels : The number of channels in the detector layer * init_bias : numeric constant added to a tensor of zeros to initialize the bias * tied_b : If true, biases are shared across all spatial locations input_space : WRITEME A Conv2DSpace to be used as input to the layer rng : WRITEME A numpy RandomState or equivalent """ if irange != "not specified": raise AssertionError( "There was a bug in setup_detector_layer_c01b." "It uses layer.irange instead of the irange parameter to the " "function. The irange parameter is now disabled by this " "AssertionError, so that this error message can alert you that " "the bug affected your code and explain why the interface is " "changing. The irange parameter to the function and this " "error message may be removed after April 21, 2014.") # Use "self" to refer to layer from now on, so we can pretend we're # just running in the set_input_space method of the layer self = layer # Make sure cuda is available check_cuda(str(type(self))) # Validate input if not isinstance(input_space, Conv2DSpace): raise TypeError("The input to a convolutional layer should be a " "Conv2DSpace, but layer " + self.layer_name + " got " + str(type(self.input_space))) if not hasattr(self, 'detector_channels'): raise ValueError("layer argument must have a 'detector_channels' " "attribute specifying how many channels to put in " "the convolution kernel stack.") # Store the input space self.input_space = input_space # Make sure number of channels is supported by cuda-convnet # (multiple of 4 or <= 3) # If not supported, pad the input with dummy channels ch = self.detector_channels rem = ch % 4 if ch > 3 and rem != 0: raise NotImplementedError("Need to do dummy channels on the output") # self.dummy_channels = 4 - rem #else: # self.dummy_channels = 0 #self.dummy_space = Conv2DSpace( # shape=input_space.shape, # channels=input_space.num_channels + self.dummy_channels, # axes=('c', 0, 1, 'b') #) if hasattr(self, 'output_stride'): kernel_stride = self.output_stride else: assert False # not sure if I got the name right, remove this assert if I did kernel_stride = [1, 1] #o_sh = int(np.ceil((i_sh + 2. * self.pad - k_sh) / float(k_st))) + 1 #o_sh -1 = np.ceil((i_sh + 2. * self.pad - k_sh) / float(k_st)) #inv_ceil(o_sh -1) = (i_sh + 2. * self.pad - k_sh) / float(k_st) #float(k_st) inv_cel(o_sh -1) = (i_sh + 2 * self.pad -k_sh) # i_sh = k_st inv_ceil(o_sh-1) - 2 * self.pad + k_sh output_shape = \ [k_st * (i_sh - 1) - 2 * self.pad_out + k_sh for i_sh, k_sh, k_st in zip(self.input_space.shape, self.kernel_shape, kernel_stride)] if self.input_space.num_channels < 16: raise ValueError("Cuda-convnet requires the input to lmul_T to have " "at least 16 channels.") self.detector_space = Conv2DSpace(shape=output_shape, num_channels=self.detector_channels, axes=('c', 0, 1, 'b')) if hasattr(self, 'partial_sum'): partial_sum = self.partial_sum else: partial_sum = 1 if hasattr(self, 'sparse_init') and self.sparse_init is not None: self.transformer = \ checked_call(make_sparse_random_conv2D, OrderedDict([('num_nonzero', self.sparse_init), ('input_space', self.detector_space), ('output_space', self.input_space), ('kernel_shape', self.kernel_shape), ('pad', self.pad), ('partial_sum', partial_sum), ('kernel_stride', kernel_stride), ('rng', rng)])) else: self.transformer = make_random_conv2D( irange=self.irange, input_axes=self.detector_space.axes, output_axes=self.input_space.axes, input_channels=self.detector_space.num_channels, output_channels=self.input_space.num_channels, kernel_shape=self.kernel_shape, pad=self.pad_out, partial_sum=partial_sum, kernel_stride=kernel_stride, rng=rng, input_shape=self.detector_space.shape) W, = self.transformer.get_params() W.name = self.layer_name + '_W' if self.tied_b: self.b = sharedX( np.zeros(self.detector_space.num_channels) + self.init_bias) else: self.b = sharedX(self.detector_space.get_origin() + self.init_bias) self.b.name = self.layer_name + '_b' logger.info('Input shape: {0}'.format(self.input_space.shape)) print layer.layer_name + ' detector space: {0}'.format( self.detector_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=('c', 0, 1, 'b')) if self.irange is not None: assert self.sparse_init is None self.transformer = conv2d.make_random_conv2D( irange=self.irange, input_channels=self.input_space.num_channels, input_axes=self.input_space.axes, output_axes=self.detector_space.axes, output_channels=self.detector_space.num_channels, kernel_shape=self.kernel_shape, kernel_stride=self.kernel_stride, 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 '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)) if self.pool_type == 'max': dummy_p = max_pool_c01b(c01b=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=('c', 0, 1, 'b')) 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=('c', 0, 1, 'b')) if self.irange is not None: assert self.sparse_init is None self.transformer = conv2d.make_random_conv2D( irange=self.irange, input_channels=self.input_space.num_channels, input_axes=self.input_space.axes, output_axes=self.detector_space.axes, output_channels=self.detector_space.num_channels, kernel_shape=self.kernel_shape, kernel_stride=self.kernel_stride, 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 '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)) if self.pool_type == 'max': dummy_p = max_pool_c01b(c01b=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=('c', 0, 1, 'b')) print 'Output space: ', self.output_space.shape
def set_input_space(self, space): """ Note: this resets parameters! """ self.input_space = space if not isinstance(self.input_space, Conv2DSpace): raise TypeError("The input to a convolutional layer should be a Conv2DSpace, " " but layer " + self.layer_name + " got "+str(type(self.input_space))) # note: I think the desired space thing is actually redundant, # since LinearTransform will also dimshuffle the axes if needed # It's not hurting anything to have it here but we could reduce # code complexity by removing it self.desired_space = Conv2DSpace(shape=space.shape, channels=space.num_channels, axes=('c', 0, 1, 'b')) ch = self.desired_space.num_channels rem = ch % 4 if ch > 3 and rem != 0: self.dummy_channels = 4 - rem else: self.dummy_channels = 0 self.dummy_space = Conv2DSpace(shape=space.shape, channels=space.num_channels + self.dummy_channels, axes=('c', 0, 1, 'b')) rng = self.mlp.rng output_shape = [self.input_space.shape[0] + 2 * self.pad - self.kernel_shape[0] + 1, self.input_space.shape[1] + 2 * self.pad - self.kernel_shape[1] + 1] def handle_kernel_shape(idx): if self.kernel_shape[idx] < 1: raise ValueError("kernel must have strictly positive size on all axes but has shape: "+str(self.kernel_shape)) if output_shape[idx] <= 0: if self.fix_kernel_shape: self.kernel_shape[idx] = self.input_space.shape[idx] + 2 * self.pad assert self.kernel_shape[idx] != 0 output_shape[idx] = 1 warnings.warn("Had to change the kernel shape to make network feasible") else: raise ValueError("kernel too big for input (even with zero padding)") map(handle_kernel_shape, [0, 1]) self.detector_space = Conv2DSpace(shape=output_shape, num_channels = self.detector_channels, axes = ('c', 0, 1, 'b')) def handle_pool_shape(idx): if self.pool_shape[idx] < 1: raise ValueError("bad pool shape: " + str(self.pool_shape)) if self.pool_shape[idx] > output_shape[idx]: if self.fix_pool_shape: assert output_shape[idx] > 0 self.pool_shape[idx] = output_shape[idx] else: raise ValueError("Pool shape exceeds detector layer shape on axis %d" % idx) map(handle_pool_shape, [0, 1]) assert self.pool_shape[0] == self.pool_shape[1] assert self.pool_stride[0] == self.pool_stride[1] assert all(isinstance(elem, py_integer_types) for elem in self.pool_stride) if self.pool_stride[0] > self.pool_shape[0]: if self.fix_pool_stride: warnings.warn("Fixing the pool stride") ps = self.pool_shape[0] assert isinstance(ps, py_integer_types) self.pool_stride = [ps, ps] else: raise ValueError("Stride too big.") assert all(isinstance(elem, py_integer_types) for elem in self.pool_stride) check_cuda() if self.irange is not None: self.transformer = conv2d_c01b.make_random_conv2D( irange = self.irange, input_axes = self.desired_space.axes, output_axes = self.detector_space.axes, input_channels = self.dummy_space.num_channels, output_channels = self.detector_space.num_channels, kernel_shape = self.kernel_shape, subsample = (1,1), pad = self.pad, partial_sum = self.partial_sum, rng = rng) W, = self.transformer.get_params() W.name = 'W' if self.tied_b: self.b = sharedX(np.zeros((self.detector_space.num_channels)) + self.init_bias) else: 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 assert self.detector_space.num_channels >= 16 dummy_detector = sharedX(self.detector_space.get_origin_batch(2)[0:16,:,:,:]) dummy_p = max_pool_c01b(c01b=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[1], dummy_p.shape[2]], num_channels = self.num_channels, axes = ('c', 0, 1, 'b') ) print 'Output space: ', self.output_space.shape