def resnet_v1_slim_fc(inputs, scope): """ slim version of resnet, can be replaced with resnet_v1.resnet_v1_50(inputs, num_classes=None, global_pool=True, output_stride=None, reuse=False, scope=scope) or any of the other resnsets """ blocks = [ resnet_utils.Block('block1', resnet_v1.bottleneck, [(64, 32, 1)] * 2 + [(64, 32, 2)]), resnet_utils.Block('block2', resnet_v1.bottleneck, [(128, 64, 1)] * 3 + [(128, 64, 2)]), resnet_utils.Block('block3', resnet_v1.bottleneck, [(256, 64, 1)] * 3 + [(256, 64, 2)]), resnet_utils.Block('block4', resnet_v1.bottleneck, [(128, 64, 1)] * 1) ] return resnet_v1.resnet_v1( inputs, blocks, # all parameters below can be passed to resnet_v1.resnet_v1_?? num_classes=None, # don't produce final prediction global_pool= True, # produce 1x1 output, equivalent to input of a FC layer output_stride=None, include_root_block=True, reuse=False, # do not re-use network # my understanding # task1 image -> resnet1 -> output # task2 image -> resnet2 -> output # if both resnets are defined under the same scope, # with reuse set to True, then some of the parameters # will be shared between two tasks scope=scope)
def testEndPointsV1(self): """Test the end points of a tiny v1 bottleneck network.""" bottleneck = resnet_v1.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_v1/shortcut', 'tiny/block1/unit_1/bottleneck_v1/conv1', 'tiny/block1/unit_1/bottleneck_v1/conv2', 'tiny/block1/unit_1/bottleneck_v1/conv3', 'tiny/block1/unit_2/bottleneck_v1/conv1', 'tiny/block1/unit_2/bottleneck_v1/conv2', 'tiny/block1/unit_2/bottleneck_v1/conv3', 'tiny/block2/unit_1/bottleneck_v1/shortcut', 'tiny/block2/unit_1/bottleneck_v1/conv1', 'tiny/block2/unit_1/bottleneck_v1/conv2', 'tiny/block2/unit_1/bottleneck_v1/conv3', 'tiny/block2/unit_2/bottleneck_v1/conv1', 'tiny/block2/unit_2/bottleneck_v1/conv2', 'tiny/block2/unit_2/bottleneck_v1/conv3' ] self.assertItemsEqual(expected, end_points)
def _build_tail(self, inputs, is_training=False): if not self._use_tail: return inputs if self._architecture == 'resnet_v1_101': train_batch_norm = (is_training and self._config.get('train_batch_norm')) with self._enter_variable_scope(): weight_decay = (self._config.get('arg_scope', {}).get('weight_decay', 0)) with tf.variable_scope(self._architecture, reuse=True): resnet_arg_scope = resnet_utils.resnet_arg_scope( batch_norm_epsilon=1e-5, batch_norm_scale=True, weight_decay=weight_decay) with slim.arg_scope(resnet_arg_scope): with slim.arg_scope([slim.batch_norm], is_training=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( inputs, blocks)) else: proposal_classifier_features = inputs return proposal_classifier_features
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_v1_block(scope, base_depth, num_units, stride, rate=1): """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. """ minor_depth = int(base_depth) major_depth = int(base_depth * 4) return resnet_utils.Block(scope, bottleneck, [{ 'depth': major_depth, 'depth_bottleneck': minor_depth, 'stride': 1, 'overide_rate': rate }] * (num_units - 1) + [{ 'depth': major_depth, 'depth_bottleneck': minor_depth, 'stride': stride, 'overide_rate': rate }])
def resnet_v1_beta_block(scope, base_depth, num_units, stride, dropout=False, num_drop=4): """Helper function for creating a resnet_v1 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_v1 bottleneck block. """ if dropout == True: return resnet_utils.Block(scope, bottleneck, [{ 'depth': base_depth * 4, 'depth_bottleneck': base_depth, 'stride': 1, 'unit_rate': 1, 'dropout': True }] * (num_drop) + [{ 'depth': base_depth * 4, 'depth_bottleneck': base_depth, 'stride': 1, 'unit_rate': 1 }] * (num_units - 1 - num_drop) + [{ 'depth': base_depth * 4, 'depth_bottleneck': base_depth, 'stride': stride, 'unit_rate': 1 }]) return resnet_utils.Block(scope, bottleneck, [{ 'depth': base_depth * 4, 'depth_bottleneck': base_depth, 'stride': 1, 'unit_rate': 1 }] * (num_units - 1) + [{ 'depth': base_depth * 4, 'depth_bottleneck': base_depth, 'stride': stride, 'unit_rate': 1 }])
def resnet_tiny2(inputs, num_classes=2, scope='resnet_tiny'): # seperate cls and fcn, add stop_gradient after fcn output blocks = [ resnet_utils.Block('block1', resnet_v1.bottleneck, [(64, 32, 1)] + [(64, 32, 2)]), resnet_utils.Block('block2', resnet_v1.bottleneck, [(128, 64, 1)] + [(128, 64, 2)]), resnet_utils.Block('block3', resnet_v1.bottleneck, [(256, 64, 1)] + [(128, 64, 2)]), resnet_utils.Block('block4', resnet_v1.bottleneck, [(128, 64, 1)]) ] net, _ = resnet_v1.resnet_v1( inputs, blocks, # all parameters below can be passed to resnet_v1.resnet_v1_?? num_classes=None, # don't produce final prediction global_pool= False, # produce 1x1 output, equivalent to input of a FC layer output_stride=16, include_root_block=True, reuse=False, # do not re-use network scope=scope) res_out = net # keep this for later CLS usage net = slim.batch_norm(slim.conv2d_transpose(net, 64, 5, 2)) net = slim.batch_norm(slim.conv2d_transpose(net, 32, 5, 2)) net = slim.batch_norm(slim.conv2d_transpose(net, 16, 5, 2)) net = slim.batch_norm(slim.conv2d_transpose(net, 8, 5, 2)) net = slim.conv2d(net, num_classes, 5, 1, activation_fn=None) logits_fcn = tf.identity(net, 'logits_fcn') net = res_out net = tf.stop_gradient(net) # add a few layers to make the image size even smaller net = slim.conv2d(net, 128, 3, 1) net = slim.max_pool2d(net, 2, 2) net = slim.conv2d(net, 128, 3, 1) net = slim.max_pool2d(net, 2, 2) net = tf.reduce_mean(net, [1, 2], keep_dims=True) # add an extra layer net = slim.conv2d(net, 64, [1, 1]) net = slim.conv2d(net, num_classes, [1, 1], activation_fn=None, normalizer_fn=None) logits_cls = tf.identity(net, 'logits_cls') return logits_fcn, logits_cls, 16
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(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.initialize_all_variables()) output, expected = sess.run([output, expected]) self.assertAllClose(output, expected, atol=1e-4, rtol=1e-4)
def resnet_v1_200(inputs, num_classes=None, 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, global_pool, output_stride, include_root_block=True, reuse=reuse, scope=scope)
def resnet_v1_50_beta(inputs, num_classes=None, is_training=None, global_pool=False, output_stride=None, multi_grid=None, reuse=None, scope='resnet_v1_50'): """Resnet v1 50 beta 变体 Args: :param inputs:tensor 尺寸,[batch, height_in, width, channels] :param num_classes: 用于分类任务的预测类别数 :param is_training:是否用BN进行训练 :param global_pool: 如果为真,则在计算logits前执行全局平均池化。真用于图像分类,假用于预测 :param output_stride:如果为None,则输出将在标称网络步长处计算。 如果output_stride不是None,则它指定所请求的输入与输出空间分辨率的比率。 :param multi_grid:在网络中使用不同的atrous卷积率的层次结构 :param reuse:是否应该重用网络及其变量。 重用的话,必须给定重用的'scope' :param scope:可选variable_scope :return:net:4级张量的大小[batch,height_out,width_out,channels_out]。 如果global_pool为False, 则height_out和width_out与相应的height_in和width_in相比减少了output_stride因子, 否则height_out和width_out都等于1。 如果num_classes为None,则net是最后一个ResNet块的输出,可能是在全局平均池之后。 如果num_classes不是None,则net包含pre-softmax激活。 end_points: 从网络组件到相应激活的字典。 :raise ValueError:如果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=6, 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)
def _resnet_small(self, inputs, num_classes=None, 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, global_pool, output_stride, include_root_block, reuse, scope)
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_small(self, inputs, num_classes=None, is_training=True, global_pool=True, output_stride=None, store_non_strided_activations=False, multi_grid=None, reuse=None, scope='resnet_v1_small'): """A shallow and thin ResNet v1 for faster tests.""" if multi_grid is None: multi_grid = [1, 1, 1] else: if len(multi_grid) != 3: raise ValueError('Expect multi_grid to have length 3.') block = resnet_v1_beta.resnet_v1_beta_block blocks = [ block('block1', base_depth=1, num_units=3, stride=2), block('block2', base_depth=2, num_units=3, stride=2), block('block3', base_depth=4, num_units=3, stride=2), resnet_utils.Block('block4', resnet_v1_beta.bottleneck, [{ 'depth': 32, 'depth_bottleneck': 8, 'stride': 1, 'unit_rate': rate } for rate in multi_grid]) ] return resnet_v1_beta.resnet_v1_beta( inputs, blocks, num_classes=num_classes, is_training=is_training, global_pool=global_pool, output_stride=output_stride, root_block_fn=functools.partial( resnet_v1_beta.root_block_fn_for_beta_variant), store_non_strided_activations=store_non_strided_activations, reuse=reuse, scope=scope)
def resnet_v1_beta_block(scope, base_depth, num_units, stride): """辅助函数,用于创建resnet_v1 beta变量的瓶颈块 Args: :param scope:块的范围 :param base_depth:对于每个单元的瓶颈层的深度 :param num_units:块中的单元数量 :param stride:该块的步幅,作为最后一个单元的步幅实现。 所有其他单位的步幅= 1。 :return:一个resnet_v1 瓶颈块 """ 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, 'unit_rate': 1 }])
def resnet_v2_block(scope, base_depth, num_units, stride): """Helper function for creating a resnet_v2 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_v2 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_rcnn(features, num_classes): resnet_arg_scope = resnet_utils.resnet_arg_scope(batch_norm_epsilon=1e-5, batch_norm_scale=True, weight_decay=5e-4) with slim.arg_scope(resnet_arg_scope): with slim.arg_scope([slim.batch_norm], is_training=True): blocks = [ resnet_utils.Block('block4', resnet_v1.bottleneck, [{ 'depth': 2048, 'depth_bottleneck': 512, 'stride': 1 }] * 3) ] net = resnet_utils.stack_blocks_dense(features, blocks) flat = tf.layers.flatten(net) cls_score = tf.layers.dense(flat, units=(num_classes + 1)) reg_score = tf.layers.dense(flat, units=(num_classes * 4)) cls_probs = tf.nn.softmax(cls_score) return cls_score, cls_probs, reg_score
def _build_tail(self, inputs, is_training=False): if not self._use_tail: return inputs if self._architecture == "resnet_v1_101": train_batch_norm = is_training and self._config.get( "train_batch_norm") with self._enter_variable_scope(): weight_decay = self._config.get("arg_scope", {}).get("weight_decay", 0) with tf.variable_scope(self._architecture, reuse=True): resnet_arg_scope = resnet_utils.resnet_arg_scope( batch_norm_epsilon=1e-5, batch_norm_scale=True, weight_decay=weight_decay, ) with slim.arg_scope(resnet_arg_scope): with slim.arg_scope([slim.batch_norm], is_training=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( inputs, blocks)) else: proposal_classifier_features = inputs return proposal_classifier_features
def _resnet_small_lite_bottleneck(self, inputs, num_classes=None, is_training=True, global_pool=True, output_stride=None, multi_grid=None, reuse=None, scope='resnet_v1_small'): """A shallow and thin ResNet v1 with lite_bottleneck.""" if multi_grid is None: multi_grid = [1, 1] else: if len(multi_grid) != 2: raise ValueError('Expect multi_grid to have length 2.') block = resnet_v1_beta.resnet_v1_small_beta_block blocks = [ block('block1', base_depth=1, num_units=1, stride=2), block('block2', base_depth=2, num_units=1, stride=2), block('block3', base_depth=4, num_units=1, stride=2), resnet_utils.Block('block4', resnet_v1_beta.lite_bottleneck, [ {'depth': 8, 'stride': 1, 'unit_rate': rate} for rate in multi_grid])] return resnet_v1_beta.resnet_v1_beta( inputs, blocks, num_classes=num_classes, is_training=is_training, global_pool=global_pool, output_stride=output_stride, root_block_fn=functools.partial( resnet_v1_beta.root_block_fn_for_beta_variant, depth_multiplier=0.25), reuse=reuse, scope=scope)
def resnet_tiny (X, scope=None, reuse=True): blocks = [ resnet_utils.Block('block1', resnet_v1.bottleneck, [(64, 32, 1)] + [(64, 32, 2)]), resnet_utils.Block('block2', resnet_v1.bottleneck, [(128, 64, 1)] + [(128, 64, 2)]), resnet_utils.Block('block3', resnet_v1.bottleneck, [(256, 64, 1)] + [(128, 64, 2)]), resnet_utils.Block('block4', resnet_v1.bottleneck, [(256, 64, 1)] + [(128, 64, 2)]), resnet_utils.Block('block5', resnet_v1.bottleneck, [(256, 64, 1)] + [(128, 64, 2)]), resnet_utils.Block('block6', resnet_v1.bottleneck, [(128, 64, 1)]) ] net,_ = resnet_v1.resnet_v1( X, blocks, # all parameters below can be passed to resnet_v1.resnet_v1_?? num_classes = 2, # don't produce final prediction global_pool = True, # produce 1x1 output, equivalent to input of a FC layer reuse=reuse, # do not re-use network scope=scope) return net
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'): """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. 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)
def resnet_v1_101(inputs, num_classes=None, is_training=None, global_pool=False, output_stride=None, store_non_strided_activations=False, multi_grid=None, use_bounded_activations=False, reuse=None, scope='resnet_v1_101'): """Resnet v1 101. 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. store_non_strided_activations: If True, we compute non-strided (undecimated) activations at the last unit of each block and store them in the `outputs_collections` before subsampling them. This gives us access to higher resolution intermediate activations which are useful in some dense prediction problems but increases 4x the computation and memory cost at the last unit of each block. multi_grid: Employ a hierarchy of different atrous rates within network. use_bounded_activations: Whether or not to use bounded activations. Bounded activations better lend themselves to quantized inference. 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. 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, store_non_strided_activations=store_non_strided_activations, reuse=reuse, scope=scope, use_bounded_activations=use_bounded_activations)
def resnet_v1_slim( inputs, num_classes=None, global_pool=True, output_stride=None, reuse=None, # the above parameters will be directly passed to # resnet.resnet_v1 scope='resnet_v1_slim'): blocks = [ resnet_utils.Block('block1', resnet_v1.bottleneck, [(64, 32, 1)] * 2 + [(64, 32, 2)]), # the last argument of Block is a list of "bottleneck" unit # configurations. Each entry is of the form [depth, in-depth, stride] # Each "bottleneck" unit consists 3 layers: # convolution from depth channels to in-depth channels # convolution from in-depth channels to in-depth channels # convolution from in-depth channels to depth channels # It's called "bottleneck" because the overall input and output # depth (# channels) are the same, while the in-depth in the # middle is smaller. # Because each bottleneck has 3 layers, the above chain has # 3 * (2 + 1) = 9 layers. # By convention alll bottleneck units have stride = 1 except for the last which has # stride of 2. The overall effect is after the whole chain, image size # is reduced by 2. # The original resnet implementation has: # -- very long chains # -- very large depth and in-depth values. # This is necessary for very big datasets like ImageNet, but for # smaller and simpler datasets we should be able to substantially # reduce these, as is what we do in this resnet_slim # resnet_utils.Block('block2', resnet_v1.bottleneck, [(128, 64, 1)] * 4 + [(128, 64, 2)]), # 3 * (4+1) = 15 layers resnet_utils.Block('block3', resnet_v1.bottleneck, [(256, 64, 1)] * 4 + [(256, 64, 2)]), # 3 * (4+1) = 15 layers resnet_utils.Block('block4', resnet_v1.bottleneck, [(256, 64, 1)] * 2) # 3 * 2 = 6 layers # so we have 9 + 15 + 15 + 6 = 45 layers # there are two extra layers added by the system, so # by the reset nomenclature this network can be called a reset_v1_47 # The first 3 Blocks each have stride = 2, and last Block is 1, # so the overall stride of this architecture is 8 # If "output_stride" is smaller than 8, resnet_v1.resnet_v1 # will add extra down-sizing layers to meet the requirement. ] return resnet_v1.resnet_v1(inputs, blocks, num_classes, global_pool, output_stride, include_root_block=True, reuse=reuse, scope=scope)
def resnet_v1_18(inputs, num_classes=None, is_training=None, global_pool=False, output_stride=None, multi_grid=None, reuse=None, scope='resnet_v1_18', sync_batch_norm_method='None'): """Resnet v1 18. 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_RESNET_18 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_v1_small_beta_block('block1', base_depth=64, num_units=2, stride=2), resnet_v1_small_beta_block('block2', base_depth=128, num_units=2, stride=2), resnet_v1_small_beta_block('block3', base_depth=256, num_units=2, stride=2), resnet_utils.Block('block4', lite_bottleneck, block4_args), ] return resnet_v1_beta(inputs, blocks=blocks, num_classes=num_classes, is_training=is_training, global_pool=global_pool, output_stride=output_stride, reuse=reuse, scope=scope, sync_batch_norm_method=sync_batch_norm_method)
def build_network(self, sess, is_training=True): # select initializers if cfg.TRAIN.TRUNCATED: initializer = tf.truncated_normal_initializer(mean=0.0, stddev=0.01) initializer_bbox = tf.truncated_normal_initializer(mean=0.0, stddev=0.001) else: initializer = tf.random_normal_initializer(mean=0.0, stddev=0.01) initializer_bbox = tf.random_normal_initializer(mean=0.0, stddev=0.001) bottleneck = resnet_v1.bottleneck blocks = [ resnet_utils.Block('block1', bottleneck, [(256, 64, 1)] * 2 + [(256, 64, 2)]), resnet_utils.Block('block2', bottleneck, [(512, 128, 1)] * 3 + [(512, 128, 2)]), resnet_utils.Block('block3', bottleneck, [(1024, 256, 1)] * 22 + [(1024, 256, 1)]), resnet_utils.Block('block4', bottleneck, [(2048, 512, 1)] * 3) ] if cfg.RESNET.FIXED_BLOCKS > 0: with slim.arg_scope(resnet_arg_scope(is_training=False)): net, _ = resnet_v1.resnet_v1(self._image, blocks[0:cfg.RESNET.FIXED_BLOCKS], global_pool=False, include_root_block=True, scope='resnet_v1_101') with slim.arg_scope(resnet_arg_scope(is_training=is_training)): net_conv5, _ = resnet_v1.resnet_v1(net, blocks[cfg.RESNET.FIXED_BLOCKS:-1], global_pool=False, include_root_block=False, scope='resnet_v1_101') else: with slim.arg_scope(resnet_arg_scope(is_training=is_training)): net_conv5, _ = resnet_v1.resnet_v1(self._image, blocks[0:-1], global_pool=False, include_root_block=True, scope='resnet_v1_101') self._act_summaries.append(net_conv5) self._layers['conv5_3'] = net_conv5 with tf.variable_scope('resnet_v1_101', 'resnet_v1_101', regularizer=tf.contrib.layers.l2_regularizer(cfg.TRAIN.WEIGHT_DECAY)): # build the anchors for the image self._anchor_component() # rpn rpn = slim.conv2d(net_conv5, 512, [3, 3], trainable=is_training, weights_initializer=initializer, scope="rpn_conv/3x3") self._act_summaries.append(rpn) rpn_cls_score = slim.conv2d(rpn, self._num_scales * 6, [1, 1], trainable=is_training, weights_initializer=initializer, padding='VALID', activation_fn=None, scope='rpn_cls_score') # change it so that the score has 2 as its channel size rpn_cls_score_reshape = self._reshape_layer(rpn_cls_score, 2, 'rpn_cls_score_reshape') rpn_cls_prob_reshape = self._softmax_layer(rpn_cls_score_reshape, "rpn_cls_prob_reshape") rpn_cls_prob = self._reshape_layer(rpn_cls_prob_reshape, self._num_scales * 6, "rpn_cls_prob") rpn_bbox_pred = slim.conv2d(rpn, self._num_scales * 12, [1, 1], trainable=is_training, weights_initializer=initializer, padding='VALID', activation_fn=None, scope='rpn_bbox_pred') if is_training: rois, roi_scores = self._proposal_layer(rpn_cls_prob, rpn_bbox_pred, "rois") rpn_labels = self._anchor_target_layer(rpn_cls_score, "anchor") # Try to have a determinestic order for the computing graph, for reproducibility with tf.control_dependencies([rpn_labels]): rois, _ = self._proposal_target_layer(rois, roi_scores, "rpn_rois") else: if cfg.TEST.MODE == 'nms': rois, _ = self._proposal_layer(rpn_cls_prob, rpn_bbox_pred, "rois") elif cfg.TEST.MODE == 'top': rois, _ = self._proposal_top_layer(rpn_cls_prob, rpn_bbox_pred, "rois") else: raise NotImplementedError # rcnn if cfg.POOLING_MODE == 'crop': pool5 = self._crop_pool_layer(net_conv5, rois, "pool5") else: raise NotImplementedError with slim.arg_scope(resnet_arg_scope(is_training=is_training)): fc7, _ = resnet_v1.resnet_v1(pool5, blocks[-1:], global_pool=False, include_root_block=False, scope='resnet_v1_101') with tf.variable_scope('resnet_v1_101', 'resnet_v1_101', regularizer=tf.contrib.layers.l2_regularizer(cfg.TRAIN.WEIGHT_DECAY)): # Average pooling done by reduce_mean fc7 = tf.reduce_mean(fc7, axis=[1,2]) cls_score = slim.fully_connected(fc7, self._num_classes, weights_initializer=initializer, trainable=is_training, activation_fn=None, scope='cls_score') cls_prob = self._softmax_layer(cls_score, "cls_prob") bbox_pred = slim.fully_connected(fc7, self._num_classes * 4, weights_initializer=initializer_bbox, trainable=is_training, activation_fn=None, scope='bbox_pred') self._predictions["rpn_cls_score"] = rpn_cls_score self._predictions["rpn_cls_score_reshape"] = rpn_cls_score_reshape self._predictions["rpn_cls_prob"] = rpn_cls_prob self._predictions["rpn_bbox_pred"] = rpn_bbox_pred self._predictions["cls_score"] = cls_score self._predictions["cls_prob"] = cls_prob self._predictions["bbox_pred"] = bbox_pred self._predictions["rois"] = rois self._score_summaries.update(self._predictions) return rois, cls_prob, bbox_pred