def _maybe_apply_1x1(feat): """Apply 1x1 conv to change layer width if necessary.""" if num_channels != target_num_channels: feat = tf.layers.conv2d( feat, filters=target_num_channels, kernel_size=(1, 1), padding='same') if apply_bn: feat = utils.batch_norm_relu( feat, is_training_bn=is_training, relu=False, data_format='channels_last', name='bn') return feat
def class_net(images, level, num_classes, num_anchors, num_filters, is_training, separable_conv=True, repeats=4, survival_prob=None, use_tpu=False): """Class prediction network.""" if separable_conv: conv_op = functools.partial( tf.layers.separable_conv2d, depth_multiplier=1, pointwise_initializer=tf.initializers.variance_scaling(), depthwise_initializer=tf.initializers.variance_scaling()) else: conv_op = functools.partial( tf.layers.conv2d, kernel_initializer=tf.random_normal_initializer(stddev=0.01)) for i in range(repeats): orig_images = images images = conv_op( images, num_filters, kernel_size=3, bias_initializer=tf.zeros_initializer(), activation=None, padding='same', name='class-%d' % i) images = utils.batch_norm_relu( images, is_training, relu=True, init_zero=False, use_tpu=use_tpu, name='class-%d-bn-%d' % (i, level)) if i > 0 and survival_prob: images = utils.drop_connect(images, is_training, survival_prob) images = images + orig_images classes = conv_op( images, num_classes * num_anchors, kernel_size=3, bias_initializer=tf.constant_initializer(-np.log((1 - 0.01) / 0.01)), padding='same', name='class-predict') return classes
def build_bifpn_layer(feats, feat_sizes, fpn_name, fpn_config, is_training, fpn_num_filters, min_level, max_level, separable_conv, apply_bn_for_resampling, conv_after_downsample, use_native_resize_op, conv_bn_relu_pattern, pooling_type, use_tpu=False): """Builds a feature pyramid given previous feature pyramid and config.""" config = fpn_config or get_fpn_config(fpn_name) num_output_connections = [0 for _ in feats] for i, fnode in enumerate(config.nodes): with tf.variable_scope('fnode{}'.format(i)): logging.info('fnode %d : %s', i, fnode) new_node_width = feat_sizes[fnode['width_index']] nodes = [] for idx, input_offset in enumerate(fnode['inputs_offsets']): input_node = feats[input_offset] num_output_connections[input_offset] += 1 input_node = resample_feature_map( input_node, '{}_{}_{}'.format(idx, input_offset, len(feats)), new_node_width, fpn_num_filters, apply_bn_for_resampling, is_training, conv_after_downsample, use_native_resize_op, pooling_type) nodes.append(input_node) # Combine all nodes. dtype = nodes[0].dtype if config.weight_method == 'attn': edge_weights = [ tf.cast(tf.Variable(1.0, name='WSM'), dtype=dtype) for _ in range(len(fnode['inputs_offsets'])) ] normalized_weights = tf.nn.softmax(tf.stack(edge_weights)) nodes = tf.stack(nodes, axis=-1) new_node = tf.reduce_sum( tf.multiply(nodes, normalized_weights), -1) elif config.weight_method == 'fastattn': edge_weights = [ tf.nn.relu( tf.cast(tf.Variable(1.0, name='WSM'), dtype=dtype)) for _ in range(len(fnode['inputs_offsets'])) ] weights_sum = tf.add_n(edge_weights) nodes = [ nodes[i] * edge_weights[i] / (weights_sum + 0.0001) for i in range(len(nodes)) ] new_node = tf.add_n(nodes) elif config.weight_method == 'sum': new_node = tf.add_n(nodes) else: raise ValueError('unknown weight_method {}'.format( config.weight_method)) with tf.variable_scope('op_after_combine{}'.format(len(feats))): if not conv_bn_relu_pattern: new_node = utils.relu_fn(new_node) if separable_conv: conv_op = functools.partial(tf.layers.separable_conv2d, depth_multiplier=1) else: conv_op = tf.layers.conv2d new_node = conv_op( new_node, filters=fpn_num_filters, kernel_size=(3, 3), padding='same', use_bias=True if not conv_bn_relu_pattern else False, name='conv') new_node = utils.batch_norm_relu( new_node, is_training_bn=is_training, relu=False if not conv_bn_relu_pattern else True, data_format='channels_last', use_tpu=use_tpu, name='bn') feats.append(new_node) num_output_connections.append(0) output_feats = {} for l in range(min_level, max_level + 1): for i, fnode in enumerate(reversed(config.nodes)): if fnode['width_index'] == l: output_feats[l] = feats[-1 - i] break return output_feats