从零开始自己搭建复杂网络2(以Tensorflow为例)
从零开始自己搭建复杂网络(以DenseNet为例)
DenseNet 是一种具有密集连接的卷积神经网络。在该网络中,任何两层之间都有直接的连接,也就是说,网络每一层的输入都是前面所有层输出的并集,
而该层所学习的特征图也会被直接传给其后面所有层作为输入。
DenseNet 在 ResNet 基础上,提出了更优秀的 shortcut 方式。Dense Connection 不仅能使得 feature 更加 robust ,还能带来更快的收敛速度。
显存和计算量上稍显不足,需要业界进一步的优化才能广泛应用。

我们使用slim框架来构建网络,进行slim官方的densenet代码的讲解。
"""Contains the definition of the DenseNet architecture. As described in https://arxiv.org/abs/1608.06993. Densely Connected Convolutional Networks
Gao Huang, Zhuang Liu, Kilian Q. Weinberger, Laurens van der Maaten
"""
那么,开始构建整体网络框架吧
densenet的基本网络由以下代码构成
def densenet(inputs,
num_classes=1000,
reduction=None,
growth_rate=None,
num_filters=None,
num_layers=None,
dropout_rate=None,
data_format='NHWC',
is_training=True,
reuse=None,
scope=None):
assert reduction is not None
assert growth_rate is not None
assert num_filters is not None
assert num_layers is not None compression = 1.0 - reduction
num_dense_blocks = len(num_layers) if data_format == 'NCHW':
inputs = tf.transpose(inputs, [0, 3, 1, 2]) with tf.variable_scope(scope, 'densenetxxx', [inputs, num_classes],
reuse=reuse) as sc:
end_points_collection = sc.name + '_end_points'
with slim.arg_scope([slim.batch_norm, slim.dropout],
is_training=is_training), \
slim.arg_scope([slim.conv2d, _conv, _conv_block,
_dense_block, _transition_block],
outputs_collections=end_points_collection), \
slim.arg_scope([_conv], dropout_rate=dropout_rate):
net = inputs # initial convolution
net = slim.conv2d(net, num_filters, 7, stride=2, scope='conv1')
net = slim.batch_norm(net)
net = tf.nn.relu(net)
net = slim.max_pool2d(net, 3, stride=2, padding='SAME') # blocks
for i in range(num_dense_blocks - 1):
# dense blocks
net, num_filters = _dense_block(net, num_layers[i], num_filters,
growth_rate,
scope='dense_block' + str(i+1)) # Add transition_block
net, num_filters = _transition_block(net, num_filters,
compression=compression,
scope='transition_block' + str(i+1)) net, num_filters = _dense_block(
net, num_layers[-1], num_filters,
growth_rate,
scope='dense_block' + str(num_dense_blocks)) # final blocks
with tf.variable_scope('final_block', [inputs]):
net = slim.batch_norm(net)
net = tf.nn.relu(net)
net = _global_avg_pool2d(net, scope='global_avg_pool') net = slim.conv2d(net, num_classes, 1,
biases_initializer=tf.zeros_initializer(),
scope='logits') 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

纵观论文的网络结构,Densenet由4个部分组成:
- initial convolution
- dense blocks
- transition_block
- final blocks
初始卷积层拥有
conv2d
batch_norm
relu
max_pool2d
这四个方法在开始定义了
with slim.arg_scope([slim.batch_norm, slim.dropout],
is_training=is_training), \
slim.arg_scope([slim.conv2d, _conv, _conv_block,
_dense_block, _transition_block],
outputs_collections=end_points_collection), \
slim.arg_scope([_conv], dropout_rate=dropout_rate):
然后我们定义_dense_block
@slim.add_arg_scope
def _dense_block(inputs, num_layers, num_filters, growth_rate,
grow_num_filters=True, scope=None, outputs_collections=None): with tf.variable_scope(scope, 'dense_blockx', [inputs]) as sc:
net = inputs
for i in range(num_layers):
branch = i + 1
net = _conv_block(net, growth_rate, scope='conv_block'+str(branch)) if grow_num_filters:
num_filters += growth_rate net = slim.utils.collect_named_outputs(outputs_collections, sc.name, net) return net, num_filters
_dense_block中由不同个数的_conv_block组成。拿densenet121来说,卷积的个数为[6,12,24,16]。
_conv_block由一个1×1的卷积和3×3的卷积组合而成,之后将两个卷积融合起来。
@slim.add_arg_scope
def _conv_block(inputs, num_filters, data_format='NHWC', scope=None, outputs_collections=None):
with tf.variable_scope(scope, 'conv_blockx', [inputs]) as sc:
net = inputs
net = _conv(net, num_filters*4, 1, scope='x1')
net = _conv(net, num_filters, 3, scope='x2')
if data_format == 'NHWC':
#在某一个shape的第三个维度上连
net = tf.concat([inputs, net], axis=3)
else: # "NCHW"
net = tf.concat([inputs, net], axis=1) net = slim.utils.collect_named_outputs(outputs_collections, sc.name, net) return net
接着,我们构建_transition_block:
@slim.add_arg_scope
def _transition_block(inputs, num_filters, compression=1.0,
scope=None, outputs_collections=None): num_filters = int(num_filters * compression)
with tf.variable_scope(scope, 'transition_blockx', [inputs]) as sc:
net = inputs
net = _conv(net, num_filters, 1, scope='blk') net = slim.avg_pool2d(net, 2) net = slim.utils.collect_named_outputs(outputs_collections, sc.name, net) return net, num_filters
这个模块由一个1×1 的卷积对其维度,然后接平均池化。
最后一层,我们使用1×1的卷积将输出维度与最后的分类数对其。
# final blocks
with tf.variable_scope('final_block', [inputs]):
net = slim.batch_norm(net)
net = tf.nn.relu(net)
net = _global_avg_pool2d(net, scope='global_avg_pool') net = slim.conv2d(net, num_classes, 1,
biases_initializer=tf.zeros_initializer(),
scope='logits')
net = tf.contrib.layers.flatten(net)
Densenet的每个模块就介绍完毕了
下面是全部的代码:
# Copyright 2016 pudae. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Contains the definition of the DenseNet architecture. As described in https://arxiv.org/abs/1608.06993. Densely Connected Convolutional Networks
Gao Huang, Zhuang Liu, Kilian Q. Weinberger, Laurens van der Maaten
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function import tensorflow as tf slim = tf.contrib.slim @slim.add_arg_scope
def _global_avg_pool2d(inputs, data_format='NHWC', scope=None, outputs_collections=None):
with tf.variable_scope(scope, 'xx', [inputs]) as sc:
axis = [1, 2] if data_format == 'NHWC' else [2, 3]
net = tf.reduce_mean(inputs, axis=axis, keepdims=True)
net = slim.utils.collect_named_outputs(outputs_collections, sc.name, net)
return net @slim.add_arg_scope
def _conv(inputs, num_filters, kernel_size, stride=1, dropout_rate=None,
scope=None, outputs_collections=None):
with tf.variable_scope(scope, 'xx', [inputs]) as sc:
net = slim.batch_norm(inputs)
net = tf.nn.relu(net)
net = slim.conv2d(net, num_filters, kernel_size) if dropout_rate:
net = tf.nn.dropout(net) net = slim.utils.collect_named_outputs(outputs_collections, sc.name, net) return net @slim.add_arg_scope
def _conv_block(inputs, num_filters, data_format='NHWC', scope=None, outputs_collections=None):
with tf.variable_scope(scope, 'conv_blockx', [inputs]) as sc:
net = inputs
net = _conv(net, num_filters*4, 1, scope='x1')
net = _conv(net, num_filters, 3, scope='x2')
if data_format == 'NHWC':
net = tf.concat([inputs, net], axis=3)
else: # "NCHW"
net = tf.concat([inputs, net], axis=1) net = slim.utils.collect_named_outputs(outputs_collections, sc.name, net) return net @slim.add_arg_scope
def _dense_block(inputs, num_layers, num_filters, growth_rate,
grow_num_filters=True, scope=None, outputs_collections=None): with tf.variable_scope(scope, 'dense_blockx', [inputs]) as sc:
net = inputs
for i in range(num_layers):
branch = i + 1
net = _conv_block(net, growth_rate, scope='conv_block'+str(branch)) if grow_num_filters:
num_filters += growth_rate net = slim.utils.collect_named_outputs(outputs_collections, sc.name, net) return net, num_filters @slim.add_arg_scope
def _transition_block(inputs, num_filters, compression=1.0,
scope=None, outputs_collections=None): num_filters = int(num_filters * compression)
with tf.variable_scope(scope, 'transition_blockx', [inputs]) as sc:
net = inputs
net = _conv(net, num_filters, 1, scope='blk') net = slim.avg_pool2d(net, 2) net = slim.utils.collect_named_outputs(outputs_collections, sc.name, net) return net, num_filters def densenet(inputs,
num_classes=1000,
reduction=None,
growth_rate=None,
num_filters=None,
num_layers=None,
dropout_rate=None,
data_format='NHWC',
is_training=True,
reuse=None,
scope=None):
assert reduction is not None
assert growth_rate is not None
assert num_filters is not None
assert num_layers is not None compression = 1.0 - reduction
num_dense_blocks = len(num_layers) if data_format == 'NCHW':
inputs = tf.transpose(inputs, [0, 3, 1, 2]) with tf.variable_scope(scope, 'densenetxxx', [inputs, num_classes],
reuse=reuse) as sc:
end_points_collection = sc.name + '_end_points'
with slim.arg_scope([slim.batch_norm, slim.dropout],
is_training=is_training), \
slim.arg_scope([slim.conv2d, _conv, _conv_block,
_dense_block, _transition_block],
outputs_collections=end_points_collection), \
slim.arg_scope([_conv], dropout_rate=dropout_rate):
net = inputs # initial convolution
net = slim.conv2d(net, num_filters, 7, stride=2, scope='conv1')
net = slim.batch_norm(net)
net = tf.nn.relu(net)
net = slim.max_pool2d(net, 3, stride=2, padding='SAME') # blocks
for i in range(num_dense_blocks - 1):
# dense blocks
net, num_filters = _dense_block(net, num_layers[i], num_filters,
growth_rate,
scope='dense_block' + str(i+1)) # Add transition_block
net, num_filters = _transition_block(net, num_filters,
compression=compression,
scope='transition_block' + str(i+1)) net, num_filters = _dense_block(
net, num_layers[-1], num_filters,
growth_rate,
scope='dense_block' + str(num_dense_blocks)) # final blocks
with tf.variable_scope('final_block', [inputs]):
net = slim.batch_norm(net)
net = tf.nn.relu(net)
net = _global_avg_pool2d(net, scope='global_avg_pool') net = slim.conv2d(net, num_classes, 1,
biases_initializer=tf.zeros_initializer(),
scope='logits')
net = tf.contrib.layers.flatten(net)
# print(net)
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 def densenet121(inputs, num_classes=1000, data_format='NHWC', is_training=True, reuse=None):
return densenet(inputs,
num_classes=num_classes,
reduction=0.5,
growth_rate=32,
num_filters=64,
num_layers=[6,12,24,16],
data_format=data_format,
is_training=is_training,
reuse=reuse,
scope='densenet121')
densenet121.default_image_size = 224 def densenet161(inputs, num_classes=1000, data_format='NHWC', is_training=True, reuse=None):
return densenet(inputs,
num_classes=num_classes,
reduction=0.5,
growth_rate=48,
num_filters=96,
num_layers=[6,12,36,24],
data_format=data_format,
is_training=is_training,
reuse=reuse,
scope='densenet161')
densenet161.default_image_size = 224 def densenet169(inputs, num_classes=1000, data_format='NHWC', is_training=True, reuse=None):
return densenet(inputs,
num_classes=num_classes,
reduction=0.5,
growth_rate=32,
num_filters=64,
num_layers=[6,12,32,32],
data_format=data_format,
is_training=is_training,
reuse=reuse,
scope='densenet169')
densenet169.default_image_size = 224 def densenet_arg_scope(weight_decay=1e-4,
batch_norm_decay=0.99,
batch_norm_epsilon=1.1e-5,
data_format='NHWC'):
with slim.arg_scope([slim.conv2d, slim.batch_norm, slim.avg_pool2d, slim.max_pool2d,
_conv_block, _global_avg_pool2d],
data_format=data_format):
with slim.arg_scope([slim.conv2d],
weights_regularizer=slim.l2_regularizer(weight_decay),
activation_fn=None,
biases_initializer=None):
with slim.arg_scope([slim.batch_norm],
scale=True,
decay=batch_norm_decay,
epsilon=batch_norm_epsilon) as scope:
return scope


从零开始自己搭建复杂网络2(以Tensorflow为例)的更多相关文章
- 从零开始自己搭建复杂网络(以Tensorflow为例)
从零开始自己搭建复杂网络(以MobileNetV2为例) tensorflow经过这几年的发展,已经成长为最大的神经网络框架.而mobileNetV2在经过Xception的实践与深度可分离卷积的应用 ...
- Hyperledger Fabric手动生成CA证书搭建Fabric网络
之前介绍了使用官方脚本自动化启动一个Fabric网络,并且所有的证书都是通过官方的命令行工具cryptogen直接生成网络中的所有节点的证书.在开发环境可以这么简单进行,但是生成环境下还是需要我们自定 ...
- CentOS6.8环境下搭建yum网络仓库
CentOS6.8环境下搭建yum网络仓库 本文利用ftp服务,在CentOS6.8系统下搭建一个yum仓库,然后用另一台虚拟机访问该仓库.并安装程序包 安装ftp服务 查询ftp服务是否安装 [ro ...
- 关于路由器漏洞利用,qemu环境搭建,网络配置的总结
FAT 搭建的坑 1 先按照官方步骤进行,完成后进行如下步骤 2 修改 move /firmadyne into /firmware-analysis-toolkit navigate to the ...
- KVM——以桥接的方式搭建虚拟机网络配置
以桥接的方式搭建虚拟机网络,其优势是可以将网络中的虚拟机看作是与主机同等地位的服务器. 在原本的局域网中有两台主机,一台是win7(IP: 192.168.0.236),一台是CentOS7(IP: ...
- 从零开始搭搭建系统3.1——顶级pom制定
从零开始搭搭建系统3.1——顶级pom制定
- 【Hadoop离线基础总结】zookeeper的介绍以及集群环境搭建、网络编程和RPC的简单了解
ZooKeeper的介绍以及集群环境搭建.网络编程和RPC的简单了解 ZooKeeper介绍 概述 ZooKeeper是一个分布式协调服务的开源框架,主要用来解决分布式集群中应用系统的一致性问题.例如 ...
- SpringBoot2.x【一】从零开始环境搭建
SpringBoot2.x[一]从零开始环境搭建 对于之前的Spring框架的使用,各种配置文件XML.properties一旦出错之后错误难寻,这也是为什么SpringBoot被推上主流的原因,Sp ...
- LSTM(长短期记忆网络)及其tensorflow代码应用
本文主要包括: 一.什么是LSTM 二.LSTM的曲线拟合 三.LSTM的分类问题 四.为什么LSTM有助于消除梯度消失 一.什么是LSTM Long Short Term 网络即为LSTM,是一种 ...
随机推荐
- Nginx一台机器上负载均衡多个Tomcat
默认你的机器上安装了Java环境,解压了Tomcat,安装了Nginx.默认这几个tomcat都部署在一台机器上. 对于Tomcat需要改三个地方[你部署的所有tomcat这三个地方都不能一样,如果你 ...
- 搞定 Kubernetes 基于flannel 的集群网络
.Docker网络模式 在讨论Kubernetes网络之前,让我们先来看一下Docker网络.Docker采用插件化的网络模式,默认提供bridge.host.none.overlay.maclan和 ...
- python 正则括号的使用及踩坑
直接先上结论: 若匹配规则里有1个括号------返回的是括号所匹配到的结果, 若匹配规则里有多个括号------返回多个括号分别匹配到的结果, 若匹配规则里没有括号------就返回整条语句所匹配到 ...
- python类变量和实例变量的区别
类变量:是为类服务的,类所有的实例都共享使用,在一个地方被改变,所有调用的地方变量值都改变.定义类时的写法为类名.变量名 实例变量:是在实例中生效的,每个实例变量的值都根据实例本身需求进行修改,不会影 ...
- xgboost应用
在业务中,我们经常需要对数据建模并预测.简单的情况下,我们采用 if else 判断(一棵树)即可.但如果预测结果与众多因素有关,而每一个特征的权重又不尽相同. 所以我们如何把这些特征的权重合理的找出 ...
- mvn依赖冲突
https://www.cnblogs.com/twoheads/p/10082453.html
- .Net进阶系列(15)-异步多线程(线程的特殊处理和深究委托赋值)(被替换)
1. 线程的异常处理 我们经常会遇到一个场景,开启了多个线程,其中一个线程报错,导致整个程序崩溃.这并不是我们想要的,我需要的结果是,其中一个线程报错,默默的记录下,其它线程正常进行,保证程序整体可以 ...
- indexOf与includes的比较
indexOf和includes都代表检测数组或字符串中是否包含某一个元素 其中indexOf返回的是数值类型,而includes返回的是布尔类型 var ary = [,,]; console.lo ...
- 由-webkit-transform-style:preserve-3d;所想
看一个用css3写幻灯片的demo用到了这么几个属性 .demo{ -webkit-transform-style:preserve-3d; -webkit-perspective:800px; -w ...
- 《深入理解java虚拟机》第三章 垃圾收集器与内存分配策略
第三章 垃圾收集器与内存分配策略 3.1 概述 哪些内存需要回收 何时回收 如何回收 程序计数器.虚拟机栈.本地方法栈3个区域随线程而生灭. java堆和方法区的内存需要回收. 3.2 对象已死吗 ...