# ResNet原理及其在TF-Slim中的实现

ResNet的原理

F(X)+X的公式可以通过在前馈网络中做一个“快捷连接”来实现（如图2） ，快捷连接跳过一个或多个层。在我们的用例中，快捷连接简单的执行自身映射，它们的输出被添加到叠加层的输出中。自身快捷连接既不会添加额外的参数也不会增加计算复杂度。整个网络依然可以用SGD+反向传播来做端到端的训练。

```def bottleneck(inputs, depth, depth_bottleneck, stride, rate=1,
outputs_collections=None, scope=None):

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=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')

output = tf.nn.relu(shortcut + residual)    return slim.utils.collect_named_outputs(outputs_collections,
sc.original_name_scope,
output)```

ResNet的结构

```def resnet_v1_50(inputs,
num_classes=None,
is_training=True,
global_pool=True,
output_stride=None,
reuse=None,
scope='resnet_v1_50'):
"""ResNet-50 model of [1]. 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)] * 3 + [(512, 128, 2)]),
resnet_utils.Block(          'block3', bottleneck, [(1024, 256, 1)] * 5 + [(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)```

```class Block(collections.namedtuple('Block', ['scope', 'unit_fn', 'args'])):
"""
A named tuple describing a ResNet block.
Its parts are:
scope: The scope of the `Block`.
unit_fn: The ResNet unit function which takes as input a `Tensor` and
returns another `Tensor` with the output of the ResNet unit.
args: A list of length equal to the number of units in the `Block`. The list
contains one (depth, depth_bottleneck, stride) tuple for each unit in the
block to serve as argument to unit_fn.

"""```

```class Block(collections.namedtuple('Block', ['scope', 'unit_fn', 'args'])):
"""
A named tuple describing a ResNet block.
Its parts are:
scope: The scope of the `Block`.
unit_fn: The ResNet unit function which takes as input a `Tensor` and
returns another `Tensor` with the output of the ResNet unit.
args: A list of length equal to the number of units in the `Block`. The list
contains one (depth, depth_bottleneck, stride) tuple for each unit in the
block to serve as argument to unit_fn.
"""
def resnet_v1(inputs,
blocks,
num_classes=None,
is_training=True,
global_pool=True,
output_stride=None,
include_root_block=True,
reuse=None,
scope=None):    with tf.variable_scope(scope, 'resnet_v1', [inputs], reuse=reuse) as sc:     end_points_collection = sc.name + '_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)
if global_pool:
# Global average pooling.
net = tf.reduce_mean(net, [1, 2], name='pool5', keep_dims=True)
if num_classes is not None:
net = slim.conv2d(net, num_classes, [1, 1], activation_fn=None,                             normalizer_fn=None, scope='logits')
# Convert end_points_collection into a dictionary of end_points.
end_points = slim.utils.convert_collection_to_dict(end_points_collection)
if num_classes is not None:
end_points['predictions'] = slim.softmax(net, scope='predictions')
return net,
end_points```

net = resnet_utils.stack_blocks_dense(net, blocks, output_stride)

```def stack_blocks_dense(net,
blocks,
output_stride=None,
outputs_collections=None):
# The current_stride variable keeps track of the effective stride of the
# activations. This allows us to invoke atrous convolution whenever applying
# the next residual unit would result in the activations having stride larger
# than the target output_stride.   current_stride = 1
# The atrous convolution rate parameter.   rate = 1    for block in blocks:
with variable_scope.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 variable_scope.variable_scope('unit_%d' % (i + 1), values=[net]):
unit_depth, unit_depth_bottleneck, unit_stride = unit          ```
```# 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,
depth=unit_depth,
depth_bottleneck=unit_depth_bottleneck,
stride=1,
rate=rate)
rate *= unit_stride
else:
net = block.unit_fn(
net,
depth=unit_depth,
depth_bottleneck=unit_depth_bottleneck,
stride=unit_stride,
rate=1)
current_stride *= unit_stride
net = 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_stridecannot be reached.')
return net```

### 参考文献

[1]Deep Residual Learning for Image Recognition [2]http://blog.csdn.net/tiandijun/article/details/52526317 [3]http://blog.csdn.net/mao_feng/article/details/52734438 [4]http://blog.csdn.net/helei001/article/details/52692128 [5]http://blog.csdn.net/u012759136/article/details/52434826#t9

424 篇文章81 人订阅

0 条评论

## 相关文章

### How to Use the TimeDistributed Layer for Long Short-Term Memory Networks in Python 译文

How to Use the TimeDistributed Layer for Long Short-Term Memory Networks in Pyth...

51312

20610

3018

### 人群密度估计--Crowd Counting Via Scale-adaptive Convolutional Nerual Network

Crowd Counting Via Scale-adaptive Convolutional Nerual Network https://arxiv....

2305

35011

3064

6468

### Sklearn-train_test_split随机划分训练集和测试集

sklearn.model_selection.train_test_split随机划分训练集和测试集 官网文档： 一般形式： train_test...

3986

4104

3875