TensorFlow 之 Slim

Slim简介

TF-Slim 是 TensorFlow 中用来构建、训练、评估复杂模型的轻量级库,tf-slim 能够将你从复杂的原生tensorflow中解放出来。
TensorFlow 安装后 tf-slim会自动安装。

Slim模块的优点

Slim模块可以使模型的构建、训练、评估变得简单:

  • 允许用户用紧凑的代码定义模型。这主要由arg_scope、layers和variables来实现。这些工具增加了代码的可读性和可维护性,减少了复制粘贴超参数值出错的可能性,并简化了超参数的调整。
  • 通过提供常用的regularizer来简化模型的开发。很多常用的计算机视觉模型(例如VGG、AlexNet)在Slim里面已经有了实现。这些模型开箱可用,并且能够以多种方式进行扩展。
  • Slim使得”复杂模型的扩展“ 以及 “从现有的模型ckpt开始训练” 变得容易。

使用Slim来构建模型

可以使用slim、variables、layers和scopes来十分简洁的定义定义模型。

Slim 定义变量(Variables)

在原生的tensorflow中创建Variables需要一个预定义的值或者一个初始化机制(例如,高斯分布随机采样)。更进一步,如果需要在一个指定的设备上创建一个variable,必须进行显式指定。为了减少创建variable需要的代码,slim模块在variable.py内提供了一系列的wrapper函数,从而使得变量的定义更加容易。

例如,要创建一个权重variable,用一个截断的正态分布初始化它,用l2_loss进行正则,并将他放到CPU上。只需要进行如下声明即可:

weight = slim.variable('weights',
                                     shape=[10, 10, 3, 3],
                                     initializer=tf.truncated_normal_initialzer(stddev=0.1),
                                     regularizer=slim.l2_regularizer(0.05),
                                     device='/CPU:0')
Slim定义 网络层(Layers)

slim定义网络层相当的方便,比tensorflow原生操作更加抽象,方便。
用conv层举例说明,通常一个卷积层的创建是由很多低级op组成的,比如:

  1. 创建权重variable和偏置值baises
  2. 对权重的输入进行卷积(输入来自前一层)
  3. 卷积结果加上偏置值
  4. 使用激活函数激活

原生的TensorFlow定义卷积层:

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, anme='biases')
    conv1 = tf.nn.relu(bias, name=scope)

如果使用slim来定义就简单很多了,只有一行代码:

input = ...
net = slim.conv2d(input, 128, [3, 3], scope='conv1_1')

经上面比较发现slim构建网络的层相当的简介,这时候可能会有读者会问用slim好像少了一个必要参数。
定义卷积核时 [filter_height, filter_width, in_channels, out_channels] ,分别代表卷积核的高/宽/输入通道数/输出通道数,slim少了一个in_channels(输入通道数)。这个不必担心,in_channels(输入通道数),Slim从input中自动提取了,同样的定义全连接层时也不需要在slim方法中指定上一层的节点数。

input = ...
net = slim.fully_connected(inputs, 32, scope='fc1')  # 只需要指定自己的节点数

关于Slim定义层的内容这里就讲这么多,slim关于层的定义和使用还有很多更加灵活的方式,后续会继续补充!接下来进行用slim进行网络训练实战。

使用Slim创建一个神经网络

以一个简单的多层感知机解决回归问题为例。
该模型只有两个隐藏层,模型输出层只有一个节点。

此外,示例还展示了在第一个全连接层FC1后如何添加Dropout层。
在测试阶段,不需要要Dropout节点,而是采用平均激活,因此需要知道该模型是处于training或tesing阶段,因为在两种情况下的计算图是不同的。

先训练并保存模型

import numpy as np
import tensorflow as tf

import tensorflow.contrib.slim as slim
import matplotlib.pyplot as plt


# 随机生成1d的回归数据
def produce_batch(batch_size, noise=0.3):
    xs = np.random.random(size=[batch_size, 1]) * 10
    ys = np.sin(xs) + 5 + np.random.normal(size=[batch_size, 1], scale=noise)
    return [xs.astype(np.float32), ys.astype(np.float32)]

# 生成训练和测试数据集
x_train, y_train = produce_batch(200)
x_test, y_test = produce_batch(200)
# plt.scatter(x_test, y_test, c='r')
# plt.show()


# 用slim定义的前向传播
def regression_model(inputs, is_training=True, scope='deep_regression'):
    with tf.variable_scope(scope, 'deep_regression', [inputs]):
        end_points = {}
        with slim.arg_scope([slim.fully_connected], activation_fn = tf.nn.relu, weights_regularizer=slim.l2_regularizer(0.001)):
            net = slim.fully_connected(inputs, 32, scope='fc1')
            end_points['fc1'] = net

            net = slim.dropout(net, 0.8, is_training=is_training)

            net = slim.fully_connected(net, 16, scope='fc2')
            end_points['fc2'] = net

            predictions = slim.fully_connected(net, 1, activation_fn=None, scope='prediction')
            end_points['out'] = predictions
    return predictions, end_points



# 将数据转化为tensor
def convert_data_to_tensors(x, y):
    inputs = tf.constant(x)
    inputs.set_shape([None, 1])
    outputs = tf.constant(y)
    outputs.set_shape([None, 1])
    return inputs, outputs



# 训练网络,并将训练模型保存到指定文件夹内
ckpt_dir = '/home/hxy/husin/Test/Slim/'
with tf.Graph().as_default():
    tf.logging.set_verbosity(tf.logging.INFO)  # 日志信息
    inputs, targets = convert_data_to_tensors(x_train, y_train)
    predictions, nodes = regression_model(inputs, is_training=True)
    loss = tf.losses.mean_squared_error(labels=targets, predictions=predictions)
    total_loss = slim.losses.get_total_loss()  # 正则化的loss
    optimizer = tf.train.AdamOptimizer(learning_rate=0.005)
    train_op = slim.learning.create_train_op(total_loss, optimizer)

    final_loss = slim.learning.train(train_op,
                                     logdir=ckpt_dir,       # 模型保存位置
                                     number_of_steps=5000,  # 迭代次数
                                     save_interval_secs=5,  # 每5秒保存一次模型
                                     log_every_n_steps=500) # 损失函数和step打印的频率
    print final_loss
    print ckpt_dir

运行结果:
在这里插入图片描述接下来验证模型:

import numpy as np
import tensorflow as tf

import tensorflow.contrib.slim as slim
import matplotlib.pyplot as plt


# 随机生成1d的回归数据
def produce_batch(batch_size, noise=0.3):
    xs = np.random.random(size=[batch_size, 1]) * 10
    ys = np.sin(xs) + 5 + np.random.normal(size=[batch_size, 1], scale=noise)
    return [xs.astype(np.float32), ys.astype(np.float32)]

# 生成训练和测试数据集
x_train, y_train = produce_batch(200)
x_test, y_test = produce_batch(200)
# plt.scatter(x_test, y_test, c='r')
# plt.show()


# 用slim定义的前向传播
def regression_model(inputs, is_training=True, scope='deep_regression'):
    with tf.variable_scope(scope, 'deep_regression', [inputs]):
        end_points = {}
        with slim.arg_scope([slim.fully_connected], activation_fn = tf.nn.relu, weights_regularizer=slim.l2_regularizer(0.001)):
            net = slim.fully_connected(inputs, 32, scope='fc1')
            end_points['fc1'] = net

            net = slim.dropout(net, 0.8, is_training=is_training)

            net = slim.fully_connected(net, 16, scope='fc2')
            end_points['fc2'] = net

            predictions = slim.fully_connected(net, 1, activation_fn=None, scope='prediction')
            end_points['out'] = predictions
    return predictions, end_points



# 将数据转化为tensor
def convert_data_to_tensors(x, y):
    inputs = tf.constant(x)
    inputs.set_shape([None, 1])
    outputs = tf.constant(y)
    outputs.set_shape([None, 1])
    return inputs, outputs

# 进行模型验证
ckpt_dir = '/home/hxy/husin/Test/Slim/'
with tf.Graph().as_default():
    inputs, targets = convert_data_to_tensors(x_test, y_test)
    predictions, end_point = regression_model(inputs, is_training=False)
    # 创建会话,从checkpoint文件恢复参数
    sv = tf.train.Supervisor(logdir=ckpt_dir)
    with sv.managed_session() as sess:
        inputs, predictions, targets = sess.run([inputs, predictions, targets])
    plt.scatter(inputs, targets, c='r')
    plt.scatter(inputs, predictions, c='b')
    plt.title('red=true, blue=predicted')
    plt.show()

验证结果:
在这里插入图片描述

发布了61 篇原创文章 · 获赞 44 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/HUXINY/article/details/86680442
今日推荐