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:
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)
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.
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.
# 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?
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])