概述
文章目录
- @[toc]
- 一、简介
- 二、常用的 Layer
- 三、作用域机制(arg_scope)
- 四、两个操作符(repeat 和 stack)
- 五、TensorFlow-Slim 中 Loss 的维护与使用
- 六、Fine-Tuning Existing Models
- 七、参考资料
文章目录
- @[toc]
- 一、简介
- 二、常用的 Layer
- 三、作用域机制(arg_scope)
- 四、两个操作符(repeat 和 stack)
- 五、TensorFlow-Slim 中 Loss 的维护与使用
- 六、Fine-Tuning Existing Models
- 七、参考资料
一、简介
- 使用 Slim 开发 TensorFlow 程序,增加了程序的易读性和可维护性,简化了 hyper parameter 的调优,使得开发的模型变得通用,封装了计算机视觉里面的一些常用模型(比如VGG、Inception、ResNet),并且容易扩展复杂的模型,可以使用已经存在的模型的 checkpoints 来开始训练算法。。Slim API 常用组件如下:
- arg_scope: scope 内的操作,使用相同的参数设定
- layers: 定义了High level 的神经网络层的定义
- nets: 定义了一些常用的网络模型,如 VGG、Inception、ResNet 等
import tensorflow.contrib.slim.nets as nets
vgg = nets.vgg
- regularizes: 规范了权重正则化的使用 API
regularization_loss = tf.add_n(slim.losses.get_regularization_losses())
total_loss = slim.losses.get_total_loss(add_regularization_losses=False)
- 导入方法:
import tensorflow.contrib.slim as slim
二、常用的 Layer
conv2d
的参数设置:- 输入数据(
NHWC
),输出channel
数,卷积核大小,卷积步长(默认为 1
)补零方式(默认为 SAME
) - 激活函数(
默认为 relu
)、命名空间 - 权重和偏置的初始化(
默认为 xavier 和 0
)、正则化参数 - BN 以及其参数(可选)
- 输入数据(
# Adds an 2-D convolution followed by an optional batch_norm layer.
# Performs atrous convolution with input stride/dilation rate equal to `rate`
def conv2d(inputs,
num_outputs,
kernel_size,
stride=1,
padding='SAME',
activation_fn=nn.relu,
scope=None
weights_initializer=initializers.xavier_initializer(),
weights_regularizer=None,
biases_initializer=init_ops.zeros_initializer(),
biases_regularizer=None,
normalizer_fn=None,
normalizer_params=None,
trainable=True,
data_format=None, # 默认是 'NHWC'
rate=1,
reuse=None,
variables_collections=None,
outputs_collections=None)
separable_conv2d
的参数设置:- 输入数据(
NHWC
),卷积核大小,卷积步长(默认为 1
)补零方式(默认为 SAME
) - 输出
channel
数:若不设置为 None,则添加一个pointwise convolution
,卷积核大小和步长均为 1 - 激活函数(
默认为 relu
)、命名空间 - 权重和偏置的初始化(
默认为 xavier 和 0
)、正则化参数 - BN 以及其参数的设置(可选)
- 输入数据(
# Adds an 2-D separable convolution followed by an optional batch_norm layer.
def separable_conv2d(
inputs,
kernel_size,
depth_multiplier=1,
stride=1,
padding='SAME',
num_outputs,
activation_fn=nn.relu,
scope=None
normalizer_fn=None,
normalizer_params=None,
trainable=True,
weights_initializer=initializers.xavier_initializer(),
pointwise_initializer=None,
weights_regularizer=None,
biases_initializer=init_ops.zeros_initializer(),
biases_regularizer=None,
data_format=DATA_FORMAT_NHWC,
rate=1,
reuse=None,
variables_collections=None,
outputs_collections=None)
fully_connected
的参数设置:- 输入数据(
NC
),输出神经元数 - 激活函数(
默认为 relu
)、命名空间 - 权重和偏置的初始化(
默认为 xavier 和 0
)、正则化参数 - BN 以及其参数(可选)
- 输入数据(
def fully_connected(inputs,
num_outputs,
# Explicitly set it to None to skip it and maintain a linear activation.
activation_fn=nn.relu,
scope=None,
weights_initializer=initializers.xavier_initializer(),
weights_regularizer=None,
biases_initializer=init_ops.zeros_initializer(),
biases_regularizer=None,
normalizer_fn=None,
normalizer_params=None,
trainable=True,
reuse=None,
variables_collections=None,
outputs_collections=None)
max_pool2d
的参数设置:- 输入数据(
NHWC
),卷积核大小,卷积步长(默认为 2
)补零方式(默认为 VALID
) - 命名空间
- 输入数据(
def fully_connected(inputs,
num_outputs,
# Explicitly set it to None to skip it and maintain a linear activation.
activation_fn=nn.relu,
scope=None,
weights_initializer=initializers.xavier_initializer(),
weights_regularizer=None,
biases_initializer=init_ops.zeros_initializer(),
biases_regularizer=None,
normalizer_fn=None,
normalizer_params=None,
trainable=True,
reuse=None,
variables_collections=None,
outputs_collections=None)
batch_norm
的参数设置:- 输入数据(
NHWC
):the normalization is over all but the last dimension - 滑动平均参数(
decay
):decay for the moving average - center(平移参数): 默认为 True, add offset of
beta
to normalized tensor - scale(缩放参数): 默认为 False,
gamma
is not used. When the next layer is linear (also e.g.nn.relu
), this can be disabled since thescaling can be done by the next layer
- activation_fn: default set to None to skip it and maintain a linear activation.
- is_training: Whether or not the layer is in training mode
- 输入数据(
def batch_norm(inputs,
decay=0.999,
center=True,
scale=False,
epsilon=0.001,
activation_fn=None,
is_training=True,
param_initializers=None,
param_regularizers=None,
updates_collections=ops.GraphKeys.UPDATE_OPS,
reuse=None,
variables_collections=None,
outputs_collections=None,
trainable=True,
batch_weights=None,
fused=None,
data_format=DATA_FORMAT_NHWC,
zero_debias_moving_mean=False,
scope=None,
renorm=False,
renorm_clipping=None,
renorm_decay=0.99,
adjustment=None)
dropout
参数设置- inputs: The tensor to pass to the nn.dropout op.
- keep_prob: A scalar
Tensor
with the same type as x. The probability that each element is kept. - is_training: A bool
Tensor
indicating whether or not the model is in training mode. If so, dropout is applied and values scaled. Otherwise, inputs is returned.
# With probability keep_prob, outputs the input element scaled up by 1 / keep_prob, otherwise outputs 0.
# The scaling is so that the expected sum is unchanged.
def dropout(inputs,
keep_prob=0.5,
noise_shape=None,
is_training=True,
outputs_collections=None,
scope=None,
seed=None)
三、作用域机制(arg_scope)
- 这个新的作用域允许使用者明确
一个或者多个操作和一些参数
传递给 arg_scope 内部的每一个操作 - 在 arg_scope 中规定的参数值,它们可以被局部
覆盖
# 在第一个 arg_scope 中,卷积层和全连接层被应用于相同的权重初始化和权重正则化;
# 在第二个arg_scope中,额外的参数仅仅对卷积层 conv2d 起作用
with slim.arg_scope([slim.conv2d, slim.fully_connected],
activation_fn=tf.nn.relu,
weights_initializer=tf.truncated_normal_initializer(stddev=0.01),
weights_regularizer=slim.l2_regularizer(0.0005)):
with slim.arg_scope([slim.conv2d], stride=1, padding='SAME'):
net = slim.conv2d(inputs, 64, [11, 11], 4, padding='VALID', scope='conv1')
net = slim.conv2d(net, 256, [5, 5],
weights_initializer=tf.truncated_normal_initializer(stddev=0.03),
scope='conv2')
net = slim.fully_connected(net, 1000, activation_fn=None, scope='fc')
四、两个操作符(repeat 和 stack)
slim.repeat
: 允许用户用相同的参数重复调用同一种操作slim.stack
: 允许用户用不同的参数重复调用同一种操作
# 示例 1
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')
# slim.repeat 允许用户用相同的参数重复调用同一种操作
# 它会自动给每一个卷积层的 scopes 命名为'conv3/conv3_1', 'conv3/conv3_2' 和 'conv3/conv3_3'
net = slim.repeat(net, 3, slim.conv2d, 256, [3, 3], scope='conv3')
net = slim.max_pool2d(net, [2, 2], scope='pool2')
# 示例 2
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')
# slim.stack 允许用户用不同的参数重复调用同一种操作(调用了slim.fully_connected 三次,简化多层的全连接层)
# 它会自动给每一个卷积层的 scopes 命名为'fc/fc_1', 'fc/fc_2' 和 'fc/fc_3'
slim.stack(x, slim.fully_connected, [32, 64, 128], scope='fc')
# 示例 3:
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')
# slim.stack 允许用户用不同的参数重复调用同一种操作(调用了slim.conv2d 三次,简化多层的卷积层)
slim.stack(x, slim.conv2d, [(32, [3, 3]), (32, [1, 1]), (64, [3, 3]), (64, [1, 1])], scope='core')
五、TensorFlow-Slim 中 Loss 的维护与使用
- 当你通过 TF-Slim 创建一个 loss 时,TF-Slim 将 loss 添加到一个特殊的
TensorFlow collection of loss functions
,这使得你既可以手动得管理全部的 loss,也可以让 TF-Slim 来替你管理它们 - 如果你想让 TF-Slim 为你管理 losses ,但是你有一个
自己实现的 loss
该怎么办?- loss_ops.py 也有一个函数
add_loss
可以将你自己实现的 loss 加到 TF-Slims collection 中
- loss_ops.py 也有一个函数
# 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(add_regularization_losses=True)
六、Fine-Tuning Existing Models
# 1、Restoring Variables(all/partial) from a 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
...
# 2、Partially Restoring Models
-------------------------------------------------------
# Create some variables.
v1 = slim.variable(name="v1", ...)
v2 = slim.variable(name="nested/v2", ...)
...
# Get list of variables to restore (which contains only 'v2'),注意 exclude 和 include 的用法
# These are all equivalent methods:
variables_to_restore = slim.get_variables_by_name("v2")
# or
variables_to_restore = slim.get_variables_by_suffix("2")
# or
variables_to_restore = slim.get_variables(scope="nested")
# or
variables_to_restore = slim.get_variables_to_restore(include=["nested"])
# or
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
...
# 3、Restoring models with different variable names
-------------------------------------------------------
# restore a model from a checkpoint whose variables have different names to those in the current graph
# Assuming than 'conv1/weights' should be restored from 'vgg16/conv1/weights'
def name_in_checkpoint(var):
return 'vgg16/' + var.op.name
# Assuming than '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")
# 4、 Initialize our new model using the values of the pre-trained model excluding the final layer
--------------------------------------------------------------------------------------------
# Load the Pascal VOC data
image, label = MyPascalVocDataLoader(...)
images, labels = tf.train.batch([image, label], batch_size=32)
# Create the model
predictions = vgg.vgg_16(images)
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,去除全连接层
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)
七、参考资料
1、https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/slim
2、https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/layers/python/layers/layers.py
3、https://github.com/tensorflow/models/tree/master/research/slim/nets
4、TensorFlow-Slim 开源的训练好的模型列表
5、TensorFlow-Slim Tutorial 翻译
最后
以上就是迷路耳机为你收集整理的TensorFlow Slim 的常用操作的全部内容,希望文章能够帮你解决TensorFlow Slim 的常用操作所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复