本文参考:
《Tensorflow学习指南:深度学习系统构建详解》
在Tensorflow的学习中,关于Tensorflow的抽象与简化提到最多的就是TF-Slim,因此做了一下简单的记录。TF-Slim属于Tensorflow的抽象库,相对于直接使用Tensorflow硬核搭建CNN,使用TF-Slim代码更加简单,主要原因在于TF-Slim可以直接定义一个层级的操作,包括卷积核大小、数量、权值初始化、正则化和激活函数:
net = slim.conv2d(inputs, 64, [11,11], 4, padding='SAME',
weights_initializer = tf.truncated_normal_initializer(0.0,0.01),
weights_regularizer = slim.l2_regularizer(0.0005))
如果网络结构中存在几个相同的卷积层相连,可以使用repeat命令高效实现,如定义连续五个卷积层:
net = slim.repeat(net, 5, slim.conv2d, 128, [3,3], scope='conv1')
另外TF-Slim可以使用arg_scope产生域,允许传递一组共享参数给域中的每个操作,由于书中并没有完整的实例,因此利用TF-Slim搭建了一个简单的CNN对MNIST数据集进行了识别分类,其完整代码如下:
import tensorflow as tf
from tensorflow.contrib import slim
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/",one_hot=True) #读取数据
batch_size = 100 #每次训练数据集大小
n_batch = mnist.train.num_examples//batch_size #训练批次
#定义输入、输出、神经元保留率
x = tf.placeholder(tf.float32,[None,784],name='x_input')
y = tf.placeholder(tf.float32,[None,10],name='y_input')
keep_prob = tf.placeholder(tf.float32)
x_image = tf.reshape(x,[-1,28,28,1]) #将输入图片二维化
#构建域,将slim.conv2d,slim.fully_connected的参数统一设置,包括采用Relu激活函数、使用L2正则化从截断式正态分布初始化权值
with slim.arg_scope([slim.conv2d,slim.fully_connected],
activation_fn = tf.nn.relu,
weights_initializer = tf.truncated_normal_initializer(0.0,0.01),
weights_regularizer = slim.l2_regularizer(0.0005)):
net = slim.conv2d(x_image,32,[5,5],scope = 'conv_1') #定义卷积层1,采用32个5*5卷积核,默认步长设置为1,padding='SAME'
net = slim.max_pool2d(net,[2,2],scope = 'pool_1') #定义池化层1,采用最大化池化
net = slim.conv2d(net,64,[5,5],scope = 'conv_2') #定义卷积层2
net = slim.max_pool2d(net,[2,2],scope = 'pool_2') #定义池化层2
net = tf.reshape(net,[-1,7*7*64]) #输出扁平成1维
net = slim.fully_connected(net,1024,scope = 'full_1')#定义全连接层1
net = slim.dropout(net,keep_prob=keep_prob,scope = 'drop_1') #随机丢弃1-keep_prob的神经元
prediction = slim.fully_connected(net,10,activation_fn=tf.nn.softmax,scope = 'full_2') #定义全连接层2,此时输出采用Softmax激活函数
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=prediction)) #损失函数
train_step = tf.train.AdamOptimizer(0.0001).minimize(loss)
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(prediction,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32)) #精确率
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
batch_xs,batch_ys = mnist.train.next_batch(batch_size)
for epoch in range(5):
for batch in range(n_batch):
batch_xs,batch_ys = mnist.train.next_batch(batch_size)
sess.run(train_step,feed_dict={x:batch_xs,y:batch_ys,keep_prob:0.7}) #训练时70%神经元工作
acc = sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels,keep_prob:1.0})#测试时全部神经元工作
print("Iter " + str(epoch) + ",Testing Accuracy " + str(acc))
输出结果:
Iter 0,Testing Accuracy 0.9029
Iter 1,Testing Accuracy 0.9362
Iter 2,Testing Accuracy 0.9499
Iter 3,Testing Accuracy 0.9606
Iter 4,Testing Accuracy 0.9645
由于本人电脑比较印度,只训练了五个周期做样例。由代码可以看出使用TF-Slim在定义网络层方面,代码的确简化,在定义复杂网络的时候,使用TF-Slim优势更加明显。
以上。