Grundklassifizierung: Bilder von Kleidung klassifizieren

Auf TensorFlow.org ansehen Quelle auf GitHub anzeigen Notizbuch herunterladen

In diesem Leitfaden wird ein neuronales Netzwerkmodell trainiert, um Bilder von Kleidung wie Turnschuhen und Hemden zu klassifizieren. Es ist in Ordnung, wenn Sie nicht alle Details verstehen; Dies ist ein schneller Überblick über ein vollständiges TensorFlow-Programm mit den Details, die Sie im Laufe der Zeit erklären.

Dieses Handbuch verwendet tf.keras , eine High-Level-API zum Erstellen und Trainieren von Modellen in TensorFlow.

# TensorFlow and tf.keras
import tensorflow as tf

# Helper libraries
import numpy as np
import matplotlib.pyplot as plt

print(tf.__version__)
2.5.0

Importieren Sie den Fashion MNIST-Datensatz

Dieser Leitfaden verwendet den Fashion MNIST- Datensatz, der 70.000 Graustufenbilder in 10 Kategorien enthält. Die Bilder zeigen einzelne Kleidungsstücke in niedriger Auflösung (28 x 28 Pixel), wie hier zu sehen:

Mode-MNIST-Sprite
Abbildung 1. Fashion-MNIST-Beispiele (von Zalando, MIT-Lizenz).

Fashion MNIST ist als Drop-In-Ersatz für den klassischen MNIST- Datensatz gedacht, der oft als "Hello, World" von maschinellen Lernprogrammen für Computer Vision verwendet wird. Der MNIST-Datensatz enthält Bilder von handgeschriebenen Ziffern (0, 1, 2 usw.) in einem Format, das mit dem der hier verwendeten Kleidungsstücke identisch ist.

Dieses Handbuch verwendet Fashion MNIST aus Gründen der Abwechslung und weil es ein etwas anspruchsvolleres Problem als normales MNIST ist. Beide Datensätze sind relativ klein und werden verwendet, um zu überprüfen, ob ein Algorithmus wie erwartet funktioniert. Sie sind gute Ausgangspunkte zum Testen und Debuggen von Code.

Hier werden 60.000 Bilder verwendet, um das Netzwerk zu trainieren und 10.000 Bilder, um zu bewerten, wie genau das Netzwerk gelernt hat, Bilder zu klassifizieren. Sie können direkt von TensorFlow aus auf das Fashion MNIST zugreifen. Importieren und laden Sie die Fashion MNIST-Daten direkt aus TensorFlow:

fashion_mnist = tf.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

Das Laden des Datensatzes gibt vier NumPy-Arrays zurück:

  • Die Arrays train_images und train_labels sind der Trainingssatz – die Daten, die das Modell zum Lernen verwendet.
  • Das Modell wird gegen die Testreihe , die Arrays test_images und test_labels .

Die Bilder sind 28x28 NumPy Arrays, mit Pixelwerten im Bereich von 0 bis 255. Die Etiketten sind eine Reihe von ganzen Zahlen, die von 0 bis 9. Diese entsprechen der Klasse der Kleidung das Bild darstellt:

Etikette Klasse
0 T-Shirt/Oberteil
1 Hose
2 Zur Seite fahren
3 Kleid
4 Mantel
5 Sandale
6 Hemd
7 Sneaker
8 Tasche
9 Stiefelette

Jedes Bild wird einem einzelnen Etikett zugeordnet. Da die Klassennamen nicht im Datensatz enthalten sind, speichern Sie sie hier, um sie später beim Plotten der Bilder zu verwenden:

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

Erkunden Sie die Daten

Untersuchen wir das Format des Datasets, bevor wir das Modell trainieren. Die folgende Abbildung zeigt, dass das Trainingsset 60.000 Bilder enthält, wobei jedes Bild als 28 x 28 Pixel dargestellt wird:

train_images.shape
(60000, 28, 28)

Ebenso gibt es 60.000 Labels im Trainingsset:

len(train_labels)
60000

Jedes Label ist eine ganze Zahl zwischen 0 und 9:

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

Das Testset enthält 10.000 Bilder. Auch hier wird jedes Bild als 28 x 28 Pixel dargestellt:

test_images.shape
(10000, 28, 28)

Und das Testset enthält 10.000 Bildetiketten:

len(test_labels)
10000

Daten vorverarbeiten

Die Daten müssen vor dem Training des Netzwerks vorverarbeitet werden. Wenn Sie das erste Bild im Trainingssatz untersuchen, werden Sie feststellen, dass die Pixelwerte im Bereich von 0 bis 255 liegen:

plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.show()

png

Skalieren Sie diese Werte auf einen Bereich von 0 bis 1, bevor Sie sie in das neuronale Netzwerkmodell einspeisen. Dazu teilt die Werte von 255. Es ist wichtig , dass der Trainingssatz und der Testsatz in der gleichen Art und Weise vorverarbeitet werden:

train_images = train_images / 255.0

test_images = test_images / 255.0

Um zu überprüfen, ob die Daten das richtige Format haben und Sie bereit sind, das Netzwerk aufzubauen und zu trainieren, lassen Sie uns die ersten 25 Bilder aus dem Trainingssatz anzeigen und den Klassennamen unter jedem Bild anzeigen.

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

png

Baue das Modell

Der Aufbau des neuronalen Netzes erfordert das Konfigurieren der Schichten des Modells und das anschließende Kompilieren des Modells.

Richten Sie die Ebenen ein

Der Grundbaustein eines neuronalen Netzes ist die Schicht . Ebenen extrahieren Darstellungen aus den ihnen zugeführten Daten. Hoffentlich sind diese Darstellungen für das vorliegende Problem sinnvoll.

Der größte Teil des Deep Learning besteht darin, einfache Ebenen miteinander zu verketten. Die meisten Layer, wie tf.keras.layers.Dense , haben Parameter, die während des Trainings gelernt werden.

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(10)
])

Die erste Ebene in diesem Netzwerk, tf.keras.layers.Flatten , wandelt das Format der Bilder von einem zweidimensionalen Array (von 28 x 28 Pixel) in ein eindimensionales Array (von 28 * 28 = 784 Pixel) um. Stellen Sie sich diese Ebene so vor, als würden Sie Pixelreihen im Bild entstapeln und aneinanderreihen. Diese Schicht hat keine zu lernenden Parameter; es formatiert nur die Daten.

Nachdem die Pixel abgeflacht sind, besteht das Netzwerk aus einer Folge von zwei tf.keras.layers.Dense Layers. Dies sind dicht verbundene oder vollständig verbundene neuronale Schichten. Die erste Dense Schicht hat 128 Knoten (oder Neuronen). Die zweite (und letzte) Schicht gibt ein Logits-Array mit der Länge 10 zurück. Jeder Knoten enthält einen Score, der angibt, dass das aktuelle Bild zu einer der 10 Klassen gehört.

Kompilieren Sie das Modell

Bevor das Modell zum Training bereit ist, braucht es noch ein paar Einstellungen. Diese werden während des Kompilierungsschritts des Modells hinzugefügt:

  • Verlustfunktion – Diese misst, wie genau das Modell während des Trainings ist. Sie möchten diese Funktion minimieren, um das Modell in die richtige Richtung zu "lenken".
  • Optimierer – Auf diese Weise wird das Modell basierend auf den angezeigten Daten und seiner Verlustfunktion aktualisiert.
  • Metriken – Wird verwendet, um die Trainings- und Testschritte zu überwachen. Im folgenden Beispiel wird die Genauigkeit verwendet , der Anteil der richtig klassifizierten Bilder.
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

Trainiere das Modell

Das Training des neuronalen Netzmodells erfordert die folgenden Schritte:

  1. Füttern Sie die Trainingsdaten in das Modell. In diesem Beispiel befinden sich die Trainingsdaten in den Arrays train_images und train_labels .
  2. Das Modell lernt, Bilder und Beschriftungen zuzuordnen.
  3. Sie bitten das Modell, Vorhersagen über eine Testreihe zu treffen – in diesem Beispiel das Array test_images .
  4. test_labels dass die Vorhersagen mit den Labels aus dem Array test_labels .

Füttere das Modell

Rufen model.fit zum Starten des Trainings die Methode model.fit – so genannt, weil sie das Modell an die Trainingsdaten „ model.fit “:

model.fit(train_images, train_labels, epochs=10)
Epoch 1/10
1875/1875 [==============================] - 3s 1ms/step - loss: 0.4982 - accuracy: 0.8256
Epoch 2/10
1875/1875 [==============================] - 3s 1ms/step - loss: 0.3747 - accuracy: 0.8658
Epoch 3/10
1875/1875 [==============================] - 3s 1ms/step - loss: 0.3356 - accuracy: 0.8770
Epoch 4/10
1875/1875 [==============================] - 3s 1ms/step - loss: 0.3112 - accuracy: 0.8856
Epoch 5/10
1875/1875 [==============================] - 3s 1ms/step - loss: 0.2941 - accuracy: 0.8915
Epoch 6/10
1875/1875 [==============================] - 3s 1ms/step - loss: 0.2776 - accuracy: 0.8972
Epoch 7/10
1875/1875 [==============================] - 3s 1ms/step - loss: 0.2678 - accuracy: 0.9000
Epoch 8/10
1875/1875 [==============================] - 3s 1ms/step - loss: 0.2564 - accuracy: 0.9049
Epoch 9/10
1875/1875 [==============================] - 3s 1ms/step - loss: 0.2467 - accuracy: 0.9083
Epoch 10/10
1875/1875 [==============================] - 3s 1ms/step - loss: 0.2399 - accuracy: 0.9103
<tensorflow.python.keras.callbacks.History at 0x7fe108a0c150>

Während der Modellzüge werden die Verlust- und Genauigkeitsmetriken angezeigt. Dieses Modell erreicht eine Genauigkeit von etwa 0,91 (oder 91%) der Trainingsdaten.

Genauigkeit bewerten

Vergleichen Sie als Nächstes die Leistung des Modells im Test-Dataset:

test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)

print('\nTest accuracy:', test_acc)
313/313 - 0s - loss: 0.3413 - accuracy: 0.8814

Test accuracy: 0.8813999891281128

Es stellt sich heraus, dass die Genauigkeit des Test-Datasets etwas geringer ist als die Genauigkeit des Trainings-Datasets. Diese Lücke zwischen Trainingsgenauigkeit und Testgenauigkeit stellt eine Überanpassung dar . Überanpassung tritt auf, wenn ein Modell für maschinelles Lernen bei neuen, zuvor nicht gesehenen Eingaben schlechter abschneidet als bei den Trainingsdaten. Ein überangepasstes Modell "merkt" sich das Rauschen und die Details im Trainingsdatensatz bis zu einem Punkt, an dem es die Leistung des Modells mit den neuen Daten negativ beeinflusst. Weitere Informationen finden Sie unter:

Voraussagen machen

Wenn das Modell trainiert ist, können Sie damit Vorhersagen zu einigen Bildern treffen. Die linearen Ausgaben des Modells, logits . Fügen Sie eine Softmax-Schicht hinzu, um die Logits in Wahrscheinlichkeiten umzuwandeln, die einfacher zu interpretieren sind.

probability_model = tf.keras.Sequential([model, 
                                         tf.keras.layers.Softmax()])
predictions = probability_model.predict(test_images)

Hier hat das Modell das Label für jedes Bild im Testset vorhergesagt. Schauen wir uns die erste Vorhersage an:

predictions[0]
array([2.9212106e-07, 1.6208847e-10, 1.3363140e-08, 2.7341349e-09,
       5.5379962e-10, 4.5457238e-04, 4.2226111e-06, 4.4925120e-03,
       5.8868943e-07, 9.9504781e-01], dtype=float32)

Eine Vorhersage ist ein Array von 10 Zahlen. Sie stehen für das „Vertrauen“ des Models, dass das Bild jedem der 10 verschiedenen Kleidungsstücke entspricht. Sie können sehen, welches Label den höchsten Konfidenzwert hat:

np.argmax(predictions[0])
9

Das Model ist sich also sehr sicher, dass es sich bei diesem Bild um eine Stiefelette oder class_names[9] . Die Prüfung des Prüfetiketts zeigt, dass diese Einstufung richtig ist:

test_labels[0]
9

Stellen Sie dies grafisch dar, um den vollständigen Satz von 10 Klassenvorhersagen anzuzeigen.

def plot_image(i, predictions_array, true_label, img):
  true_label, img = 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):
  true_label = true_label[i]
  plt.grid(False)
  plt.xticks(range(10))
  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')

Vorhersagen überprüfen

Wenn das Modell trainiert ist, können Sie damit Vorhersagen zu einigen Bildern treffen.

Schauen wir uns das 0. Bild, die Vorhersagen und das Vorhersage-Array an. Die Labels für korrekte Vorhersagen sind blau und die Labels für falsche Vorhersagen sind rot. Die Zahl gibt den Prozentsatz (von 100) für das vorhergesagte Label an.

i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i],  test_labels)
plt.show()

png

i = 12
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i],  test_labels)
plt.show()

png

Lassen Sie uns mehrere Bilder mit ihren Vorhersagen plotten. Beachten Sie, dass das Modell auch dann falsch sein kann, wenn es sehr zuversichtlich ist.

# Plot the first X test images, their predicted labels, and the true labels.
# Color correct predictions in blue and incorrect predictions in red.
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[i], test_labels, test_images)
  plt.subplot(num_rows, 2*num_cols, 2*i+2)
  plot_value_array(i, predictions[i], test_labels)
plt.tight_layout()
plt.show()

png

Verwenden Sie das trainierte Modell

Verwenden Sie schließlich das trainierte Modell, um eine Vorhersage über ein einzelnes Bild zu treffen.

# Grab an image from the test dataset.
img = test_images[1]

print(img.shape)
(28, 28)

tf.keras Modelle sind optimiert, um Vorhersagen für einen Batch oder eine Sammlung von Beispielen gleichzeitig zu treffen. Dementsprechend müssen Sie, obwohl Sie ein einzelnes Bild verwenden, es zu einer Liste hinzufügen:

# Add the image to a batch where it's the only member.
img = (np.expand_dims(img,0))

print(img.shape)
(1, 28, 28)

Sagen Sie nun das richtige Label für dieses Bild voraus:

predictions_single = probability_model.predict(img)

print(predictions_single)
[[8.8914348e-05 1.3264636e-13 9.9108773e-01 1.2658383e-10 8.1463791e-03
  1.6905785e-08 6.7695131e-04 2.7492119e-17 5.1699739e-10 7.1339325e-17]]
plot_value_array(1, predictions_single[0], test_labels)
_ = plt.xticks(range(10), class_names, rotation=45)
plt.show()

png

tf.keras.Model.predict gibt eine Liste von Listen zurück – eine Liste für jedes Bild im Datenstapel. Holen Sie sich die Vorhersagen für unser (einziges) Bild im Stapel:

np.argmax(predictions_single[0])
2

Und das Modell sagt erwartungsgemäß ein Etikett voraus.

# MIT License
#
# Copyright (c) 2017 François Chollet
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.