def gen_fcn(batch_size, img_shape, kernel_size, data_type='float32', threshold=1e-4): ''' generate theano function for doing lecun lcn of a given setting modified from lecun_lcn in pylearn2.datasets.preprocessing currently data_type can only be float32 if not, will report error saying input and kernel should be the same type and kernel type is float32 ''' X = tensor.matrix(dtype=data_type) X = X.reshape((batch_size, img_shape[0], img_shape[1], 1)) filter_shape = (1, 1, kernel_size, kernel_size) filters = sharedX(gaussian_filter(kernel_size).reshape(filter_shape)) input_space = Conv2DSpace(shape=img_shape, num_channels=1) transformer = Conv2D(filters=filters, batch_size=batch_size, input_space=input_space, border_mode='full') convout = transformer.lmul(X) # For each pixel, remove mean of 9x9 neighborhood mid = int(np.floor(kernel_size / 2.)) centered_X = X - convout[:, mid:-mid, mid:-mid, :] # Scale down norm of 9x9 patch if norm is bigger than 1 transformer = Conv2D(filters=filters, batch_size=batch_size, input_space=input_space, border_mode='full') sum_sqr_XX = transformer.lmul(X**2) denom = tensor.sqrt(sum_sqr_XX[:, mid:-mid, mid:-mid, :]) per_img_mean = denom.mean(axis=[1, 2]) divisor = tensor.largest(per_img_mean.dimshuffle(0, 'x', 'x', 1), denom) divisor = tensor.maximum(divisor, threshold) new_X = centered_X / divisor new_X = tensor.flatten(new_X, outdim=3) f = function([X], new_X) return f
def lecun_lcn(input, img_shape, kernel_shape, threshold=1e-4): """ Yann LeCun's local contrast normalization Original code in Theano by: Guillaume Desjardins Parameters ---------- input : WRITEME img_shape : WRITEME kernel_shape : WRITEME threshold : WRITEME """ input = input.reshape((input.shape[0], input.shape[1], input.shape[2], 1)) X = tensor.matrix(dtype=input.dtype) X = X.reshape((len(input), img_shape[0], img_shape[1], 1)) filter_shape = (1, 1, kernel_shape, kernel_shape) filters = sharedX(gaussian_filter(kernel_shape).reshape(filter_shape)) input_space = Conv2DSpace(shape=img_shape, num_channels=1) transformer = Conv2D(filters=filters, batch_size=len(input), input_space=input_space, border_mode='full') convout = transformer.lmul(X) # For each pixel, remove mean of 9x9 neighborhood mid = int(numpy.floor(kernel_shape / 2.)) centered_X = X - convout[:, mid:-mid, mid:-mid, :] # Scale down norm of 9x9 patch if norm is bigger than 1 transformer = Conv2D(filters=filters, batch_size=len(input), input_space=input_space, border_mode='full') sum_sqr_XX = transformer.lmul(X ** 2) denom = tensor.sqrt(sum_sqr_XX[:, mid:-mid, mid:-mid, :]) per_img_mean = denom.mean(axis=[1, 2]) divisor = tensor.largest(per_img_mean.dimshuffle(0, 'x', 'x', 1), denom) divisor = tensor.maximum(divisor, threshold) new_X = centered_X / divisor new_X = tensor.flatten(new_X, outdim=3) f = function([X], new_X) return f(input)
def test_lmul(self): """ Use conv2D to check whether the convolution worked correctly. """ conv2d = Conv2D(self.filters, self.batch_size, self.input_space, output_axes=('b', 'c', 0, 1),) f_co = theano.function([self.image_tensor], conv2d.lmul(self.image_tensor)) f_cu = theano.function([self.image_tensor], self.cudnn2d.lmul(self.image_tensor)) self.assertTrue(np.allclose(f_co(self.image), f_cu(self.image)))
def setUp(self): """ Set up a test image and filter to re-use """ self.image = numpy.random.rand(1, 3, 3, 1).astype(theano.config.floatX) self.image_tensor = tensor.tensor4() self.input_space = Conv2DSpace((3, 3), 1) self.filters_values = numpy.ones( (1, 1, 2, 2), dtype=theano.config.floatX ) self.filters = sharedX(self.filters_values, name='filters') self.conv2d = Conv2D(self.filters, 1, self.input_space)
def test_channels(self): """ Go from 2 to 3 channels and see whether the shape is correct """ input_space = Conv2DSpace((3, 3), num_channels=3) filters_values = numpy.ones( (2, 3, 2, 2), dtype=theano.config.floatX ) filters = sharedX(filters_values) image = numpy.random.rand(1, 3, 3, 3).astype(theano.config.floatX) conv2d = Conv2D(filters, 1, input_space) f = theano.function([self.image_tensor], conv2d.lmul(self.image_tensor)) assert f(image).shape == (1, 2, 2, 2)
def test_lmul_sq_T(self): """ Check whether this function outputs the same values as when taking the square manually """ conv2d_sq = Conv2D(sharedX(numpy.square(self.filters_values)), 1, self.input_space ).lmul(self.image_tensor) conv2d = self.conv2d.lmul(self.image_tensor) f = theano.function([self.image_tensor], self.conv2d.lmul_T(conv2d_sq)) f2 = theano.function([self.image_tensor], self.conv2d.lmul_sq_T(conv2d)) numpy.testing.assert_allclose(f(self.image), f2(self.image))
def test_axes(self): """ Use different output axes and see whether the output is what we expect """ default_axes = ('b', 0, 1, 'c') axes = (0, 'b', 1, 'c') mapping = tuple(axes.index(axis) for axis in default_axes) input_space = Conv2DSpace((3, 3), num_channels=1, axes=axes) conv2d = Conv2D(self.filters, 1, input_space, output_axes=axes) f_axes = theano.function([self.image_tensor], conv2d.lmul(self.image_tensor)) f = theano.function([self.image_tensor], self.conv2d.lmul(self.image_tensor)) output_axes = f_axes(numpy.transpose(self.image, mapping)) output = f(self.image) output_axes = numpy.transpose(output_axes, mapping) numpy.testing.assert_allclose(output, output_axes) assert output.shape == output_axes.shape