📜 原文链接: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.npz11493376/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/51875/1875 [==============================] - 4s 2ms/step - loss: 0.2976 - accuracy: 0.9127Epoch 2/51875/1875 [==============================] - 4s 2ms/step - loss: 0.1418 - accuracy: 0.9578Epoch 3/51875/1875 [==============================] - 4s 2ms/step - loss: 0.1060 - accuracy: 0.9678Epoch 4/51875/1875 [==============================] - 4s 2ms/step - loss: 0.0854 - accuracy: 0.9734Epoch 5/51875/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])
