《TensorFlow实战Google深度学习框架第2版》教材中的样例代码,由于tensorflow版本、运行过程的修改、敲码过程中的失误、教材样例自带的错误等原因,可能会导致代码与教材不一致或者不能运行成功,仅供参考。
第10章 TensorFlow高层封装
Keras requires TensorFlow 2.2 or higher.
- 10.1 使用TensorFlow-Slim在MNIST数据集上实现LeNet-5模型
#!/usr/bin/python
# -*- coding: utf-8 -*-
import tensorflow as tf
import tensorflow.contrib.slim as slim
from tensorflow.examples.tutorials.mnist import input_data
# 通过TensorFlow-Slim来定义LeNet-5的网络结构
def lenet5(inputs):
# 将输入数据转化为一个4维数组,其中第一维表示batch大小,另三维表示一张图片
inputs = tf.reshape(inputs, [-1, 28, 28, 1])
# 定义第一层卷积层
# 从下面的代码可以看到通过TensorFlow-Slim定义的网络结构并不需要用户去关心如何声明和初始化变量,而只需要定义网络结构即可
# 下一行代码中定了一个卷积层,该卷积层的深度为32(使用32个卷积核),过滤器的大小为5×5,使用金0填充
net = slim.conv2d(inputs, 32, [5, 5], padding='SAME', scope='layer1-conv')
# 定义一个最大池化层,其过滤器大小为2×2,步长为2
net = slim.max_pool2d(net, 2, stride=2, scope='layer2-max-pool')
# 类似的定义其他网络层结构
net = slim.conv2d(net, 64, [5, 5], padding='SAME', scope='layer3-conv')
net = slim.max_pool2d(net, 2, stride=2, scope='layer4-max-pool')
# 直接使用TensorFlow-Slim封装好的flatten函数将4维矩阵转为2维,这样可以方便后面的全连接层的计算
# 通过封装好的函数,用户不再需要自己计算通过卷积层之后矩阵的大小
net = slim.flatten(net, scope='flatten')
# 通过TensorFlow-Slim定义全连接层,该全连接层有500个隐藏节点
net = slim.fully_connected(net, 500, scope='layer5')
net = slim.fully_connected(net, 10, scope='output')
return net
# 通过TensorFlow-Slim定义网络结构,并使用之前章节中给出的方式训练定义好的模型
def train(mnist):
x = tf.placeholder(tf.float32, [None, 784], name='x-input')
y_ = tf.placeholder(tf.float32, [None, 10], name='y-input')
y = lenet5(x)
# 定义损失函数和训练方法
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))
loss = tf.reduce_mean(cross_entropy)
train_op = tf.train.GradientDescentOptimizer(0.01).minimize(loss)
# 训练过程
with tf.Session() as sess:
tf.global_variables_initializer().run()
for i in range(10000):
xs, ys = mnist.train.next_batch(100)
_, loss_value = sess.run([train_op, loss], feed_dict={x: xs, y_: ys})
if i % 1000 == 0:
print("After %d training step(s), loss on training batch is %g." % (i, loss_value))
def main(argv=None):
mnist = input_data.read_data_sets("/path/to/MNIST_data", one_hot=True)
train(mnist)
if __name__ == '__main__':
tf.app.run()
- 10.1 使用TFLearn在MNIST数据集上实现LeNet-5模型
#!/usr/bin/python
# -*- coding: utf-8 -*-
import tflearn
from tflearn.layers.core import input_data, fully_connected
from tflearn.layers.conv import conv_2d, max_pool_2d
from tflearn.layers.estimator import regression
import tflearn.datasets.mnist as mnist
# 读取MNIST数据
trainX, trainY, testX, testY = mnist.load_data(
data_dir="/path/to/MNIST_data", one_hot=True)
# 将图像数据resize成卷积卷积神经网络输入的格式,其中第一维表示batch大小,另三维表示一张图片
trainX = trainX.reshape([-1, 28, 28, 1])
testX = testX.reshape([-1, 28, 28, 1])
# 构建神经网络,这个过程和TensorFlow-Slim比较类似,input_data定义了一个placeholder来接入输入数据
net = input_data(shape=[None, 28, 28, 1], name='input')
# 通过TFLearn封装好的API定义一个深度为5,过滤器为5×5,激活函数为ReLU的卷积层
net = conv_2d(net, 32, 5, activation='relu')
# 定义一个过滤器为2×2的最大池化层
net = max_pool_2d(net, 2)
# 类似地定义其他的网络结构
net = conv_2d(net, 64, 5, activation='relu')
net = max_pool_2d(net, 2)
net = fully_connected(net, 500, activation='relu')
net = fully_connected(net, 10, activation='softmax')
# 使用TFLearn封装好的函数定义学习任务,指定优化器为sgd,学习率为0.01,损失函数为交叉熵
net = regression(net, optimizer='sgd', learning_rate=0.01,
loss='categorical_crossentropy')
# 通过定义的网络结构训练模型,并在指定的验证数据上验证模型的效果
# TFLearn将模型的训练过程封装到了一个类中,这样可以减少非常多的冗余代码
model = tflearn.DNN(net, tensorboard_verbose=0)
model.fit(trainX, trainY, n_epoch=10,
validation_set=([testX, testY]),
show_metric=True)
- 10.2 使用原生态Keras在MNIST数据集上实现LeNet-5模型