原文链接: TensorFlow 使用 slim 模块搭建复杂网络

上一篇: scrapy 代理使用

下一篇: TensorFlow infogan 生成 mnist 数据集

参考

https://blog.csdn.net/guvcolie/article/details/77686555

https://www.cnblogs.com/zyly/p/9146787.html

引入模块

import tensorflow.contrib.slim as slim

简化模型搭建

input = ...
with tf.name_scope('conv1_1') as scope:kernel = tf.Variable(tf.truncated_normal([3, 3, 64, 128], dtype=tf.float32,stddev=1e-1), name='weights')conv = tf.nn.conv2d(input, kernel, [1, 1, 1, 1], padding='SAME')biases = tf.Variable(tf.constant(0.0, shape=[128], dtype=tf.float32),trainable=True, name='biases')bias = tf.nn.bias_add(conv, biases)conv1 = tf.nn.relu(bias, name=scope)net = slim.conv2d(input, 128, [3, 3], scope='conv1_1')

TF-Slim提供了标准接口用于组建神经网络,包括:

Layer TF-Slim
BiasAdd slim.bias_add
BatchNorm slim.batch_norm
Conv2d slim.conv2d
Conv2dInPlane slim.conv2d_in_plane
Conv2dTranspose (Deconv) slim.conv2d_transpose
FullyConnected slim.fully_connected
AvgPool2D slim.avg_pool2d
Dropout slim.dropout
Flatten slim.flatten
MaxPool2D slim.max_pool2d
OneHotEncoding slim.one_hot_encoding
SeparableConv2 slim.separable_conv2d
UnitNorm slim.unit_norm

repeat

net = ...
net = slim.conv2d(net, 256, [3, 3], scope='conv3_1')
net = slim.conv2d(net, 256, [3, 3], scope='conv3_2')
net = slim.conv2d(net, 256, [3, 3], scope='conv3_3')
net = slim.max_pool2d(net, [2, 2], scope='pool2')net = slim.repeat(net, 3, slim.conv2d, 256, [3, 3], scope='conv3')
net = slim.max_pool2d(net, [2, 2], scope='pool2')

slim.repeat不但可以在一行中使用相同的参数,而且还能智能地展开scope,即每个后续的slim.conv2d调用所对应的scope都会追加下划线及迭代数字。更具体地讲,上面代码的scope分别为 'conv3/conv3_1', 'conv3/conv3_2' and 'conv3/conv3_3'.

stack

# Verbose way:
x = slim.fully_connected(x, 32, scope='fc/fc_1')
x = slim.fully_connected(x, 64, scope='fc/fc_2')
x = slim.fully_connected(x, 128, scope='fc/fc_3')# Equivalent, TF-Slim way using slim.stack:
slim.stack(x, slim.fully_connected, [32, 64, 128], scope='fc')

TF-Slim的 slim.stack操作符允许调用者用不同的参数重复使用相同的操作符是创建一个stack或网络层塔。slim.stack也会为每个创建的操作符生成一个新的scope。例如,下面是一个简单的方法去创建MLP:

在这个例子中,slim.stack调用 slim.fully_connected 三次,前一个层的输出是下一层的输入。而每个网络层的输出通道数从32变到64,再到128. 同样,我们可以用stack简化一个多卷积层塔:

# Verbose way:
x = slim.conv2d(x, 32, [3, 3], scope='core/core_1')
x = slim.conv2d(x, 32, [1, 1], scope='core/core_2')
x = slim.conv2d(x, 64, [3, 3], scope='core/core_3')
x = slim.conv2d(x, 64, [1, 1], scope='core/core_4')# Using stack:
slim.stack(x, slim.conv2d, [(32, [3, 3]), (32, [1, 1]), (64, [3, 3]), (64, [1, 1])], scope='core')

这种方式可以确保这三个卷积层共享相同的参数值,但是仍然没有减少代码规模。通过使用arg_scope,我们既能确保每层共享参数值,又能精简代码

如例所示,arg_scope使代码更简洁且易于维护。注意,在arg_scope中被指定的参数值,也可以在局部位置进行覆盖。比如,padding参数设置为'SAME', 而第二个卷积层仍然可以通过把它设为'VALID'而覆盖掉arg_scope中的默认设置。

with slim.arg_scope([slim.conv2d], padding='SAME',weights_initializer=tf.truncated_normal_initializer(stddev=0.01)weights_regularizer=slim.l2_regularizer(0.0005)):net = slim.conv2d(inputs, 64, [11, 11], scope='conv1')net = slim.conv2d(net, 128, [11, 11], padding='VALID', scope='conv2')net = slim.conv2d(net, 256, [11, 11], scope='conv3')

vgg16 模型搭建以及各层shape

import tensorflow as tf
import tensorflow.contrib.slim as slim
def vgg_16(inputs,num_classes=1000,is_training=True,dropout_keep_prob=0.5,):# Collect outputs for conv2d, fully_connected and max_pool2d.with slim.arg_scope([slim.conv2d, slim.fully_connected, slim.max_pool2d]):print(inputs.shape)  # (16, 224, 224, 3)net = slim.repeat(inputs, 2, slim.conv2d, 64, [3, 3], scope='conv1')print(net.shape)  # (16, 224, 224, 64)net = slim.max_pool2d(net, [2, 2], scope='pool1')print(net.shape)  # (16, 112, 112, 64)net = slim.repeat(net, 2, slim.conv2d, 128, [3, 3], scope='conv2')print(net.shape)  # (16, 112, 112, 128)net = slim.max_pool2d(net, [2, 2], scope='pool2')print(net.shape)  # (16, 56, 56, 128)net = slim.repeat(net, 3, slim.conv2d, 256, [3, 3], scope='conv3')print(net.shape)  # (16, 56, 56, 256)net = slim.max_pool2d(net, [2, 2], scope='pool3')print(net.shape)  # (16, 28, 28, 256)net = slim.repeat(net, 3, slim.conv2d, 512, [3, 3], scope='conv4')print(net.shape)  # (16, 28, 28, 512)net = slim.max_pool2d(net, [2, 2], scope='pool4')print(net.shape)  # (16, 14, 14, 512)net = slim.repeat(net, 3, slim.conv2d, 512, [3, 3], scope='conv5')print(net.shape)  # (16, 14, 14, 512)net = slim.max_pool2d(net, [2, 2], scope='pool5')print(net.shape)  # (16, 7, 7, 512)# Use conv2d instead of fully_connected layers.net = slim.conv2d(net, 4096, [7, 7], padding="VALID", scope='fc6')print(net.shape)  # (16, 1, 1, 4096)net = slim.dropout(net, dropout_keep_prob,scope='dropout6')print(net.shape)  # (16, 1, 1, 4096)net = slim.conv2d(net, 4096, [1, 1], scope='fc7')print(net.shape)  # (16, 1, 1, 4096)# Convert end_points_collection into a end_point dict.net = slim.fully_connected(net, num_classes,activation_fn=slim.softmax, scope='fc8')print(net.shape)  # (16, 1, 1, 1000)print('---')return netin_x = tf.zeros([16, 224, 224, 3])res = vgg_16(in_x)

loss

import tensorflow as tf
vgg = tf.contrib.slim.nets.vgg# Load the images and labels.
images, labels = ...# Create the model.
predictions, _ = vgg.vgg_16(images)# Define the loss functions and get the total loss.
loss = slim.losses.softmax_cross_entropy(predictions, labels)

多输出的多任务模型:在这个例子中,我们有两个损失,分别是通过 slim.losses.softmax_cross_entropy和 slim.losses.sum_of_squares得到的。我们既可以通过相加得到 total_loss,也可以通过 slim.losses.get_total_loss()得到total_loss。这是怎么做到的呢?当你通过TF-Slim创建一个损失函数时,TF-Slim会把损失加入到一个特殊的Tensorflow的损失函数集合中。这样你既可以手动管理损失函数,也可以托管给TF-Slim。

# Load the images and labels.
images, scene_labels, depth_labels = ...# Create the model.
scene_predictions, depth_predictions = CreateMultiTaskModel(images)# Define the loss functions and get the total loss.
classification_loss = slim.losses.softmax_cross_entropy(scene_predictions, scene_labels)
sum_of_squares_loss = slim.losses.sum_of_squares(depth_predictions, depth_labels)# The following two lines have the same effect:
total_loss = classification_loss + sum_of_squares_loss
total_loss = slim.losses.get_total_loss(add_regularization_losses=False)

可以手动管理损失函数,也可以让TF-Slim知晓这个自定义损失函数,然后托管给TF-Slim。

# Load the images and labels.
images, scene_labels, depth_labels, pose_labels = ...# Create the model.
scene_predictions, depth_predictions, pose_predictions = CreateMultiTaskModel(images)# Define the loss functions and get the total loss.
classification_loss = slim.losses.softmax_cross_entropy(scene_predictions, scene_labels)
sum_of_squares_loss = slim.losses.sum_of_squares(depth_predictions, depth_labels)
pose_loss = MyCustomLossFunction(pose_predictions, pose_labels)
slim.losses.add_loss(pose_loss) # Letting TF-Slim know about the additional loss.# The following two ways to compute the total loss are equivalent:
regularization_loss = tf.add_n(slim.losses.get_regularization_losses())
total_loss1 = classification_loss + sum_of_squares_loss + pose_loss + regularization_loss# (Regularization Loss is included in the total loss by default).
total_loss2 = slim.losses.get_total_loss()

train

g = tf.Graph()# Create the model and specify the losses...
...total_loss = slim.losses.get_total_loss()
optimizer = tf.train.GradientDescentOptimizer(learning_rate)# create_train_op ensures that each time we ask for the loss, the update_ops
# are run and the gradients being computed are applied too.
train_op = slim.learning.create_train_op(total_loss, optimizer)
logdir = ... # Where checkpoints are stored.slim.learning.train(train_op,logdir,number_of_steps=1000,save_summaries_secs=300,save_interval_secs=600):

在该例中, slim.learning.train根据 train_op 计算损失、应用梯度step。logdir指定了checkpoints和event文件的存储路径。我们可以限制梯度step到任何数值。这里我们采用1000步。最后, save_summaries_secs=300 表示每5分钟计算一次summaries, save_interval_secs=600 表示每10分钟保存一次模型的checkpoint。

从检查恢复部分变量

# Create some variables.
v1 = tf.Variable(..., name="v1")
v2 = tf.Variable(..., name="v2")
...
# Add ops to restore all the variables.
restorer = tf.train.Saver()# Add ops to restore some variables.
restorer = tf.train.Saver([v1, v2])# Later, launch the model, use the saver to restore variables from disk, and
# do some work with the model.
with tf.Session() as sess:# Restore variables from disk.restorer.restore(sess, "/tmp/model.ckpt")print("Model restored.")# Do some work with the model...
# Create some variables.
v1 = slim.variable(name="v1", ...)
v2 = slim.variable(name="nested/v2", ...)
...# Get list of variables to restore (which contains only 'v2'). These are all
# equivalent methods:
#从检查点文件中恢复name='v2'的变量
variables_to_restore = slim.get_variables_by_name("v2")
# or 从检查点文件中恢复name带有2的所有变量
variables_to_restore = slim.get_variables_by_suffix("2")
# or 从检查点文件中恢复命名空间scope='nested'的所有变量
variables_to_restore = slim.get_variables(scope="nested")
# or 恢复命名空间scope='nested'的所有变量
variables_to_restore = slim.get_variables_to_restore(include=["nested"])
# or 除了命名空间scope='v1'的变量
variables_to_restore = slim.get_variables_to_restore(exclude=["v1"])      # Create the saver which will be used to restore the variables.
restorer = tf.train.Saver(variables_to_restore)with tf.Session() as sess:# Restore variables from disk.restorer.restore(sess, "/tmp/model.ckpt")print("Model restored.")# Do some work with the model...

当图的变量名与checkpoint中的变量名不同时,恢复模型参数

当从checkpoint文件中恢复变量时,Saver在checkpoint文件中定位到变量名,并且把它们映射到当前图中的变量中。之前的例子中,我们创建了Saver,并为其提供了变量列表作为参数。这时,在checkpoint文件中定位的变量名,是隐含地从每个作为参数给出的变量的var.op.name而获得的。这一方式在图与checkpoint文件中变量名字相同时,可以很好的工作。而当名字不同时,必须给Saver提供一个将checkpoint文件中的变量名映射到图中的每个变量的字典。

假设我们定义的网络变量是conv1/weights,而从VGG检查点文件加载的变量名为vgg16/conv1/weights,正常load肯定会报错(找不到变量名),但是可以这样:例子见下:

# Assuming that 'conv1/weights' should be restored from 'vgg16/conv1/weights'
def name_in_checkpoint(var):return 'vgg16/' + var.op.name# Assuming that 'conv1/weights' and 'conv1/bias' should be restored from 'conv1/params1' and 'conv1/params2'
def name_in_checkpoint(var):if "weights" in var.op.name:return var.op.name.replace("weights", "params1")if "bias" in var.op.name:return var.op.name.replace("bias", "params2")variables_to_restore = slim.get_model_variables()
variables_to_restore = {name_in_checkpoint(var):var for var in variables_to_restore}
restorer = tf.train.Saver(variables_to_restore)with tf.Session() as sess:# Restore variables from disk.restorer.restore(sess, "/tmp/model.ckpt")

微调训练

image, label = MyPascalVocDataLoader(...)
images, labels = tf.train.batch([image, label], batch_size=32)# Create the model,20类
predictions = vgg.vgg_16(images,num_classes=20)train_op = slim.learning.create_train_op(...)# Specify where the Model, trained on ImageNet, was saved.
model_path = '/path/to/pre_trained_on_imagenet.checkpoint'# Specify where the new model will live:
log_dir = '/path/to/my_pascal_model_dir/'# Restore only the convolutional layers: 从检查点载入除了fc6,fc7,fc8层之外的参数
variables_to_restore = slim.get_variables_to_restore(exclude=['fc6', 'fc7', 'fc8'])
init_fn = assign_from_checkpoint_fn(model_path, variables_to_restore)# Start training.
slim.learning.train(train_op, log_dir, init_fn=init_fn)

TensorFlow 使用 slim 模块搭建复杂网络相关推荐

  1. TensorFlow搭建VGG-Siamese网络

    TensorFlow搭建VGG-Siamese网络 Siamese原理 Siamese网络,中文称为孪生网络.大致结构如下图所示: Siamese网络有两个输入,一个输出.其中,两个输入经过相同的网络 ...

  2. slim php dd model,第二十四节,TensorFlow下slim库函数的使用以及使用VGG网络进行预训练、迁移学习(附代码)...

    在介绍这一节之前,需要你对slim模型库有一些基本了解,具体可以参考第二十二节,TensorFlow中的图片分类模型库slim的使用.数据集处理,这一节我们会详细介绍slim模型库下面的一些函数的使用 ...

  3. 宝可梦 图片识别python_使用Tensorflow从0开始搭建精灵宝可梦的检测APP

    使用Tensorflow从0开始搭建精灵宝可梦的检测APP 本文为本人原创,转载请注明来源链接 环境要求 Tensorflow1.12.0 cuda 9.0 python3.6.10 Android ...

  4. Tensorflow object detection API 搭建属于自己的物体识别模型(转载修改)

    Tensorflow object detection API 搭建属于自己的物体识别模型 电脑配置信息 开始搭建环境 测试自带案例 准备训练图片 配置文件与模型 开始训练模型 生成最终的训练文件 测 ...

  5. TensorFlow之Slim

    文章目录 What are the various components of TF-Slim? Defining Models Variables Layers Scopes Working Exa ...

  6. tensorflow中slim详解

    1.变量的定义 from __future__ import absolute_import from __future__ import division from __future__ impor ...

  7. Tensorflow object detection API 搭建物体识别模型

    ----------------------------------------------------先把别人博客教程跑通-------------------------------------- ...

  8. 【以太坊】搭建测试网络之ubuntu系统安装node.js

    一.前言 在确认了要在本地搭建测试网络之后,那就不管什么私有链方面的东西了.俗话说万事开头难,博主这边了解到,搭建测试网络必须的环境主要是:node,golang,还有以太坊的geth客户端.OK,方 ...

  9. 学习C++项目—— 搭建多进程网络服务框架,增加业务和日志,心跳机制

    学习计算机网络编程 一.思路和学习方法   本文学习于:C语言技术网(www.freecplus.net),在 b 站学习于 C 语言技术网,并加以自己的一些理解和复现,如有侵权会删除.   接下来对 ...

最新文章

  1. 2022-2028年中国饮水机市场投资分析及前景预测报告
  2. Web Essentials之样式表StyleSheets
  3. 初步学习Linux文件基本属性和Cygwin STATUS_ACCESS_VIOLATION 错误
  4. 洛谷P1182 数列分段`Section II`
  5. lj245a引脚功能图_技术文章—教你快速读懂单片机时序图
  6. id jquery选择器 开头_HTML的id选择器类选择器
  7. 掌握神经网络,我应该学习哪些至关重要的知识点?
  8. sql 整改措施 注入_记一次Sql注入 解决方案
  9. 利用 WireShark 深入调试网络请求
  10. “蓝脑”计划:人造大脑的可能性 文化·探索 CCTV_com
  11. 【Unity3D】人体模型及动画
  12. 微信小程序毕业设计 基于微信共享小程序系统开题报告
  13. 天津电动自行车外贸出口认证GCC合格证
  14. 关于使用 MediaPlayer.setLooping(true) 设置循环播放
  15. cmos与非门电路、或非门电路
  16. AR智能眼镜会成未来趋势
  17. java sort 降序_详解Java sort()数组排序(升序和降序)
  18. iOS 手机照片上传服务器方向不对的原因以及解决方法
  19. 苹果最早明年在Apple Watch中引入microLED显示屏
  20. sh.k6p.co.index.php,PHP--微信中使用支付宝--提示跳转页面的源代码

热门文章

  1. Java 内部类之匿名内部类
  2. 19、网络配线架打线工艺
  3. 蒟蒻重返c++,学海拾贝
  4. JSP+SQL基于JSP的学生信息管理系统(源代码+论文+答辩PPT)
  5. Android Google 账户
  6. 南宁第一职业技术学校计算机专业,南宁第一职业技术学校
  7. cocos-js与android平台互相调用
  8. Quartus Prime基础操作
  9. 企业公众号文章写作方向要从这几个方面着手
  10. 在已有公众号发布微信小程序