初窥Tensorflow Object Detection API 源码之(1.1) Resnet
2018-02-13 14:31
1681 查看
Overview
resnet_v1
resnet_utilsstack_blocks_dense
bottleneck
resnet_utilsBlock
resnet_v1_50
resnet_v1_101
大名鼎鼎的Resnet众所周知,其结构我也不想太多论述,详见论文
Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun
Deep Residual Learning for Image Recognition.
https://arxiv.org/abs/1512.03385
与resnet50的区别在于blocks的配置
resnet_v1
resnet_utilsstack_blocks_dense
bottleneck
resnet_utilsBlock
resnet_v1_50
resnet_v1_101
大名鼎鼎的Resnet众所周知,其结构我也不想太多论述,详见论文
Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun
Deep Residual Learning for Image Recognition.
https://arxiv.org/abs/1512.03385
Overview
models/research/slim/nets/resnet_v1.pyresnet_v1
为resnet50,101,152,200提供总框架,blocks提供了网络结构配置def resnet_v1(inputs, blocks, num_classes=None, is_training=True, global_pool=True, output_stride=None, include_root_block=True, spatial_squeeze=True, reuse=None, scope=None): with tf.variable_scope(scope, 'resnet_v1', [inputs], reuse=reuse) as sc: end_points_collection = sc.original_name_scope + '_end_points' with slim.arg_scope([slim.conv2d, bottleneck, resnet_utils.stack_blocks_dense], outputs_collections=end_points_collection): with slim.arg_scope([slim.batch_norm], is_training=is_training): net = inputs if include_root_block: 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 /= 4 net = resnet_utils.conv2d_same(net, 64, 7, stride=2, scope='conv1') net = slim.max_pool2d(net, [3, 3], stride=2, scope='pool1') net = resnet_utils.stack_blocks_dense(net, blocks, output_stride) # Convert end_points_collection into a dictionary of end_points. end_points = slim.utils.convert_collection_to_dict( end_points_collection) if global_pool: # Global average pooling. net = tf.reduce_mean(net, [1, 2], name='pool5', keep_dims=True) end_points['global_pool'] = net if num_classes: net = slim.conv2d(net, num_classes, [1, 1], activation_fn=None, normalizer_fn=None, scope='logits') end_points[sc.name + '/logits'] = net if spatial_squeeze: net = tf.squeeze(net, [1, 2], name='SpatialSqueeze') end_points[sc.name + '/spatial_squeeze'] = net end_points['predictions'] = slim.softmax(net, scope='predictions') return net, end_points resnet_v1.default_image_size = 224
resnet_utils.stack_blocks_dense
resnet_utils.stack_blocks_dense会解开blocks@slim.add_arg_scope def stack_blocks_dense(net, blocks, output_stride=None, outputs_collections=None): current_stride = 1 # The atrous convolution rate parameter. rate = 1 for block in blocks: with tf.variable_scope(block.scope, 'block', [net]) as sc: for i, unit in enumerate(block.args): if output_stride is not None and current_stride > output_stride: raise ValueError('The target output_stride cannot be reached.') with tf.variable_scope('unit_%d' % (i + 1), values=[net]): # If we have reached the target output_stride, then we need to employ # atrous convolution with stride=1 and multiply the atrous rate by the # current unit's stride for use in subsequent layers. if output_stride is not None and current_stride == output_stride: net = block.unit_fn(net, rate=rate, **dict(unit, stride=1)) rate *= unit.get('stride', 1) else: net = block.unit_fn(net, rate=1, **unit) current_stride *= unit.get('stride', 1) net = slim.utils.collect_named_outputs(outputs_collections, sc.name, net) if output_stride is not None and current_stride != output_stride: raise ValueError('The target output_stride cannot be reached.') return net
bottleneck
Resnet的核心元结构def bottleneck(inputs, depth, depth_bottleneck, stride, rate=1, outputs_collections=None, scope=None, use_bounded_activations=False): with tf.variable_scope(scope, 'bottleneck_v1', [inputs]) as sc: depth_in = slim.utils.last_dimension(inputs.get_shape(), min_rank=4) if depth == depth_in: shortcut = resnet_utils.subsample(inputs, stride, 'shortcut') else: shortcut = slim.conv2d( inputs, depth, [1, 1], stride=stride, activation_fn=tf.nn.relu6 if use_bounded_activations else None, scope='shortcut') residual = slim.conv2d(inputs, depth_bottleneck, [1, 1], stride=1, scope='conv1') residual = resnet_utils.conv2d_same(residual, depth_bottleneck, 3, stride, rate=rate, scope='conv2') residual = slim.conv2d(residual, depth, [1, 1], stride=1, activation_fn=None, scope='conv3') if use_bounded_activations: # Use clip_by_value to simulate bandpass activation. residual = tf.clip_by_value(residual, -6.0, 6.0) output = tf.nn.relu6(shortcut + residual) else: output = tf.nn.relu(shortcut + residual) return slim.utils.collect_named_outputs(outputs_collections, sc.name, output)
resnet_utils.Block
class Block(collections.namedtuple('Block', ['scope', 'unit_fn', 'args'])):
Block继承了collection.namedtuple 如此,可以解开resnet_v1_block: { 'scope':scope, 'unit_fn':bottleneck, 'args':[{ 'depth':base_depth*4, 'depth_bottleneck':base_depth, 'stride':stride }] }
resnet_v1_50
def resnet_v1_50(inputs, num_classes=None, is_training=True, global_pool=True, output_stride=None, spatial_squeeze=True, reuse=None, scope='resnet_v1_50'): blocks = [ resnet_v1_block('block1', base_depth=64, num_units=3, stride=2), resnet_v1_block('block2', base_depth=128, num_units=4, stride=2), resnet_v1_block('block3', base_depth=256, num_units=6, stride=2), resnet_v1_block('block4', base_depth=512, num_units=3, stride=1), ] return resnet_v1(inputs, blocks, num_classes, is_training, global_pool=global_pool, output_stride=output_stride, include_root_block=True, spatial_squeeze=spatial_squeeze, reuse=reuse, scope=scope) resnet_v1_50.default_image_size = resnet_v1.default_image_size
resnet_v1_101
def resnet_v1_101(inputs, num_classes=None, is_training=True, global_pool=True, output_stride=None, spatial_squeeze=True, reuse=None, scope='resnet_v1_101'): """ResNet-101 model of [1]. See resnet_v1() for arg and return description.""" blocks = [ resnet_v1_block('block1', base_depth=64, num_units=3, stride=2), resnet_v1_block('block2', base_depth=128, num_units=4, stride=2), resnet_v1_block('block3', base_depth=256, num_units=23, stride=2), resnet_v1_block('block4', base_depth=512, num_units=3, stride=1), ] return resnet_v1(inputs, blocks, num_classes, is_training, global_pool=global_pool, output_stride=output_stride, include_root_block=True, spatial_squeeze=spatial_squeeze, reuse=reuse, scope=scope) resnet_v1_101.default_image_size = resnet_v1.default_image_size
与resnet50的区别在于blocks的配置
相关文章推荐
- 初窥Tensorflow Object Detection API 源码之(2.1)FasterRCNNMetaArch
- 初窥Tensorflow Object Detection API 源码之(2.4)BoxPredictor
- 初窥Tensorflow Object Detection API 源码之(2.5)target_assigner
- 初窥Tensorflow Object Detection API 源码之(1.2)FeatureExtractor.Config
- 初窥Tensorflow Object Detection API 源码
- 初窥Tensorflow Object Detection API 源码之(2.6)matcher
- 初窥Tensorflow Object Detection API 源码之(2.1.1)FasterRCNNMetaArch.predict
- Tensorflow object detection API 源码阅读笔记:Fast r-cnn
- Tensorflow object detection API 源码阅读笔记:架构
- Tensorflow object detection API 源码阅读笔记:Mask R-CNN
- Tensorflow object detection API 源码阅读笔记:RFCN
- TensorFlow Object Detection API 实践
- tensorflow object detection API 使用记录2
- Tensorflow Object Detection API使用
- TensorFlow Object Detection API教程——制作自己的数据集
- win10下用tensorflow object detection API 验证时报No module named 'object_detection'
- TensorFlow学习——Tensorflow Object Detection API(win10,CPU)
- Think in dataset under evaluation of TensorFlow object detection API
- Tensorflow开源的object detection API中的源码解析(三):faster_rcnn_inception_resnet_v2_feature_extractor.py
- Tensorflow开源的object detection API中的源码阅读(四):inception_resnet_v2.py