60. 构建 LeNet-5 Estimator#
60.1. 介绍#
前面的实验中,我们使用 TensorFlow 低阶
tf.nn
模块和高阶
tf.keras
模块,以及 PyTorch 模块
nn.Module
和
nn.Sequential
等 4 种不同的方法来构建了 LeNet-5
经典卷积神经网络。本次挑战将使用学习过的 TensorFlow
Estimator 高阶 API 来重构 LeNet-5 并完成训练。
60.2. 知识点#
TensorFlow Estimator 使用
LeNet-5 卷积神经网络
60.3. LeNet-5 结构#
前面,我们已经使用 2 个框架共 4 种方法实现了 LeNet-5 卷积神经网络,相信你对其结构已经十分熟悉了。
实际上,在学习 TensorFlow 高阶 API 的实验中,我们还介绍了 TensorFlow Estimator。Estimator 具备很多优点,尤其是在生产环境部署,很多优质论文提供的示例代码也是通过 Estimator 分发。
所以,本次挑战你将独立尝试使用 TensorFlow 自定义一个 LeNet-5 网络的 Estimator,并完成训练。由于前面的实验只学习了使用 TensorFlow 提供的预定义 Estimator,所以挑战会提供一些自定义 Estimator 资料供你学习。
开放型挑战
挑战:使用 TensorFlow 构建一个包含 LeNet-5 结构的 Estimator,并完成模型训练和评估。
规定:神经网络结构必须与 LeNet-5 完全一致。可以自由定义损失函数,优化方法及其他超级参数。挑战将提供 MNIST 数据及预处理过程。
首先,我们加载所需 MNIST 数据。
import numpy as np
import tensorflow as tf
# 从课程镜像服务器下载 MNIST NumPy 数据
DATA_URL = "https://cdn.aibydoing.com/aibydoing/files/mnist.npz"
path = tf.keras.utils.get_file("mnist.npz", DATA_URL)
with np.load(path) as data:
# 将 28x28 图像 Padding 至 32x32
x_train = np.pad(
data["x_train"].reshape([-1, 28, 28, 1]),
((0, 0), (2, 2), (2, 2), (0, 0)),
"constant",
)
y_train = data["y_train"]
x_test = np.pad(
data["x_test"].reshape([-1, 28, 28, 1]),
((0, 0), (2, 2), (2, 2), (0, 0)),
"constant",
)
y_test = data["y_test"]
x_train.shape, y_train.shape, x_test.shape, y_test.shape
((60000, 32, 32, 1), (60000,), (10000, 32, 32, 1), (10000,))
参考答案 Exercise 60.1
import tensorflow as tf
def lenet_fn(features, labels, mode):
# 卷积层,6 个 5x5 卷积核,步长为 1,relu 激活,第一层需指定 input_shape
conv1 = tf.keras.layers.Conv2D(filters=6,
kernel_size=(5, 5),
strides=(1, 1),
activation='relu', input_shape=(32, 32, 1))(features["x"])
# 平均池化,池化窗口默认为 2
pool1 = tf.keras.layers.AveragePooling2D(
pool_size=(2, 2), strides=2)(conv1)
# 卷积层,16 个 5x5 卷积核,步为 1,relu 激活
conv2 = tf.keras.layers.Conv2D(filters=16, kernel_size=(
5, 5), strides=(1, 1), activation='relu')(pool1)
# 平均池化,池化窗口默认为 2
pool2 = tf.keras.layers.AveragePooling2D(
pool_size=(2, 2), strides=2)(conv2)
# 需展平后才能与全连接层相连
flatten = tf.keras.layers.Flatten()(pool2)
# 全连接层,输出为 120,relu 激活
fc1 = tf.keras.layers.Dense(units=120, activation='relu')(flatten)
# 全连接层,输出为 84,relu 激活
fc2 = tf.keras.layers.Dense(units=84, activation='relu')(fc1)
# 全连接层,输出为 10,Softmax 激活
logits = tf.keras.layers.Dense(units=10, activation='softmax')(fc2)
# 计算损失
loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)
# 训练模式
if mode == tf.estimator.ModeKeys.TRAIN:
optimizer = tf.train.AdamOptimizer(learning_rate=0.001)
train_op = optimizer.minimize(
loss=loss, global_step=tf.train.get_global_step())
return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op)
# 评估模式
if mode == tf.estimator.ModeKeys.EVAL:
eval_metric_ops = {
"accuracy": tf.metrics.accuracy(
labels=labels, predictions=tf.argmax(input=logits, axis=1))}
return tf.estimator.EstimatorSpec(mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)
上面,我们已经将原 \(28 \times 28 \times 1\) 的原始 NumPy 数组扩充为 \(32 \times 32 \times 1\) 尺寸。接下来,请大家参与 TensorFlow 官方指南,自学从 Keras 模型到 Estimator 模型的内容,基于课程前面构建的 Keras LeNet-5 模型,将其转换为 Estimator 模型并完成训练。
参考学习资料
○ 欢迎分享本文链接到你的社交账号、博客、论坛等。更多的外链会增加搜索引擎对本站收录的权重,从而让更多人看到这些内容。