📜 原文链接:https://tensorflow.google.cn/tutorials/quickstart/beginner
本篇文章将使用 Keras 来完成 3 个任务:
- 建立一个对图像进行分类的神经网络
- 训练神经网络
- 评估模型的准确性
下载并安装 TensorFlow2.x,并将其导入到程序中。
import tensorflow as tf
载入并准备好 MINIST数据集,并将样本从整数转换为浮点数:
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
📑 终端输出结果:
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 5s 0us/step
🔔 首次运行上述代码,会通过 Google API 来下载 MNIST 数据。值得注意的是,如果你不能访问访问谷歌,将不能下载该数据集,其他办法请自行百度。
通过将模型的各层进行堆叠,搭建出一个 tf.keras.Sequential
模型,同时选定模型的优化器(optimizer) 和损失函数(loss function):
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10)
])
对于每个样本,模型返回一个 logits 或者 log-odds 的分数向量列表,向量列表中每个元素对应到每个类别。
predictions = model(x_train[:1]).numpy()
predictions
📑 输出结果:
array([[ 0.50147635, 0.27259597, -1.1021543 , -0.20509964, 0.8072599 ,
-0.68293977, -0.45379734, 1.2299292 , 0.31612065, -0.17554879]],
dtype=float32)
💡 这里是 Cifar10 数据集,有 10 个类别,所以对应输出是一个长度为 10 的向量。
通过 tf.nn.softmax
函数可以将这些 logits 分数转换为对应类的概率。
tf.nn.softmax(predictions).numpy()
📑 输出结果:
array([[0.12580125, 0.10006529, 0.02530679, 0.0620616 , 0.1707989 ,
0.03848571, 0.0483966 , 0.26064417, 0.10451677, 0.06392293]],
dtype=float32)
💡 我们也可以将 tf.nn.softmax
作为神经网络中最后一层的激活函数,可将我们的代码修改成如下所示:
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation='softmax') # 这里添加 softmax 激活函数
])
尽管这种方法可以模型的输出更具解释性,但不建议使用此方法,因为当使用 softmax 输出时,不可能给所有模型提供精确并数值稳定的损失值计算。loss.SparseCategoricalCrossentropy
损失函数接收 logits
向量和 from_logits
参数,并且返回每个样本的标量损失。
loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
返回的损失值就是真实类别的负对数概率:如果模型预测的是正确的类别,该值将会为 0。
这个未经训练的模型给出的概率值接近于随机值(随机每个类别的概率为 ),所以初始损失值应该接近于 2.3(-tf.math.log(1/10).numpy()
)。
loss_fn(y_train[:1], predictions).numpy() # 输出:3.2574682
下面我们给模型指定优化器(optimizer)、损失函数(loss function) 以及评价指标(metrics)。
model.compile(optimizer='adam',
loss=loss_fn,
metrics=['accuracy'])
通过 model.fit
方法调整模型参数来使损失值最小化。
model.fit(x_train, y_train, epochs=5)
📑 输出结果:
Epoch 1/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.2976 - accuracy: 0.9127
Epoch 2/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.1418 - accuracy: 0.9578
Epoch 3/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.1060 - accuracy: 0.9678
Epoch 4/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0854 - accuracy: 0.9734
Epoch 5/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0733 - accuracy: 0.9771
<tensorflow.python.keras.callbacks.History at 0x28a2370c6d8>
model.evaluate
方法通常用来评估模型在验证集(Validation-set) 或者测试集(Test-set)的效果。
model.evaluate(x_test, y_test, verbose=2)
📑 输出结果:
313/313 - 1s - loss: 0.0764 - accuracy: 0.9762
[0.07640933990478516, 0.9761999845504761]
💡 verbose 参数可给定 3 个数值,分别为 0、1、2。其中 0 表示不展示,1 表示展示进度条,2 表示直接展示结果。
现在我们的图像分类器在训练集上的预测精度已经接近于 98%。
如果你想要模型输出一个概率值,可以通过结合 softmax 层与封装训练好的模型来实现:
probability_model = tf.keras.Sequential([
model,
tf.keras.layers.Softmax()
])
probability_model(x_test[:5])
📑 输出结果:
<tf.Tensor: shape=(5, 10), dtype=float32, numpy=
array([[6.26229095e-08, 2.68061551e-09, 1.73842454e-05, 2.29407378e-04,
1.80993913e-12, 1.27843300e-08, 9.75732573e-15, 9.99751508e-01,
2.87250344e-07, 1.33290189e-06],
[2.41450930e-08, 1.70489453e-04, 9.99811113e-01, 1.77893126e-05,
3.21382776e-16, 3.48518768e-07, 2.29711770e-08, 6.11730032e-15,
2.43219262e-07, 3.98595375e-14],
[1.51075188e-08, 9.99706924e-01, 3.11348049e-05, 4.63649121e-06,
1.74165580e-05, 2.31678382e-06, 6.91525929e-06, 1.31301495e-04,
9.92691712e-05, 1.81115965e-07],
[9.99845862e-01, 2.93073867e-08, 2.12001796e-05, 6.11394512e-07,
4.11029669e-06, 7.62671652e-06, 3.90081223e-05, 1.91258687e-06,
1.01774184e-07, 7.94934313e-05],
[2.60670390e-07, 3.86829069e-10, 5.87267323e-07, 4.03869542e-08,
9.98871744e-01, 5.70653469e-07, 4.86737747e-07, 9.62683134e-06,
2.05614515e-06, 1.11458707e-03]], dtype=float32)>
其实上述图像分类器也可以这些写:
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5)
model.predict(x_test[:5])