diff --git a/tensorlayer/layers.py b/tensorlayer/layers.py index 43640e1e6..bf2717b9d 100644 --- a/tensorlayer/layers.py +++ b/tensorlayer/layers.py @@ -1852,7 +1852,7 @@ class DeformableConv2dLayer(Layer): e.g. if apply a 3*3 kernel, the number of the last dimension should be 18 (2*3*3) channel_multiplier : int, The number of channels to expand to. filter_size : tuple (height, width) for filter size. - strides : tuple (height, width) for strides. + strides : tuple (height, width) for strides. Current implementation fix to (1, 1, 1, 1) act : None or activation function. shape : list of shape shape of the filters, [filter_height, filter_width, in_channels, out_channels]. @@ -1867,35 +1867,49 @@ class DeformableConv2dLayer(Layer): name : a string or None An optional name to attach to this layer. + Examples + -------- + >>> network = tl.layers.InputLayer(x, name='input_layer') + >>> offset_1 = tl.layers.Conv2dLayer(layer=network, act =act, shape=[3, 3, 3, 18], strides=[1, 1, 1, 1],padding='SAME', name='offset_layer1') + >>> network = tl.layers.DeformableConv2dLayer(layer=network, act=act, offset_layer=offset_1, shape=[3, 3, 3, 32], name='deformable_conv_2d_layer1') + >>> offset_2 = tl.layers.Conv2dLayer(layer=network, act = act, shape=[3, 3, 32, 18], strides=[1, 1, 1, 1], padding='SAME', name='offset_layer2') + >>> network = tl.layers.DeformableConv2dLayer(layer=network, act = act, offset_layer=offset_2, shape=[3, 3, 32, 64], name='deformable_conv_2d_layer2') + + References + ----------- + - The deformation operation was adapted from the implementation in ``_ + Notes ----------- - The stride is fixed as (1, 1, 1, 1) - - `The padding is fixed as 'same' + - `The padding is fixed as 'SAME' - The current implementation is memory-inefficient, please use carefully """ + def __init__( self, layer=None, - offset_layer=None, act=tf.identity, - shape=[3, 3, 10, 10], + offset_layer=None, + shape=[3, 3, 1, 100], + name='deformable_conv_2d_layer', W_init=tf.truncated_normal_initializer(stddev=0.02), b_init=tf.constant_initializer(value=0.0), W_init_args={}, - b_init_args={}, - name='deformable_conv_2d_layer', + b_init_args={} ): + if tf.__version__ < "1.4": + raise Exception("Deformable CNN layer requires tensrflow 1.4 or higher version") + Layer.__init__(self, name=name) self.inputs = layer.outputs self.offset_layer = offset_layer - if tf.__version__ < "1.4": - raise Exception("Deformable CNN layer requires tensrflow 1.4 or higher version") - print(" [TL] DeformableConv2dLayer %s: shape:%s, act:%s" % (self.name, str(shape), act.__name__)) with tf.variable_scope(name) as vs: + offset = self.offset_layer.outputs assert offset.get_shape()[-1] == 2 * shape[0] * shape[1] @@ -1912,8 +1926,9 @@ def __init__( initial_offsets = tf.tile(initial_offsets, [input_h, input_w, 1, 1]) # initial_offsets --> (h, w, n, 2) initial_offsets = tf.cast(initial_offsets, 'float32') grid = tf.meshgrid( - tf.range(input_h), tf.range(input_w), indexing='ij' - ) + tf.range(- int((shape[0] - 1)/2.0), int(input_h - int((shape[0] - 1)/2.0)), 1), + tf.range(- int((shape[1] - 1)/2.0), int(input_w - int((shape[1] - 1)/2.0)), 1), indexing='ij') + grid = tf.stack(grid, axis=-1) grid = tf.cast(grid, 'float32') # grid --> (h, w, 2) grid = tf.expand_dims(grid, 2) # grid --> (h, w, 1, 2) @@ -1923,7 +1938,7 @@ def __init__( input_deform = tf_batch_map_offsets(self.inputs, offset, grid_offset) W = tf.get_variable(name='W_conv2d', shape=[1, 1, shape[0] * shape[1], shape[-2], shape[-1]], - initializer=W_init, **W_init_args) + initializer=W_init, **W_init_args) b = tf.get_variable(name='b_conv2d', shape=(shape[-1]), initializer=b_init, **b_init_args) self.outputs = tf.reshape(act( @@ -1936,8 +1951,11 @@ def __init__( self.all_drop = dict(layer.all_drop) ## offset_layer - self.all_layers.extend(offset_layer.all_layers) - self.all_params.extend(offset_layer.all_params) + offset_params = [osparam for osparam in offset_layer.all_params if osparam not in layer.all_params] + offset_layers = [oslayer for oslayer in offset_layer.all_layers if oslayer not in layer.all_layers] + + self.all_params.extend(offset_params) + self.all_layers.extend(offset_layers) self.all_drop.update(offset_layer.all_drop) ## this layer