Ejemplo n.º 1
0
class Vgg16():
    def __init__(self, cfgs, saveDir=None, initmodelfile=None, run='training'):

        self.cfgs = cfgs
        self.saveDir = saveDir
        self.io = IO()
        weights_file = initmodelfile
        self.data_dict = np.load(weights_file, encoding='latin1').item()
        self.io.print_info("Model weights loaded from {}".format(
            self.cfgs['model_weights_path']))

        self.images = tf.placeholder(tf.float32, [
            None, self.cfgs[run]['image_height'],
            self.cfgs[run]['image_width'], self.cfgs[run]['n_channels']
        ],
                                     name="inputlayer")
        self.edgemaps = tf.placeholder(tf.float32, [
            None, self.cfgs[run]['image_height'],
            self.cfgs[run]['image_width'], 1
        ])
        self.define_model()

    def define_model(self):
        """
        Load VGG params from disk without FC layers A
        Add branch layers (with deconv) after each CONV block
        """

        start_time = time.time()

        self.conv1_1 = self.conv_layer_vgg(self.images, "conv1_1")
        self.conv1_2 = self.conv_layer_vgg(self.conv1_1, "conv1_2")
        self.side_1 = self.side_layer(self.conv1_2, "side_1", 1)
        self.pool1 = self.max_pool(self.conv1_2, 'pool1')

        self.io.print_info('Added CONV-BLOCK-1+SIDE-1')

        self.conv2_1 = self.conv_layer_vgg(self.pool1, "conv2_1")
        self.conv2_2 = self.conv_layer_vgg(self.conv2_1, "conv2_2")
        self.side_2 = self.side_layer(self.conv2_2, "side_2", 2)
        self.pool2 = self.max_pool(self.conv2_2, 'pool2')

        self.io.print_info('Added CONV-BLOCK-2+SIDE-2')

        self.conv3_1 = self.conv_layer_vgg(self.pool2, "conv3_1")
        self.conv3_2 = self.conv_layer_vgg(self.conv3_1, "conv3_2")
        self.conv3_3 = self.conv_layer_vgg(self.conv3_2, "conv3_3")
        self.side_3 = self.side_layer(self.conv3_3, "side_3", 4)
        self.pool3 = self.max_pool(self.conv3_3, 'pool3')

        self.io.print_info('Added CONV-BLOCK-3+SIDE-3')

        self.conv4_1 = self.conv_layer_vgg(self.pool3, "conv4_1")
        self.conv4_2 = self.conv_layer_vgg(self.conv4_1, "conv4_2")
        self.conv4_3 = self.conv_layer_vgg(self.conv4_2, "conv4_3")
        self.side_4 = self.side_layer(self.conv4_3, "side_4", 8)
        self.pool4 = self.max_pool(self.conv4_3, 'pool4')

        self.io.print_info('Added CONV-BLOCK-4+SIDE-4')

        self.conv5_1 = self.conv_layer_vgg(self.pool4, "conv5_1")
        self.conv5_2 = self.conv_layer_vgg(self.conv5_1, "conv5_2")
        self.conv5_3 = self.conv_layer_vgg(self.conv5_2, "conv5_3")
        self.side_5 = self.side_layer(self.conv5_3, "side_5", 16)

        self.io.print_info('Added CONV-BLOCK-5+SIDE-5')

        self.side_outputs = [
            self.side_1, self.side_2, self.side_3, self.side_4, self.side_5
        ]

        w_shape = [1, 1, len(self.side_outputs), 1]
        self.fuse = self.conv_layer(tf.concat(self.side_outputs, axis=3),
                                    w_shape,
                                    name='fuse_1',
                                    use_bias=False,
                                    w_init=tf.constant_initializer(0.2))

        self.io.print_info('Added FUSE layer')

        # complete output maps from side layer and fuse layers
        self.outputs = self.side_outputs + [self.fuse]

        self.data_dict = None
        self.io.print_info("Build model finished: {:.4f}s".format(time.time() -
                                                                  start_time))

    def max_pool(self, bottom, name):
        return tf.nn.max_pool(bottom,
                              ksize=[1, 2, 2, 1],
                              strides=[1, 2, 2, 1],
                              padding='SAME',
                              name=name)

    def conv_layer_vgg(self, bottom, name):
        """
            Adding a conv layer + weight parameters from a dict
        """
        with tf.variable_scope(name):
            filt = self.get_conv_filter(name)

            conv = tf.nn.conv2d(bottom, filt, [1, 1, 1, 1], padding='SAME')

            conv_biases = self.get_bias(name)
            bias = tf.nn.bias_add(conv, conv_biases)

            relu = tf.nn.relu(bias)
            return relu

    def conv_layer(self,
                   x,
                   W_shape,
                   b_shape=None,
                   name=None,
                   padding='SAME',
                   use_bias=True,
                   w_init=None,
                   b_init=None):

        W = self.weight_variable(W_shape, w_init)
        tf.summary.histogram('weights_{}'.format(name), W)

        if use_bias:
            b = self.bias_variable([b_shape], b_init)
            tf.summary.histogram('biases_{}'.format(name), b)

        conv = tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding=padding)

        return conv + b if use_bias else conv

    def deconv_layer(self, x, upscale, name, padding='SAME', w_init=None):

        x_shape = tf.shape(x)
        in_shape = x.shape.as_list()

        w_shape = [upscale * 2, upscale * 2, in_shape[-1], 1]
        strides = [1, upscale, upscale, 1]

        W = self.weight_variable(w_shape, w_init)
        tf.summary.histogram('weights_{}'.format(name), W)

        out_shape = tf.stack([x_shape[0], x_shape[1], x_shape[2], w_shape[2]
                              ]) * tf.constant(strides, tf.int32)
        deconv = tf.nn.conv2d_transpose(x,
                                        W,
                                        out_shape,
                                        strides=strides,
                                        padding=padding)

        return deconv

    def side_layer(self, inputs, name, upscale):
        """
            https://github.com/s9xie/hed/blob/9e74dd710773d8d8a469ad905c76f4a7fa08f945/examples/hed/train_val.prototxt#L122
            1x1 conv followed with Deconvoltion layer to upscale the size of input image sans color
        """
        with tf.variable_scope(name):

            in_shape = inputs.shape.as_list()
            w_shape = [1, 1, in_shape[-1], 1]

            classifier = self.conv_layer(inputs,
                                         w_shape,
                                         b_shape=1,
                                         w_init=tf.constant_initializer(),
                                         b_init=tf.constant_initializer(),
                                         name=name + '_reduction')

            classifier = self.deconv_layer(
                classifier,
                upscale=upscale,
                name='{}_deconv_{}'.format(name, upscale),
                w_init=tf.truncated_normal_initializer(stddev=0.1))

            return classifier

    def get_conv_filter(self, name):
        return tf.constant(self.data_dict[name][0], name="filter")

    def get_bias(self, name):
        return tf.constant(self.data_dict[name][1], name="biases")

    def weight_variable(self, shape, initial):

        init = initial(shape)
        return tf.Variable(init)

    def bias_variable(self, shape, initial):

        init = initial(shape)
        return tf.Variable(init)

    def setup_testing(self, session):
        """
            Apply sigmoid non-linearity to side layer ouputs + fuse layer outputs for predictions
        """

        self.predictions = []

        for idx, b in enumerate(self.outputs):
            output = tf.nn.sigmoid(b, name='output_{}'.format(idx))
            self.predictions.append(output)

    def setup_training(self, session):
        """
            Apply sigmoid non-linearity to side layer ouputs + fuse layer outputs
            Compute total loss := side_layer_loss + fuse_layer_loss
            Compute predicted edge maps from fuse layer as pseudo performance metric to track
        """

        self.predictions = []
        self.loss = 0

        self.io.print_warning('Deep supervision application set to {}'.format(
            self.cfgs['deep_supervision']))

        for idx, b in enumerate(self.side_outputs):
            output = tf.nn.sigmoid(b, name='output_{}'.format(idx))
            cost = sigmoid_cross_entropy_balanced(
                b, self.edgemaps, name='cross_entropy{}'.format(idx))

            self.predictions.append(output)
            if self.cfgs['deep_supervision']:
                self.loss += (self.cfgs['loss_weights'] * cost)

        fuse_output = tf.nn.sigmoid(self.fuse, name='fuse')
        tf.summary.image('fuseSigmoid', fuse_output)
        fuse_cost = sigmoid_cross_entropy_balanced(self.fuse,
                                                   self.edgemaps,
                                                   name='cross_entropy_fuse')
        tf.summary.image('cvSourceEdge', self.edgemaps)
        self.predictions.append(fuse_output)
        self.loss += (self.cfgs['loss_weights'] * fuse_cost)

        pred = tf.cast(tf.greater(fuse_output, 0.5),
                       tf.int32,
                       name='predictions')
        error = tf.cast(tf.not_equal(pred, tf.cast(self.edgemaps, tf.int32)),
                        tf.float32)
        self.error = tf.reduce_mean(error, name='pixel_error')
        tf.summary.scalar('loss', self.loss)
        tf.summary.scalar('error', self.error)

        self.merged_summary = tf.summary.merge_all()
        save_dir = self.saveDir
        if not os.path.exists(save_dir):
            os.makedirs(save_dir)
        self.train_writer = tf.summary.FileWriter(self.saveDir + '/train',
                                                  session.graph)
        self.val_writer = tf.summary.FileWriter(self.saveDir + '/val')
Ejemplo n.º 2
0
class Vgg16():
    def __init__(self, cfgs, saveDir=None, initmodelfile=None, run='training'):

        self.cfgs = cfgs
        self.saveDir = saveDir
        self.io = IO()
        weights_file = initmodelfile
        self.data_dict = np.load(weights_file, encoding='latin1').item()
        self.io.print_info("Model weights loaded from {}".format(
            self.cfgs['model_weights_path']))

        self.images = tf.placeholder(tf.float32, [
            None, self.cfgs[run]['image_height'],
            self.cfgs[run]['image_width'], self.cfgs[run]['n_channels']
        ],
                                     name="inputlayer")
        self.edgemaps = tf.placeholder(tf.float32, [
            None, self.cfgs[run]['image_height'],
            self.cfgs[run]['image_width'], 1
        ])

        self.weights_regularizer = None
        self.filter_initializer = tf.contrib.layers.xavier_initializer()

        self.define_model()

    def define_model(self):
        """
        Load VGG params from disk without FC layers A
        Add branch layers (with deconv) after each CONV block
        """

        start_time = time.time()

        self.conv1_1 = self.conv_layer_vgg(self.images, "conv1_1")
        self.conv1_2 = self.conv_layer_vgg(self.conv1_1, "conv1_2")
        with tf.variable_scope('dsn1'):
            #self.side_1 = self.side_layer(self.conv1_2, "side_1", 1)
            self.side_1 = self.dsn_1x1_conv2d(self.conv1_2, 1)

        self.pool1 = self.max_pool(self.conv1_2, 'pool1')
        self.io.print_info('Added CONV-BLOCK-1+SIDE-1')

        self.conv2_1 = self.conv_layer_vgg(self.pool1, "conv2_1")
        self.conv2_2 = self.conv_layer_vgg(self.conv2_1, "conv2_2")
        with tf.variable_scope('dsn2'):
            #self.side_2 = self.side_layer(self.conv2_2, "side_2", 2)
            self.side_2 = self.dsn_1x1_conv2d(self.conv2_2, 1)
            self.side_2 = self.dsn_deconv2d_with_upsample_factor(
                self.side_2, 1, upsample_factor=2)

        self.pool2 = self.max_pool(self.conv2_2, 'pool2')
        self.io.print_info('Added CONV-BLOCK-2+SIDE-2')

        self.conv3_1 = self.conv_layer_vgg(self.pool2, "conv3_1")
        self.conv3_2 = self.conv_layer_vgg(self.conv3_1, "conv3_2")
        self.conv3_3 = self.conv_layer_vgg(self.conv3_2, "conv3_3")
        with tf.variable_scope('dsn3'):
            #self.side_3 = self.side_layer(self.conv3_3, "side_3", 4)
            self.side_3 = self.dsn_1x1_conv2d(self.conv3_3, 1)
            self.side_3 = self.dsn_deconv2d_with_upsample_factor(
                self.side_3, 1, upsample_factor=4)

        self.pool3 = self.max_pool(self.conv3_3, 'pool3')

        self.io.print_info('Added CONV-BLOCK-3+SIDE-3')

        self.conv4_1 = self.conv_layer_vgg(self.pool3, "conv4_1")
        self.conv4_2 = self.conv_layer_vgg(self.conv4_1, "conv4_2")
        self.conv4_3 = self.conv_layer_vgg(self.conv4_2, "conv4_3")
        with tf.variable_scope('dsn4'):
            #self.side_4 = self.side_layer(self.conv4_3, "side_4", 8)
            self.side_4 = self.dsn_1x1_conv2d(self.conv4_3, 1)
            self.side_4 = self.dsn_deconv2d_with_upsample_factor(
                self.side_4, 1, upsample_factor=8)

        self.pool4 = self.max_pool(self.conv4_3, 'pool4')
        self.io.print_info('Added CONV-BLOCK-4+SIDE-4')

        self.conv5_1 = self.conv_layer_vgg(self.pool4, "conv5_1")
        self.conv5_2 = self.conv_layer_vgg(self.conv5_1, "conv5_2")
        self.conv5_3 = self.conv_layer_vgg(self.conv5_2, "conv5_3")
        with tf.variable_scope('dsn5'):
            #self.side_5 = self.side_layer(self.conv5_3, "side_5", 16)
            self.side_5 = self.dsn_1x1_conv2d(self.conv5_3, 1)
            self.side_5 = self.dsn_deconv2d_with_upsample_factor(
                self.side_5, 1, upsample_factor=16)

        self.io.print_info('Added CONV-BLOCK-5+SIDE-5')
        self.side_outputs = [
            self.side_1, self.side_2, self.side_3, self.side_4, self.side_5
        ]

        w_shape = [1, 1, len(self.side_outputs), 1]

        with tf.variable_scope('fuse'):
            #self.fuse = self.conv_layer(tf.concat(self.side_outputs, axis=3),
            #                            w_shape, name='fuse_1', use_bias=False,
            #                            w_init=tf.constant_initializer(0.2))
            self.fuse = tf.concat([
                self.side_1, self.side_2, self.side_3, self.side_4, self.side_5
            ], 3)
            self.fuse = self.output_1x1_conv2d(self.fuse, 1)

        # complete output maps from side layer and fuse layers
        self.outputs = self.side_outputs + [self.fuse]

        self.data_dict = None
        self.io.print_info("Build model finished: {:.4f}s".format(time.time() -
                                                                  start_time))

    def dsn_1x1_conv2d(self, inputs, filters):
        use_bias = True
        #if const.use_batch_norm:
        #    use_bias = False

        kernel_size = [1, 1]
        outputs = tf.layers.conv2d(
            inputs,
            filters,
            kernel_size,
            padding='same',
            activation=None,  ## no activation
            use_bias=use_bias,
            kernel_initializer=self.filter_initializer,
            kernel_regularizer=self.weights_regularizer)

        #if const.use_batch_norm:
        #    outputs = tf.layers.batch_normalization(outputs, training=is_training)
        ## no activation
        return outputs

    def output_1x1_conv2d(self, inputs, filters):
        kernel_size = [1, 1]
        outputs = tf.layers.conv2d(
            inputs,
            filters,
            kernel_size,
            padding='same',
            activation=None,  ## no activation
            use_bias=True,  ## use bias
            kernel_initializer=self.filter_initializer,
            kernel_regularizer=self.weights_regularizer)

        ## no batch normalization
        ## no activation

        return outputs

    def dsn_deconv2d_with_upsample_factor(self, inputs, filters,
                                          upsample_factor):
        ## https://github.com/s9xie/hed/blob/master/examples/hed/train_val.prototxt
        ## 从这个原版代码里看,是这样计算 kernel_size 的
        kernel_size = [2 * upsample_factor, 2 * upsample_factor]
        outputs = tf.layers.conv2d_transpose(
            inputs,
            filters,
            kernel_size,
            strides=(upsample_factor, upsample_factor),
            padding='same',
            activation=None,  ## no activation
            use_bias=True,  ## use bias
            kernel_initializer=self.filter_initializer,
            kernel_regularizer=self.weights_regularizer)

        ## 概念上来说,deconv2d 已经是最后的输出 layer 了,只不过最后还有一步 1x1 的 conv2d 把 5 个 deconv2d 的输出再融合到一起
        ## 所以不需要再使用 batch normalization 了
        return outputs

    def max_pool(self, bottom, name):
        return tf.nn.max_pool(bottom,
                              ksize=[1, 2, 2, 1],
                              strides=[1, 2, 2, 1],
                              padding='SAME',
                              name=name)

    def conv_layer_vgg(self, bottom, name):
        """
            Adding a conv layer + weight parameters from a dict
        """
        with tf.variable_scope(name):
            filt = self.get_conv_filter(name)
            conv = tf.nn.conv2d(bottom, filt, [1, 1, 1, 1], padding='SAME')
            conv_biases = self.get_bias(name)
            bias = tf.nn.bias_add(conv, conv_biases)
            relu = tf.nn.relu(bias)
            return relu

    def conv_layer(self,
                   x,
                   W_shape,
                   b_shape=None,
                   name=None,
                   padding='SAME',
                   use_bias=True,
                   w_init=None,
                   b_init=None):

        W = self.weight_variable(W_shape, w_init)
        tf.summary.histogram('weights_{}'.format(name), W)
        if use_bias:
            b = self.bias_variable([b_shape], b_init)
            tf.summary.histogram('biases_{}'.format(name), b)
        conv = tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding=padding)
        return conv + b if use_bias else conv

    def deconv_layer(self, x, upscale, name, padding='SAME', w_init=None):

        x_shape = tf.shape(x)
        in_shape = x.shape.as_list()
        w_shape = [upscale * 2, upscale * 2, in_shape[-1], 1]
        strides = [1, upscale, upscale, 1]
        W = self.weight_variable(w_shape, w_init)
        tf.summary.histogram('weights_{}'.format(name), W)
        out_shape = tf.stack([x_shape[0], x_shape[1], x_shape[2], w_shape[2]
                              ]) * tf.constant(strides, tf.int32)
        deconv = tf.nn.conv2d_transpose(x,
                                        W,
                                        out_shape,
                                        strides=strides,
                                        padding=padding)
        return deconv

    def side_layer(self, inputs, name, upscale):
        """
            https://github.com/s9xie/hed/blob/9e74dd710773d8d8a469ad905c76f4a7fa08f945/examples/hed/train_val.prototxt#L122
            1x1 conv followed with Deconvoltion layer to upscale the size of input image sans color
        """
        with tf.variable_scope(name):
            in_shape = inputs.shape.as_list()
            w_shape = [1, 1, in_shape[-1], 1]
            classifier = self.conv_layer(inputs,
                                         w_shape,
                                         b_shape=1,
                                         w_init=tf.constant_initializer(),
                                         b_init=tf.constant_initializer(),
                                         name=name + '_reduction')

            classifier = self.deconv_layer(
                classifier,
                upscale=upscale,
                name='{}_deconv_{}'.format(name, upscale),
                w_init=tf.truncated_normal_initializer(stddev=0.1))
            return classifier

    def get_conv_filter(self, name):
        return tf.constant(self.data_dict[name][0], name="filter")

    def get_bias(self, name):
        return tf.constant(self.data_dict[name][1], name="biases")

    def weight_variable(self, shape, initial):
        init = initial(shape)
        return tf.Variable(init)

    def bias_variable(self, shape, initial):
        init = initial(shape)
        return tf.Variable(init)

    def setup_testing(self, session):
        """
            Apply sigmoid non-linearity to side layer ouputs + fuse layer outputs for predictions
        """
        self.predictions = []
        for idx, b in enumerate(self.outputs):
            output = tf.nn.sigmoid(b, name='output_{}'.format(idx))
            self.predictions.append(output)

    def setup_training(self, session):
        """
            Apply sigmoid non-linearity to side layer ouputs + fuse layer outputs
            Compute total loss := side_layer_loss + fuse_layer_loss
            Compute predicted edge maps from fuse layer as pseudo performance metric to track
        """

        self.predictions = []
        self.loss = 0
        self.io.print_warning('Deep supervision application set to {}'.format(
            self.cfgs['deep_supervision']))
        for idx, b in enumerate(self.side_outputs):
            #tf.summary.image('output_{}'.format(idx), b)
            output = tf.nn.sigmoid(b, name='output_{}'.format(idx))
            cost = sigmoid_cross_entropy_balanced(
                b, self.edgemaps, name='cross_entropy{}'.format(idx))

            self.predictions.append(output)
            if self.cfgs['deep_supervision']:
                self.loss += (self.cfgs['loss_weights'] * cost)

        #tf.summary.image('fuse', self.fuse)
        fuse_output = tf.nn.sigmoid(self.fuse, name='fuse')
        tf.summary.image('fuseSigmoid', fuse_output)
        fuse_cost = sigmoid_cross_entropy_balanced(self.fuse,
                                                   self.edgemaps,
                                                   name='cross_entropy_fuse')
        #tf.summary.image('cvSource', self.images)
        tf.summary.image('cvSourceEdge', self.edgemaps)
        self.predictions.append(fuse_output)
        self.loss += (self.cfgs['loss_weights'] * fuse_cost)

        pred = tf.cast(tf.greater(fuse_output, 0.5),
                       tf.int32,
                       name='predictions')
        error = tf.cast(tf.not_equal(pred, tf.cast(self.edgemaps, tf.int32)),
                        tf.float32)
        self.error = tf.reduce_mean(error, name='pixel_error')

        tf.summary.scalar('loss', self.loss)
        tf.summary.scalar('error', self.error)

        self.merged_summary = tf.summary.merge_all()

        save_dir = self.saveDir
        if not os.path.exists(save_dir):
            os.makedirs(save_dir)

        self.train_writer = tf.summary.FileWriter(save_dir + '/train',
                                                  session.graph)
        self.val_writer = tf.summary.FileWriter(save_dir + '/val')

    '''
    for bn test 
    '''

    def build(self, input_image, is_training):
        with tf.name_scope('processing'):
            #bgr cv2
            b, g, r = tf.split(input_image, 3, axis=3)
            image = tf.concat([b * 0.00390625, g * 0.00390625, r * 0.00390625],
                              axis=3)
        # vgg16
        # block 1
        self.conv1_1 = self.conv_bn_f(image,
                                      is_training=is_training,
                                      name='conv1_1')
        self.conv1_2 = self.conv_bn_f(self.conv1_1,
                                      is_training=is_training,
                                      name='conv1_2')
        self.pool1 = self.max_pool(self.conv1_2, name='pool1')
        # block 2
        self.conv2_1 = self.conv_bn_f(self.pool1,
                                      is_training=is_training,
                                      name='conv2_1')
        self.conv2_2 = self.conv_bn_f(self.conv2_1,
                                      is_training=is_training,
                                      name='conv2_2')
        self.pool2 = self.max_pool(self.conv2_2, name='pool2')
        # block 3
        self.conv3_1 = self.conv_bn_f(self.pool2,
                                      is_training=is_training,
                                      name='conv3_1')
        self.conv3_2 = self.conv_bn_f(self.conv3_1,
                                      is_training=is_training,
                                      name='conv3_2')
        self.conv3_3 = self.conv_bn_f(self.conv3_2,
                                      is_training=is_training,
                                      name='conv3_3')
        self.pool3 = self.max_pool(self.conv3_3, name='pool3')
        # block 4
        self.conv4_1 = self.conv_bn_f(self.pool3,
                                      is_training=is_training,
                                      name='conv4_1')
        self.conv4_2 = self.conv_bn_f(self.conv4_1,
                                      is_training=is_training,
                                      name='conv4_2')
        self.conv4_3 = self.conv_bn_f(self.conv4_2,
                                      is_training=is_training,
                                      name='conv4_3')
        self.pool4 = self.max_pool(self.conv4_3, name='pool4')
        # block 5
        self.conv5_1 = self.conv_bn_f(self.pool4,
                                      is_training=is_training,
                                      name='conv5_1')
        self.conv5_2 = self.conv_bn_f(self.conv5_1,
                                      is_training=is_training,
                                      name='conv5_2')
        self.conv5_3 = self.conv_bn_f(self.conv5_2,
                                      is_training=is_training,
                                      name='conv5_3')

        self.upscore_dsn1_1 = self.conv_bn(self.conv1_1,
                                           ksize=[1, 1, 64, 1],
                                           is_training=is_training,
                                           name='upscore_dsn1_1')
        self.upscore_dsn1_2 = self.conv_bn(self.conv1_2,
                                           ksize=[1, 1, 64, 1],
                                           is_training=is_training,
                                           name='upscore_dsn1_2')

        self.score_dsn2_1 = self.conv_bn(self.conv2_1,
                                         ksize=[1, 1, 128, 1],
                                         is_training=is_training,
                                         name='score_dsn2_1')
        self.upscore_dsn2_1 = self.upsampling(self.score_dsn2_1,
                                              tf.shape(image)[1:3])

        self.score_dsn2_2 = self.conv_bn(self.conv2_2,
                                         ksize=[1, 1, 128, 1],
                                         is_training=is_training,
                                         name='score_dsn2_2')
        self.upscore_dsn2_2 = self.upsampling(self.score_dsn2_2,
                                              tf.shape(image)[1:3])

        self.score_dsn3_1 = self.conv_bn(self.conv3_1,
                                         ksize=[1, 1, 256, 1],
                                         is_training=is_training,
                                         name='score_dsn3_1')
        self.upscore_dsn3_1 = self.upsampling(self.score_dsn3_1,
                                              tf.shape(image)[1:3])

        self.score_dsn3_2 = self.conv_bn(self.conv3_2,
                                         ksize=[1, 1, 256, 1],
                                         is_training=is_training,
                                         name='score_dsn3_2')
        self.upscore_dsn3_2 = self.upsampling(self.score_dsn3_2,
                                              tf.shape(image)[1:3])

        self.score_dsn3_3 = self.conv_bn(self.conv3_3,
                                         ksize=[1, 1, 256, 1],
                                         is_training=is_training,
                                         name='score_dsn3_3')
        self.upscore_dsn3_3 = self.upsampling(self.score_dsn3_3,
                                              tf.shape(image)[1:3])

        self.score_dsn4_1 = self.conv_bn(self.conv4_1,
                                         ksize=[1, 1, 512, 1],
                                         is_training=is_training,
                                         name='score_dsn4_1')
        self.upscore_dsn4_1 = self.upsampling(self.score_dsn4_1,
                                              tf.shape(image)[1:3])

        self.score_dsn4_2 = self.conv_bn(self.conv4_2,
                                         ksize=[1, 1, 512, 1],
                                         is_training=is_training,
                                         name='score_dsn4_2')
        self.upscore_dsn4_2 = self.upsampling(self.score_dsn4_2,
                                              tf.shape(image)[1:3])

        self.score_dsn4_3 = self.conv_bn(self.conv4_3,
                                         ksize=[1, 1, 512, 1],
                                         is_training=is_training,
                                         name='score_dsn4_3')
        self.upscore_dsn4_3 = self.upsampling(self.score_dsn4_3,
                                              tf.shape(image)[1:3])

        self.score_dsn5_1 = self.conv_bn(self.conv5_1,
                                         ksize=[1, 1, 512, 1],
                                         is_training=is_training,
                                         name='score_dsn5_1')
        self.upscore_dsn5_1 = self.upsampling(self.score_dsn5_1,
                                              tf.shape(image)[1:3])

        self.score_dsn5_2 = self.conv_bn(self.conv5_2,
                                         ksize=[1, 1, 512, 1],
                                         is_training=is_training,
                                         name='score_dsn5_2')
        self.upscore_dsn5_2 = self.upsampling(self.score_dsn5_2,
                                              tf.shape(image)[1:3])

        self.score_dsn5_3 = self.conv_bn(self.conv5_3,
                                         ksize=[1, 1, 512, 1],
                                         is_training=is_training,
                                         name='score_dsn5_3')
        self.upscore_dsn5_3 = self.upsampling(self.score_dsn5_3,
                                              tf.shape(image)[1:3])

        self.concat = tf.concat([
            self.upscore_dsn1_1, self.upscore_dsn1_2, self.upscore_dsn2_1,
            self.upscore_dsn2_2, self.upscore_dsn3_1, self.upscore_dsn3_2,
            self.upscore_dsn3_3, self.upscore_dsn4_1, self.upscore_dsn4_2,
            self.upscore_dsn4_3, self.upscore_dsn5_1, self.upscore_dsn5_2,
            self.upscore_dsn5_3
        ],
                                axis=3)

        self.score = self.conv_bn(self.concat,
                                  ksize=[1, 1, 13, self.class_number],
                                  is_training=is_training,
                                  name='score')
        self.softmax = tf.nn.softmax(self.score + tf.constant(1e-4))

        self.pred = tf.argmax(self.softmax, axis=-1)

    '''
    tf.contrib.layers.batch_norm(inputs, decay=0.999, center=True, scale=False, epsilon=0.001, activation_fn=None,
    param_initializers=None, param_regularizers=None, updates_collections=tf.GraphKeys.UPDATE_OPS, is_training=True,
    reuse=None, variables_collections=None, outputs_collections=None, trainable=True, batch_weights=None, fused=None,
    data_format=DATA_FORMAT_NHWC, zero_debias_moving_mean=False, scope=None, renorm=False, renorm_clipping=None, renorm_decay=0.99, adjustment=None)

    tf.contrib.layers.batch_norm 参数:
    1 inputs: 输入
    2 decay :衰减系数。合适的衰减系数值接近1.0,特别是含多个9的值:0.999(默认值),0.99,0.9。如果训练集表现很好而验证/测试集表现得不好,选择小的系数(推荐使用0.9)。如果想要提高稳定性,zero_debias_moving_mean设为True
    3 center:如果为True,有beta偏移量;如果为False,无beta偏移量
    4 scale:如果为True,则乘以gamma。如果为False,gamma则不使用。当下一层是线性的时(例如nn.relu),由于缩放可以由下一层完成,所以可以禁用该层。
    5 epsilon:避免被零除
    6 activation_fn:用于激活,默认为线性激活函数
    7 param_initializers : beta, gamma, moving mean and moving variance的优化初始化
    8 param_regularizers : beta and gamma正则化优化
    9 updates_collections :Collections来收集计算的更新操作。updates_ops需要使用train_op来执行。如果为None,则会添加控件依赖项以确保更新已计算到位。
    10 is_training:图层是否处于训练模式。在训练模式下,它将积累转入的统计量moving_mean并 moving_variance使用给定的指数移动平均值 decay。当它不是在训练模式,那么它将使用的数值moving_mean和moving_variance。
    11 scope:可选范围variable_scope
    注意:训练时,需要更新moving_mean和moving_variance。默认情况下,更新操作被放入tf.GraphKeys.UPDATE_OPS,所以需要添加它们作为依赖项train_op。例如:  
    update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)  with tf.control_dependencies(update_ops):    train_op = optimizer.minimize(loss)
    可以将updates_collections = None设置为强制更新,但可能会导致速度损失,尤其是在分布式设置中。
    '''

    def conv_bn_f(self, bottom, is_training, name):
        # finu-tune and batch_norm ; fine-tune not shape,shape had known
        with tf.variable_scope(name):
            weights = self.get_conv_filter_v2(name)
            out = tf.nn.conv2d(bottom,
                               filter=weights,
                               strides=[1, 1, 1, 1],
                               padding='SAME')
            biases = self.get_bias_v2(name)
            out = tf.nn.bias_add(out, biases)
            #bn before relu and train True test False
            out = tf.contrib.layers.batch_norm(
                out, center=True, scale=True,
                is_training=is_training)  # 这里的scale为真需要注意下,神马意思
            out = tf.nn.relu(out)
        return out

    def conv_bn(self, bottom, ksize, is_training, name):
        # initialize and batch_norm ; stride =[1,1,1,1]
        with tf.variable_scope(name):
            weights = tf.get_variable('weights',
                                      ksize,
                                      tf.float32,
                                      initializer=xavier_initializer())
            biases = tf.get_variable('biases', [ksize[-1]],
                                     tf.float32,
                                     initializer=tf.constant_initializer(0.0))
            out = tf.nn.conv2d(bottom,
                               filter=weights,
                               strides=[1, 1, 1, 1],
                               padding='SAME')
            out = tf.nn.bias_add(out, biases)
            #bn
            out = tf.contrib.layers.batch_norm(out,
                                               center=True,
                                               scale=True,
                                               is_training=is_training)
            out = tf.nn.relu(out)
        return out

    def get_conv_filter_v2(self, name):
        init = tf.constant_initializer(self.vgg16_params[name]['weights'])
        shape = self.vgg16_params[name]['weights'].shape
        var = tf.get_variable('weights',
                              shape=shape,
                              dtype=tf.float32,
                              initializer=init)
        return var

    def get_bias_v2(self, name):
        init = tf.constant_initializer(self.vgg16_params[name]['biases'])
        shape = self.vgg16_params[name]['biases'].shape  # tuple
        bias = tf.get_variable('biases',
                               shape=shape,
                               dtype=tf.float32,
                               initializer=init)
        return bias

    def upsampling(self, bottom, feature_map_size):
        # feature_map_size: int [h,w]
        return tf.image.resize_bilinear(bottom, size=feature_map_size)