Slim
Slim 简介
Slim ( tf.contrib.slim ) 是一个轻量级的 TensorFlow 框架, 封装了 TensorFlow 的大量 API, 在之前学习过程中我自己明显可以感觉到 tf 的代码太啰嗦了, 想要写一个简单的 CNN 就需要写将近 50 行的辅助函数, 和 20 行的网络搭建, 之前使用 Keras 框架虽然同样可以简化代码, 但是 Keras 和 TensorFlow 的原生 API 彼此的兼容性较差, 而 Slim 则兼备了轻量开发和与 TensorFlow 兼容两大优点
代码对比
原生 TensorFlow
def new_weights(shape):
return tf.Variable(tf.truncated_normal(shape, stddev=0.05))
def new_biases(length):
return tf.Variable(tf.truncated_normal([length], stddev=0.05))
def new_conv_layer(input, nb_filter, nb_channel = 1, filter_size = 3):
shape = [filter_size, filter_size, nb_channel, nb_filter]
weights = new_weights(shape)
biases = new_biases(nb_filter)
layer = tf.nn.conv2d(input = input,
filter = weights,
strides = [1, 1, 1, 1],
padding = "SAME")
layer += biases
layer = tf.nn.max_pool(value = layer,
ksize = [1, 2, 2, 1],
strides = [1, 2, 2, 1],
padding = 'SAME')
layer = tf.nn.relu(layer)
return layer, weights
def flatten_layer(layer):
layer_shape = layer.get_shape()
num_features = layer_shape[1:4].num_elements()
layer_flat = tf.reshape(layer, [-1, num_features])
return layer_flat, num_features
def new_fc_layer(input, nb_input, nb_output, use_relu = True):
weights = new_weights(shape = [nb_input, nb_output])
biases = new_biases(nb_output)
layer = tf.matmul(input, weights) + biases
if use_relu:
layer = tf.nn.relu(layer)
return layer
x = tf.placeholder(dtype = tf.float32, shape = [None, 28, 28, 1])
y_ = tf.placeholder(dtype = tf.float32, shape = [None, nb_class])
layer_1, _ = new_conv_layer(input = x,
nb_filter = 16)
layer_2, _ = new_conv_layer(input = layer_1,
nb_channel = 16,
nb_filter = 32)
layer_flat, fatures = flatten_layer(layer_2)
fc_1 = new_fc_layer(input = layer_flat,
nb_input = fatures,
nb_output = 64)
fc_2 = new_fc_layer(input = fc_1,
nb_input = 64,
nb_output = nb_class,
use_relu = False)
y = tf.nn.softmax(fc_2)
Slim
x = tf.placeholder(dtype = tf.float32, shape = [None, 28, 28, 1])
y_ = tf.placeholder(dtype = tf.float32, shape = [None, nb_class])
layer_1 = slim.conv2d(x, 16, [3, 3])
layer_2 = slim.conv2d(layer1, 32, [3, 3])
layer_flat = slim.flatten(layer_2)
fc_1 = slim.fully_connected(layer_flat, 64)
fc_2 = slim.fully_connected(fc_1, nb_class, activation_fn = None)
y = tf.nn.softmax(fc_2)
由此可见, slim 框架相比于原生 TensorFlow 极大地减少了代码量, 同时 slim 还有以下功能
共享参数
有时候神经网络的层之间的某些参数是相同的, 如 VGG-16 中所有卷积层的卷积核都是 3 * 3, 如果每个层都写一遍会很啰嗦, slim 引入了 arg_scope 机制解决了这一问题
# 写法一
net = slim.conv2d(net, 32, [3, 3], weights_initializer = tf.truncated_normal_initializer(stddev = 0.01), scope = 'conv_1')
net = slim.conv2d(net, 64, [3, 3], weights_initializer = tf.truncated_normal_initializer(stddev = 0.01), scope = 'conv_2')
net = slim.conv2d(net, 128, [3, 3], weights_initializer = tf.truncated_normal_initializer(stddev = 0.01), scope = 'conv_3')
# 写法二
with slim.arg_scope([slim. conv2d], kernel_size = [3, 3], weights_initializer = tf.truncated_normal_initializer(stddev = 0.01)):
net = slim.conv2d(net, 32, scope = 'conv_1')
net = slim.conv2d(net, 64, scope = 'conv_2')
net = slim.conv2d(net, 128, scope = 'conv_3')