更新至 TensorFlow 2.0 alpha 版本
本指南訓練一個神經網絡模型,對運動鞋和襯衫等服裝圖像進行分類。如果你不瞭解所有細節也沒關係,這是一個完整的 TensorFlow 程序的快速概覽。
本指南使用 tf.keras,這是一個高級 API,用於在 TensorFlow 中構建和訓練模型。
!pip install -q tensorflow==2.0.0-alpha0
from __future__ import absolute_import, division, print_function
# TensorFlow 和 tf.keras
import tensorflow as tf
from tensorflow import keras
# 相關庫
import numpy as np
import matplotlib.pyplot as plt
print(tf.__version__)
2.0.0-alpha0
導入 Fashion MNIST 數據集
本指南使用 Fashion MNIST 數據集,該數據集包含 10 個類別的 70,000 張灰度圖像。下圖顯示了低分辨率(28 x 28 像素)的單件服裝:
Fashion MNIST 旨在作爲經典 MNIST 數據集的直接替代品,MNIST 通常用作計算機視覺機器學習程序的“Hello,World”。MNIST 數據集包含手寫數字(0、1、2 等)的圖像,其格式與我們在此處使用的服裝格式相同。
Fashion MNIST 具有多樣性,且比普通的 MNIST 更具挑戰性。兩個數據集都相對較小,能用於驗證算法是否按預期工作。它們是測試和調試代碼的良好起點。
我們將使用 60,000 張圖像來訓練網絡,10,000 張圖像來評估網絡對圖像分類的準確性。你可以直接從 TensorFlow 訪問 Fashion MNIST,只需導入並加載數據:
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
32768/29515 [=================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26427392/26421880 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
8192/5148 [===============================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 0s 0us/step
加載數據集將返回四個 NumPy 數組:
train_images
和train_labels
數組爲訓練集 —— 模型用來學習的數據。- 模型使用測試集
test_images
和test_labels
數組測試模型。
圖像是 28 x 28 NumPy 數組,像素值在 0 到 255 之間。標籤是一個整數數組,範圍從 0 到 9。標籤對應於圖像所代表的服裝類別:
標籤 | 類別 |
---|---|
0 | T-恤 |
1 | 褲子 |
2 | 套衫 |
3 | 連衣裙 |
4 | 大衣 |
5 | 涼鞋 |
6 | 襯衫 |
7 | 運動鞋 |
8 | 手提包 |
9 | 踝靴 |
每個圖像都映射到一個標籤。由於類名不包含在數據集中,因此將它們存儲在列表以便在繪製圖像時使用:
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
探索數據
讓我們在訓練模型之前探索數據集的格式。下面顯示訓練集中有 60,000 張圖像,每張圖像爲 28 x 28 像素:
train_images.shape
(60000, 28, 28)
同樣,訓練集中有 60,000 個標籤:
len(train_labels)
60000
每個標籤都是 0 到 9 之間的整數:
train_labels
array([9, 0, 0, ..., 3, 0, 5], dtype=uint8)
測試集中有 10,000 張圖像。同樣,每張圖像爲 28 x 28 像素:
test_images.shape
(10000, 28, 28)
測試集包含 10,000 個圖像標籤:
len(test_labels)
10000
預處理數據
在訓練網絡之前,必須對數據進行預處理。如果你檢查訓練集中的第一個圖像,你將看到像素值位於 0 到 255 之間:
plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.show()
在將數據送入神經網絡模型之前,我們將這些像素值縮放至 0 到 1 的範圍。先將圖像的數據類型從整數轉換爲浮點數,併除以 255。
這是預處理圖像的功能,以同樣的方式對訓練集和測試集進行預處理非常重要:
train_images = train_images / 255.0
test_images = test_images / 255.0
顯示訓練集中的前 25 張圖像,並在每個圖像下方顯示類名。驗證數據格式是否正確,以及是否已準備好構建和訓練網絡。
plt.figure(figsize=(10,10))
for i in range(25):
plt.subplot(5,5,i+1)
plt.xticks([])
plt.yticks([])
plt.grid(False)
plt.imshow(train_images[i], cmap=plt.cm.binary)
plt.xlabel(class_names[train_labels[i]])
plt.show()
建立模型
構建神經網絡需要配置模型的網絡層,然後編譯模型。
設置網絡層
神經網絡的基本構造塊是網絡層。網絡層從提供給它們的數據中提取表徵,這些表徵對於手頭的問題更有意義。
大多數深度學習包括將簡單層鏈接在一起。大多數層,像 tf.keras.layers.Dense
都有在訓練期間需要學習的參數。
model = keras.Sequential([
keras.layers.Flatten(input_shape=(28, 28)),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dense(10, activation='softmax')
])
網絡中的第一層,tf.keras.layers.Flatten
,將圖像的格式從 2 維數組(28 x 28 像素)轉換爲 28 * 28 = 784 像素的一維數組。該層將圖像像素展開,並進行排列。該層沒有要學習的參數,它只重新格式化數據。
在像素展開爲一維之後,網絡由兩層 tf.keras.layers.Dense
序列組成。這些是密集連接或全連接的神經網絡層。第一個 Dense
層有 128 個節點(或神經元)。第二(最後)層是一個 10 節點的 softmax 層 —— 返回有 10 個概率分數的數組,其總和爲1。每個節點包含指示當前圖像屬於 10 個類之一的概率。
編譯模型
在對模型進行訓練之前,需要一些設置。這些是在模型的 compile
步驟中添加的:
- 損失函數(Loss function)—— 衡量模型在訓練過程中的準確性。我們希望最小化此函數,以便在正確的方向上“引導”模型。
- 優化器(Optimizer)—— 基於數據以及損失函數更新模型的方式。
- 指標(Metrics)—— 監控訓練和測試步驟。以下示例使用 accuracy,即正確分類的圖像比例。
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
訓練模型
訓練神經網絡模型需要以下步驟:
- 將訓練數據輸入模型 —— 在此示例中爲
train_images
和train_labels
數組。 - 模型學習關聯圖像和標籤。
- 使用模型對測試集進行預測 —— 在此示例中爲
test_images
數組。驗證預測結果是否與test_labels
數組中的標籤匹配。
要開始訓練,需要調用 model.fit
方法:
model.fit(train_images, train_labels, epochs=5)
Epoch 1/5
60000/60000 [==============================] - 5s 84us/sample - loss: 0.5039 - accuracy: 0.8214
Epoch 2/5
60000/60000 [==============================] - 4s 74us/sample - loss: 0.3768 - accuracy: 0.8633
Epoch 3/5
60000/60000 [==============================] - 5s 78us/sample - loss: 0.3385 - accuracy: 0.8758
Epoch 4/5
60000/60000 [==============================] - 5s 76us/sample - loss: 0.3131 - accuracy: 0.8838
Epoch 5/5
60000/60000 [==============================] - 5s 79us/sample - loss: 0.2930 - accuracy: 0.8914
<tensorflow.python.keras.callbacks.History at 0x7f9fc269b278>
模型訓練時,顯示損失和準確率指標。該模型在訓練數據上達到約 0.89(或 89%)的準確率。
評估準確率
接下來,比較模型在測試數據集上的性能:
test_loss, test_acc = model.evaluate(test_images, test_labels)
print('\nTest accuracy:', test_acc)
10000/10000 [==============================] - 0s 46us/sample - loss: 0.3595 - accuracy: 0.8740
Test accuracy: 0.874
事實證明,模型在測試集上的準確率略低於訓練集的準確率。訓練準確率和測試準確率之間的差距是過擬合的一個例子。過擬合是指機器學習模型在新數據上的表現比在訓練數據上表現得更差。
作出預測
我們可以使用訓練之後的模型來預測某些圖像。
predictions = model.predict(test_images)
模型已經預測了測試集中每個圖像的標籤。我們來看看第一個預測結果:
predictions[0]
array([1.1913482e-05, 2.5270497e-08, 9.4376639e-07, 5.6023836e-10,
3.0359536e-07, 4.5878277e-03, 1.3910754e-06, 1.4167473e-01,
1.1293515e-05, 8.5371155e-01], dtype=float32)
預測結果是 10 個數字的數組。這描述了模型的“自信程度”,圖像對應於 10 種不同服裝中的一種。我們可以看到哪個標籤具有最高的置信度:
np.argmax(predictions[0])
9
因此,該模型最有信心認爲這個圖像是踝靴,或是 class_names[9]
。我們可以檢查測試標籤,看看這是否正確:
test_labels[0]
9
我們可以繪製出圖像來看看全部 10 個通道。
def plot_image(i, predictions_array, true_label, img):
predictions_array, true_label, img = predictions_array[i], true_label[i], img[i]
plt.grid(False)
plt.xticks([])
plt.yticks([])
plt.imshow(img, cmap=plt.cm.binary)
predicted_label = np.argmax(predictions_array)
if predicted_label == true_label:
color = 'blue'
else:
color = 'red'
plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
100*np.max(predictions_array),
class_names[true_label]),
color=color)
def plot_value_array(i, predictions_array, true_label):
predictions_array, true_label = predictions_array[i], true_label[i]
plt.grid(False)
plt.xticks([])
plt.yticks([])
thisplot = plt.bar(range(10), predictions_array, color="#777777")
plt.ylim([0, 1])
predicted_label = np.argmax(predictions_array)
thisplot[predicted_label].set_color('red')
thisplot[true_label].set_color('blue')
查看第一張圖像(索引爲 0)、預測結果和預測的數組。
i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions, test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions, test_labels)
plt.show()
i = 12
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions, test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions, test_labels)
plt.show()
讓我們繪製更多的圖像。正確的預測標籤標記爲藍色,錯誤的預測標籤標記爲紅色。數字表示對預測標籤的自信百分比。注意,即使預測很自信,結果也可能是錯的。
# 繪製前 X 張測試圖像、預測標籤和真實標籤
# 藍色爲正確預測,紅色爲錯誤預測
num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
plt.subplot(num_rows, 2*num_cols, 2*i+1)
plot_image(i, predictions, test_labels, test_images)
plt.subplot(num_rows, 2*num_cols, 2*i+2)
plot_value_array(i, predictions, test_labels)
plt.show()
最後,使用訓練的模型對單個圖像進行預測。
# 從測試數據集中選出一張圖像
img = test_images[0]
print(img.shape)
(28, 28)
tf.keras
模型被優化爲一次性對樣本的批量或集合進行預測。因此,即使我們使用單個圖像,我們也需要將其添加到列表中:
# 添加圖像至批量
img = (np.expand_dims(img,0))
print(img.shape)
(1, 28, 28)
現在預測圖像:
predictions_single = model.predict(img)
print(predictions_single)
[[1.1913485e-05 2.5270452e-08 9.4376657e-07 5.6023952e-10 3.0359516e-07
4.5878240e-03 1.3910718e-06 1.4167461e-01 1.1293518e-05 8.5371172e-01]]
plot_value_array(0, predictions_single, test_labels)
_ = plt.xticks(range(10), class_names, rotation=45)
model.predict
返回一個列表集,一個列表對應一批量數據中的一個圖像。獲取批量中圖像的預測:
np.argmax(predictions_single[0])
9
和以前一樣,模型預測標籤爲 9。