def resnet_v1_200(inputs, num_classes=None, is_training=True, global_pool=True, output_stride=None, reuse=None, scope='resnet_v1_200'): """ResNet-200 model of [2]. See resnet_v1() for arg and return description.""" blocks = [ resnet_utils.Block('block1', bottleneck, [(256, 64, 1)] * 2 + [(256, 64, 2)]), resnet_utils.Block('block2', bottleneck, [(512, 128, 1)] * 23 + [(512, 128, 2)]), resnet_utils.Block('block3', bottleneck, [(1024, 256, 1)] * 35 + [(1024, 256, 2)]), resnet_utils.Block('block4', bottleneck, [(2048, 512, 1)] * 3) ] return resnet_v1(inputs, blocks, num_classes, is_training, global_pool=global_pool, output_stride=output_stride, include_root_block=True, reuse=reuse, scope=scope)
def _resnet_small(self, inputs, num_classes=None, is_training=True, global_pool=True, output_stride=None, include_root_block=True, reuse=None, scope='resnet_v1_small'): """A shallow and thin ResNet v1 for faster tests.""" bottleneck = resnet_v1.bottleneck blocks = [ resnet_utils.Block( 'block1', bottleneck, [(4, 1, 1)] * 2 + [(4, 1, 2)]), resnet_utils.Block( 'block2', bottleneck, [(8, 2, 1)] * 2 + [(8, 2, 2)]), resnet_utils.Block( 'block3', bottleneck, [(16, 4, 1)] * 2 + [(16, 4, 2)]), resnet_utils.Block( 'block4', bottleneck, [(32, 8, 1)] * 2)] return resnet_v1.resnet_v1(inputs, blocks, num_classes, is_training=is_training, global_pool=global_pool, output_stride=output_stride, include_root_block=include_root_block, reuse=reuse, scope=scope)
def testEndPointsV2(self): """Test the end points of a tiny v2 bottleneck network.""" bottleneck = resnet_v2.bottleneck blocks = [ resnet_utils.Block('block1', bottleneck, [(4, 1, 1), (4, 1, 2)]), resnet_utils.Block('block2', bottleneck, [(8, 2, 1), (8, 2, 1)]) ] inputs = create_test_input(2, 32, 16, 3) with slim.arg_scope(resnet_utils.resnet_arg_scope()): _, end_points = self._resnet_plain(inputs, blocks, scope='tiny') expected = [ 'tiny/block1/unit_1/bottleneck_v2/shortcut', 'tiny/block1/unit_1/bottleneck_v2/conv1', 'tiny/block1/unit_1/bottleneck_v2/conv2', 'tiny/block1/unit_1/bottleneck_v2/conv3', 'tiny/block1/unit_2/bottleneck_v2/conv1', 'tiny/block1/unit_2/bottleneck_v2/conv2', 'tiny/block1/unit_2/bottleneck_v2/conv3', 'tiny/block2/unit_1/bottleneck_v2/shortcut', 'tiny/block2/unit_1/bottleneck_v2/conv1', 'tiny/block2/unit_1/bottleneck_v2/conv2', 'tiny/block2/unit_1/bottleneck_v2/conv3', 'tiny/block2/unit_2/bottleneck_v2/conv1', 'tiny/block2/unit_2/bottleneck_v2/conv2', 'tiny/block2/unit_2/bottleneck_v2/conv3' ] self.assertItemsEqual(expected, end_points)
def _atrousValues(self, bottleneck): """Verify the values of dense feature extraction by atrous convolution. Make sure that dense feature extraction by stack_blocks_dense() followed by subsampling gives identical results to feature extraction at the nominal network output stride using the simple self._stack_blocks_nondense() above. Args: bottleneck: The bottleneck function. """ blocks = [ resnet_utils.Block('block1', bottleneck, [(4, 1, 1), (4, 1, 2)]), resnet_utils.Block('block2', bottleneck, [(8, 2, 1), (8, 2, 2)]), resnet_utils.Block('block3', bottleneck, [(16, 4, 1), (16, 4, 2)]), resnet_utils.Block('block4', bottleneck, [(32, 8, 1), (32, 8, 1)]) ] nominal_stride = 8 # Test both odd and even input dimensions. height = 30 width = 31 with slim.arg_scope(resnet_utils.resnet_arg_scope()): with slim.arg_scope([slim.batch_norm], is_training=False): for output_stride in [1, 2, 4, 8, None]: with tf.Graph().as_default(): with self.test_session() as sess: tf.set_random_seed(0) inputs = create_test_input(1, height, width, 3) # Dense feature extraction followed by subsampling. output = resnet_utils.stack_blocks_dense( inputs, blocks, output_stride) if output_stride is None: factor = 1 else: factor = nominal_stride // output_stride output = resnet_utils.subsample(output, factor) # Make the two networks use the same weights. tf.get_variable_scope().reuse_variables() # Feature extraction at the nominal network rate. expected = self._stack_blocks_nondense( inputs, blocks) sess.run(tf.global_variables_initializer()) output, expected = sess.run([output, expected]) self.assertAllClose(output, expected, atol=1e-4, rtol=1e-4)
def _extract_box_classifier_features(self, proposal_feature_maps, scope): """Extracts second stage box classifier features. Args: proposal_feature_maps: A 4-D float tensor with shape [batch_size * self.max_num_proposals, crop_height, crop_width, depth] representing the feature map cropped to each proposal. scope: A scope name (unused). Returns: proposal_classifier_features: A 4-D float tensor with shape [batch_size * self.max_num_proposals, height, width, depth] representing box classifier features for each proposal. """ with tf.variable_scope(self._architecture, reuse=self._reuse_weights): with slim.arg_scope( resnet_utils.resnet_arg_scope( batch_norm_epsilon=1e-5, batch_norm_scale=True, weight_decay=self._weight_decay)): with slim.arg_scope([slim.batch_norm], is_training=self._train_batch_norm): blocks = [ resnet_utils.Block('block4', resnet_v1.bottleneck, [{ 'depth': 2048, 'depth_bottleneck': 512, 'stride': 1 }] * 3) ] proposal_classifier_features = resnet_utils.stack_blocks_dense( proposal_feature_maps, blocks) return proposal_classifier_features
def resnet_v2_small_beta_block(scope, base_depth, num_units, stride): """helper for resnet v2""" block_args = [] for _ in range(num_units - 1): block_args.append({'depth': base_depth, 'stride': 1, 'unit_rate': 1}) block_args.append({'depth': base_depth, 'stride': stride, 'unit_rate': 1}) return resnet_utils.Block(scope, lite_bottleneck_v2, block_args)
def resnet_v1_small_beta_block(scope, base_depth, num_units, stride): """Helper function for creating a resnet_18 beta variant bottleneck block. Args: scope: The scope of the block. base_depth: The depth of the bottleneck layer for each unit. num_units: The number of units in the block. stride: The stride of the block, implemented as a stride in the last unit. All other units have stride=1. Returns: A resnet_18 bottleneck block. """ block_args = [] for _ in range(num_units - 1): block_args.append({'depth': base_depth, 'stride': 1, 'unit_rate': 1}) block_args.append({'depth': base_depth, 'stride': stride, 'unit_rate': 1}) return resnet_utils.Block(scope, lite_bottleneck, block_args)
def resnet_v1_block(scope, base_depth, num_units, stride): """Helper function for creating a resnet_v1 bottleneck block. Args: scope: The scope of the block. base_depth: The depth of the bottleneck layer for each unit. num_units: The number of units in the block. stride: The stride of the block, implemented as a stride in the last unit. All other units have stride=1. Returns: A resnet_v1 bottleneck block. """ return resnet_utils.Block(scope, bottleneck, [{ 'depth': base_depth * 4, 'depth_bottleneck': base_depth, 'stride': 1 }] * (num_units - 1) + [{ 'depth': base_depth * 4, 'depth_bottleneck': base_depth, 'stride': stride }])
def resnet_v1_101_beta(inputs, num_classes=None, is_training=None, global_pool=False, output_stride=None, multi_grid=None, reuse=None, scope='resnet_v1_101', sync_batch_norm_method='None'): """Resnet v1 101 beta variant. This variant modifies the first convolution layer of ResNet-v1-101. In particular, it changes the original one 7x7 convolution to three 3x3 convolutions. Args: inputs: A tensor of size [batch, height_in, width_in, channels]. num_classes: Number of predicted classes for classification tasks. If None we return the features before the logit layer. is_training: Enable/disable is_training for batch normalization. global_pool: If True, we perform global average pooling before computing the logits. Set to True for image classification, False for dense prediction. output_stride: If None, then the output will be computed at the nominal network stride. If output_stride is not None, it specifies the requested ratio of input to output spatial resolution. multi_grid: Employ a hierarchy of different atrous rates within network. reuse: whether or not the network and its variables should be reused. To be able to reuse 'scope' must be given. scope: Optional variable_scope. sync_batch_norm_method: String, sync batchnorm method. Returns: net: A rank-4 tensor of size [batch, height_out, width_out, channels_out]. If global_pool is False, then height_out and width_out are reduced by a factor of output_stride compared to the respective height_in and width_in, else both height_out and width_out equal one. If num_classes is None, then net is the output of the last ResNet block, potentially after global average pooling. If num_classes is not None, net contains the pre-softmax activations. end_points: A dictionary from components of the network to the corresponding activation. Raises: ValueError: if multi_grid is not None and does not have length = 3. """ if multi_grid is None: multi_grid = _DEFAULT_MULTI_GRID else: if len(multi_grid) != 3: raise ValueError('Expect multi_grid to have length 3.') blocks = [ resnet_v1_beta_block('block1', base_depth=64, num_units=3, stride=2), resnet_v1_beta_block('block2', base_depth=128, num_units=4, stride=2), resnet_v1_beta_block('block3', base_depth=256, num_units=23, stride=2), resnet_utils.Block('block4', bottleneck, [{ 'depth': 2048, 'depth_bottleneck': 512, 'stride': 1, 'unit_rate': rate } for rate in multi_grid]), ] return resnet_v1_beta( inputs, blocks=blocks, num_classes=num_classes, is_training=is_training, global_pool=global_pool, output_stride=output_stride, root_block_fn=functools.partial(root_block_fn_for_beta_variant), reuse=reuse, scope=scope, sync_batch_norm_method=sync_batch_norm_method)
def resnet_mod(inputs, num_classes=None, is_training=None, global_pool=False, output_stride=None, multi_grid=None, root_depth_multiplier=0.25, reuse=None, scope='resnet_v1_18', sync_batch_norm_method='None'): """ A custom Resnet variant based on v2 preact architecture. """ ## define the multi_grid/atrous blocks if multi_grid is None: multi_grid = [1, 1] else: if len(multi_grid) != 2: raise ValueError('Expect multi_grid to have length 2.') block4_args = [] for rate in multi_grid: block4_args.append({'depth': 512, 'stride': 1, 'unit_rate': rate}) blocks = [ resnet_v2_small_beta_block('block1', base_depth=64, num_units=1, stride=2), resnet_v2_small_beta_block('block2', base_depth=128, num_units=1, stride=2), resnet_v2_small_beta_block('block3', base_depth=256, num_units=1, stride=2), resnet_utils.Block('block4', lite_bottleneck_v2, block4_args), ] # root_block_fn = root_block_fn_for_beta_variant root_block_fn = functools.partial(conv2d_ws.conv2d_same, num_outputs=64, kernel_size=3, stride=2, scope='root_conv1') batch_norm = utils.get_batch_norm_fn(sync_batch_norm_method) with tf.variable_scope(scope, 'resnet_mod', [inputs], reuse=reuse) as sc: end_points_collection = sc.original_name_scope + '_end_points' with slim.arg_scope([ slim.conv2d, conv2d_ws.conv2d, lite_bottleneck_v2, resnet_utils.stack_blocks_dense ], outputs_collections=end_points_collection): if is_training is not None: arg_scope = slim.arg_scope([batch_norm], is_training=is_training) else: arg_scope = slim.arg_scope([]) with arg_scope: net = inputs if output_stride is not None: if output_stride % 4 != 0: raise ValueError( 'The output_stride needs to be a multiple of 4.') output_stride //= 2 net = root_block_fn(net) # net = slim.max_pool2d(net, 3, stride=2, padding='SAME', scope='pool1') net = resnet_utils.stack_blocks_dense(net, blocks, output_stride) ## add a batchnorm and relu layer since the last conv output don't have them in v2 net = slim.batch_norm(net, activation_fn=tf.nn.relu, scope='postnorm') # Convert end_points_collection into a dictionary of end_points. end_points = slim.utils.convert_collection_to_dict( end_points_collection) return net, end_points