Aufgabenstellung

Verwenden Sie diese Seite, um ein jupyter-Notebook zu erstellen. Es soll Codeboxen in sinnvoller Gliederung enthalten, die von Erklärungen und Kommentaren in Markdown-Boxen begleitet werden.

1. Vorbereitung

Verwendet wird das Tools keras. Es ist (unter anderem) Bestandteil der python-Bibliothek tensorflow. Dazu kommen mit numpy und matplotlib zwei weitere Standardbibliotheken.

# TensorFlow und Keras
import tensorflow as tf
from tensorflow import keras            

# Hilfsbibliotheken
import numpy as np
import matplotlib.pyplot as plt

Das sagen die Entwickler über ihre Bibliotheken:

2. Datenbeschaffung

Um das Notebook flexibel zu gestalten, werden die Daten in Ordnern abgelegt, so kann man einfach Pfade ändern:

# Daten einlesen
TRAIN_DATA_FOLDER = "/srv/tausch/ki/kleidung/train"
TEST_DATA_FOLDER = "/srv/tausch/ki/kleidung/test"

train_images = np.load(file=f"{TRAIN_DATA_FOLDER}/train_images.npy")
train_labels = np.load(file=f"{TRAIN_DATA_FOLDER}/train_labels.npy")

test_images = np.load(file=f"{TEST_DATA_FOLDER}/test_images.npy")
test_labels = np.load(file=f"{TEST_DATA_FOLDER}/test_labels.npy")

Bei .npy-Dateien handelt es sich um binäre Exportformate der numpy-Bibliothek. Die Bilddatei enthält Arrays von Bildern, die selbst mehrdimensionale Arrays sind, die Labeldatei ein Array der zu lernenden Kategorien. Im Beispielfall handelt es sich um Graustufenbilder, auch wenn sie später farbig dargestellt werden können. Wichtig ist außerdem, dass die Arrays synchronisiert sind.

# Eigenschaften der Daten
num_images = len(test_images)
print(f"{num_images} Bilddaten aus dem Testkatalog geladen")

# Wie sieht so ein Bild aus?
img_id = 20
plt.imshow(test_images[img_id], cmap = 'gray')
plt.title(f"Testbild {img_id}: {train_images[img_id].shape}")
plt.show()

Das colormap-Attribut ist optional. Lässt man es weg, bekommt man Falschfarbenbilder in violett und gelb. Wichtig ist das shape-Attribut, es gibt die Bildgröße an.
→ Jetzt könnte man auch mal in den Trainingsdatensatz schauen…

# Wie sehen die Labels aus?
print(train_labels)

3. Modell entwerfen

Neuronale Netze bestehen aus Schichten. In der Eingabeschicht liegen die Daten, im Beispiel sind das 28x28 Knoten, die den Pixeldaten der Bilder entsprechen. Die Ausgabeschicht besteht aus Knoten für jede der Kategorien, hier also 10. Dazwischen befinden sich eine oder mehrere Schichten mit (fast) beliebig vielen Knoten.

Abbildung: kilabfrankfurt.de

Formal gesehen soll dieses konkrete Netz eine Funktion ℕ784 → ℝ10 lernen, die 784-dimensionale Argumente auf 10-dimensionale Funktionswerte abbildet. Da sich diese Funktion nicht analytisch darstellen lässt, lässt man das Netz mit einem Teil der Wertetabelle lernen und hofft, dass es dann die „fehlenden“ Werte ergänzen kann. Ein solches neuronales Netz ist mit Keras schnell hergestellt:

# Ein sehr einfaches neuronales Netzwerk konfigurieren...
model = keras.Sequential()
model.add(keras.layers.Flatten(input_shape=(28,28)))
model.add(keras.layers.Dense(200))
model.add(keras.layers.Dense(200))
model.add(keras.layers.Dense(200))
model.add(keras.layers.Dense(10))

# ...und erstellen
model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy'])

Flatten erzeugt aus dem 2d-Bildarray ein 1d-Array von Knoten. Dabei wird die Lagebeziehung der Pixel zueinander berücksichtigt - einige liegen zwar in verschiedenen Zeilen aber trotzdem direkt nebeneinander. Eine Dense-Schicht hat die Eigenschaft, dass jeder Knoten darin mit jedem Knoten der vorigen Schicht verbunden wird.

Außerdem handelt es sich um ein so genanntes Feed-Forward-Netz, Daten laufen also immer nur von links nach rechts.

4. The Magic™ happens

# Modell mit Daten trainieren
training = model.fit(train_images, train_labels, epochs=5)

… bitte warten… das Netz berechnet Ergebnisse, vergleicht mit den Lösungen und verschiebt seine Berechnungen etwas weiter in die richtige Richtung… bitte warten…

# Trainingsfortschritt anzeigen
plt.plot(training.history['accuracy'])
plt.show()

Mit matplotlib kann man nicht nur Bilder, sondern Grafiken allgemeiner Art anzeigen, natürlich auch Diagramme.

→ Was bedeutet der Graph?

5. Auswertung - Nutzung des Netzes

Das trainierte Netz kann man zu den Testdaten befragen. Natürlich auch zu den Trainingsdaten, aber die „kennt“ es ja schon...

# Welches Label hat den höchsten Wert?
img_id = 97
model.predict(test_images[[img_id]])

Die Ausgabe ist der Ergebnisvektor des Netzes für diese Eingabe. Interessant ist die Koordinate mit dem maximalen Wert. Wenn man nur wüsste, welcher Index für welche Kategorie steht...

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

# Label in Produktnamen umbenennen
highestvalue = np.argmax(model.predict(test_images[[img_id]]))
print(real_labels[highestvalue])

Jetzt wäre es natürlich schön, wenn man sehen könnte, was auf diesem Bild tatsächlich ist… Man kann ja auch noch ein paar weitere Testbilder bestimmen lassen.


        

Da auch die Testdaten gelabelt sind, kann man die allgemeine Performance des Netzes bestimmen.

# Für alle Testdaten checken
score = model.evaluate(test_images, test_labels, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])