圖像分類

本指南訓練神經網路模型,對服裝圖像進行分類,如運動鞋和襯衫。 如果您不瞭解所有細節,那也沒關係;這是一個完整的TensorFlow程序的快節奏概述,詳細解釋了我們的目標。

本指南使用tf.keras,一個高級API,用於在TensorFlow中構建和訓練模型。

from __future__ import absolute_import, division, print_function, unicode_literals

# TensorFlow and tf.keras
import tensorflow as tf
from tensorflow import keras
# Helper libraries
import numpy as np
import matplotlib.pyplot as plt
print(tf.__version__)

2.0.0-alpha0

1. 導入MNIST數據集

本指南使用Fashion MNIST數據集,該數據集包含10個類別中的70,000個灰度圖像。 圖像顯示了低解析度(28 x 28像素)的單件服裝,如下所示:

Fashion MNIST旨在替代經典的MNIST數據集 - 通常用作計算機視覺機器學習計劃的「Hello,World」。 MNIST數據集包含手寫數字(0,1,2等)的圖像,其格式與我們將在此處使用的服裝的格式相同。

本指南使用Fashion MNIST的多樣性,因為這是一個比普通MNIST稍微更具挑戰性的問題。這兩個數據集都相對較小,用於驗證演算法是否按預期工作。它們是測試和調試代碼的良好起點。

我們將使用60,000張圖像來訓練網路,10,000張圖像來評估網路模型的準確度。您可以直接從TensorFlow訪問Fashion MNIST,直接從TensorFlow導入並加重Fashion MNIST數據:

fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

Downloading data from storage.googleapis.com/ 32768/29515 [=================================] - 0s 0us/step Downloading data from storage.googleapis.com/ 26427392/26421880 [==============================] - 1s 0us/step Downloading data from storage.googleapis.com/ 8192/5148 [===============================================] - 0s 0us/step Downloading data from storage.googleapis.com/ 4423680/4422102 [==============================] - 0s 0us/step

載入數據返回4個NumPy數組:

  • train_images和train_labels數組是訓練集 – 模型用於學習的數據。
  • 模型將根據測試集test_images和test_labels數組進行測試。

圖像為28x28 NumPy數組,像素值範圍為0到255,標籤是一個整數數組,範圍為0到9,這些對應於圖像所代表的服裝類別:

| Label | Class | |-------|-------------| | 0 | T-shirt/top | | 1 | Trouser | | 2 | Pullover | | 3 | Dress | | 4 | Coat | | 5 | Sandal | | 6 | Shirt | | 7 | Sneaker | | 8 | Bag | | 9 | Ankle boot |

每個圖像都映射到一個標籤,由於類名不包含在數據集中,因此將它們存儲在此處以便在繪製圖像時使用:

class_names = [T-shirt/top, Trouser, Pullover, Dress, Coat, Sandal, Shirt, Sneaker, Bag, Ankle boot]

2. 探索數據

讓我們在訓練模型之前探索數據集的格式。以下顯示訓練集中有60,000個圖像,每個圖像表示為28 x 28像素:

print(train_images.shape)

(60000, 28, 28)

同樣,訓練集中有60,000個標籤:

print(len(train_labels)

60000

每個標籤都是0到9之間的整數:

print(train_labels)

array([9, 0, 0, ..., 3, 0, 5], dtype=uint8)

測試集中有10,000個圖像。同樣,每個圖像表示為28 x 28像素:

print(test_images.shape)

(10000, 28, 28)

測試集包含10,000個圖像標籤:

print(len(test_labels)

10000

3. 預處理數據

在訓練網路之前必須對數據進行預處理。 如果您檢查訓練集中的第一個圖像,您將看到像素值落在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_lables[i]])
plt.show()

4. 構建模型

構建神經網路需要配置模型的層,然後編譯模型。

設置圖層

神經網路的基本構建塊是層,圖層從提供給它們的數據中提取表示,希望這些表示對於手頭的問題是有意義的。

大多數深度學習包括將簡單層鏈接在一起。大多數圖層(例如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將圖像的格式從二維陣列(28乘28像素)轉換為一維陣列(28* 28 =784像素)。可以將此圖層視為圖像中未堆疊的像素行並將它們排列在一起。該層沒有要學習的參數,它只重新格式化數據。

在像素被展平之後,網路由兩個tf.keras.layers.Dense層的序列組成。這些是密集連接或完全連接的神經層。第一個Dense層有128個節點(或神經元)。第二層是10節點softmax層,其返回10個概率分數的數組,其總和為1.每個節點包含指示當前圖像屬於10個類之一的概率的分數。

編譯模型

在模型準備好進行訓練之前,它需要更多設置,這些是在模型的編譯步驟中添加的:

  • 損失函數,這可以衡量模型在訓練過程中的準確程度。我們希望最小化此功能,以便在正確的方向上「引導」模型。
  • 優化器,這是基於它看到的數據及其損失函數更新模型的方式。

  • 度量標準,用於監控訓練和測試步驟。以下示例使用精度,即正確分類的圖像分數。 model.compile(optimizer=』adam』, loss=』sparse_categorical_crossentropy』, metrics=[『accuracy』])

訓練模型

訓練神經網路模型需要以下步驟:

  • 將訓練數據輸入模型。在此實例中,訓練數據位於train_images和train_lables數組中。
  • 該模型學習如何關聯圖像和標籤。
  • 我們要求模型對測試集進行預測,在本例中為test_images數組。我們驗證預測是否與test_labels數組中的標籤匹配。

要開始訓練,請調用model.fit()方法,因為它將模型「擬合」到訓練數據:

model.fit(train_images, train_labels, epochs=5)

Epoch 1/5 60000/60000 [==============================] - 5s 91us/sample - loss: 0.5008 - accuracy: 0.8229 Epoch 2/5 60000/60000 [==============================] - 6s 96us/sample - loss: 0.3772 - accuracy: 0.8642 Epoch 3/5 60000/60000 [==============================] - 5s 83us/sample - loss: 0.3383 - accuracy: 0.8770 Epoch 4/5 60000/60000 [==============================] - 6s 93us/sample - loss: 0.3118 - accuracy: 0.8850 Epoch 5/5 60000/60000 [==============================] - 5s 87us/sample - loss: 0.2968 - accuracy: 0.8917 <tensorflow.python.keras.callbacks.History at 0x7fade4985828>

隨著模型訓練,顯示損失和準確度指標。該模型在訓練數據上達到約0.88(或88%)的準確度。

5. 評估精度

接下來,比較模型在測試數據集上的表現情況:

test_loss, test_acc = model.evaluate(test_images, test_labels)
print(『
Test accuracy:』, test_acc)

10000/10000 [==============================] - 0s 48us/sample - loss: 0.3528 - accuracy: 0.8731 Test accuracy: 0.8731

事實證明,測試數據集的準確性略低於訓練數據集的準確性。訓練精度和測試精度之間的差距表示過度擬合。過度擬合是指機器學習模型在新的數據比在訓練數據上表現更差,也就是泛化性不好。

6. 預測

通過訓練模型,我們可以使用它來預測某些圖形。

predictions = model.predict(test_images)

這裡,模型已經 預測了測試集中每個圖像的標籤,我們來看看第一個預測:

print(predictions[0])

array([1.9575714e-06, 6.7943779e-07, 6.8796659e-08, 1.0737034e-08, 4.2004976e-06, 1.7093077e-03, 6.3816929e-05, 3.0452705e-03, 2.9946015e-05, 9.9514478e-01], dtype=float32)

預測是10個數字的數組,它們代表模型的「置信度」,即圖像對應於10種不同服裝中的每一種。我們可以看到哪個標籤具有最高的置信度值:

print(np.argmax(predictions[0]))

9

因此,模型最確信這是一個踝靴,或class_names[9]。檢查測試標籤,該分類是正確的:

print(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()

讓我們用他們的預測繪製幾個圖像。正確的預測標籤是藍色的,不正確的預測標籤是紅色的。該數字給出了預測標籤的百分比(滿分100)。請注意,即使非常自信,模型也可能出錯。

# 繪製前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.9575675e-06 6.7943722e-07 6.8796524e-08 1.0737034e-08 4.2005054e-06 1.7093077e-03 6.3816879e-05 3.0452705e-03 2.9946015e-05 9.9514478e-01]] | | plot_value_array(0, predictions_single, test_labels) _ = plt.xticks(range(10), class_names, rotation=45) plt.show()

model.predict返回列表,一批數據中每個圖像的列表,獲取批次中我們(唯一)圖像的預測:

print(np.argmax(predictions_single[0]))

9

和前面的一樣,模型預測標籤為9。

本教程源代碼


推薦閱讀:
相關文章