Python-Tutorial 12:
Keras und Tensorflow - Python-Frameworks für Machine Learning

Dies Tutorial bietet einen Schnelleinstieg in die Frameworks Keras und Tensorflow, die zu den meistverwendeten Python-Frameworks für Machine Learning gehören. Es werden zwei Beispiele vorgestellt, die repräsentative Anwendungsgebiete veranschaulichen: einerseits die Bilderkennung als Beispiel für Klassifikation und andererseits die Prognose von Stromverbrauchsdaten als Beispiel für eine Regressionsaufgabe.

  Motivation

Eins der meistgenutzten Python-Framework für die Entwicklung Künstlicher Neuronalen Netzwerke und Deep-Learning-Modelle ist Keras mit Tensorflow als Backend.

Warum Keras?

Keras ist ein Python-Paket, das als benutzerfreundliche Programmierschnittstelle für verschiedene Machine Learning Frameworks wie Tensorflow, PyTorch und JAX verwendet wird.

Warum Tensorflow?

Google's Tensorflow ist ein Framework für Maschinelles Lernen und insbesondere Deep Learning. Tensorflow hat Keras schon integriert, d.h. sobald man Tensorflow installiert, ist die passende Keras-Version automatisch dabei. Die Verwendung von Tensorflow bietet z.B. den Vorteil, dass für die Erstellung eigener Machine Learning-Modelle die Rechenkapazität von Google Colab verwendet werden kann.

1 Keras

Keras ist ein Python-Paket, das als benutzerfreundliche Programmierschnittstelle für verschiedene Machine Learning Frameworks wie Tensorflow, PyTorch und JAX verwendet wird.

Keras bietet zum Erstellen eines neuronalen Netzwerks zwei Klassen: Sequential und Functional, die beide die Erstellung mehrschichtiger Netzwerke unterstützen. Die Sequential-API ermöglicht das sequentielle Zusammenzufügen von Schichten (Layer), während mit Hilfe der Functional-API komplexere Anordnungen von Schichten erstellt werden können.

Die Schichten eines Künstlichen Neuronalen Netzwerks sind in Keras durch die Klassen der Layer-API realisiert: Conv2D, MaxPooling2D, Flatten, Dense, LSTM etc. Jede Layer-Klasse hat eine Gewichtsmatrix, eine Größenangabe für die Anzahl verwendeter Neuronen (units), eine Formatbeschreibung der Eingabedaten (input_shape), eine Aktivierungsfunktion (activation), und eine Reihe weiterer Parameter, die die Gestaltung der Schicht steuern.

Die üblichen Schritte beim Erstellen eines Neuronalen Netzwerks (Modell erstellen, Modell trainieren, Modell validieren und verwenden) werden in Keras mit Hilfe der Funktionen compile(), fit() und predict() durchgeführt.

2 Tensorflow

Google's Tensorflow ist ein Framework für Machine Learning, das insbesondere für Anwendungen in der Bild- und Spracherkennung genutzt wird. Tensorflow bietet Programmierschnittstellen für verschiedene Programmiersprachen an, insbesondere Python, Java und C++, davon ist die meistgenutzte und stabilste Schnittstelle die Python API. Die Dokumentation der Tensorflow-API ist umfangreich und die zur Verfügung gestellten Beispiele können durch Ausführung der verlinkten Colab-Notebooks praktisch nachvollzogen werden.

Tensorflow wird zunächst für Aufgaben in der Bild- und Videobearbeitung eingesetzt, sowohl für Aufgaben der Bilderkennung (ist ein Objekt da?) als auch der Bild-Klassifikation (um welches Objekt handelt es sich?). Das Trainieren eines Modells in der Bildklassifikation ist sehr aufwendig - hier kann man mit Tensorflow auf vortrainierte Modelle zurückgreifen und einfach diese für die Klassifikation verwenden.

Was genau ist ein Tensor? Ein Tensor ist im Sprachgebrauch des Machine Learning eine mehrdimensionale konstante Datenstruktur mit einem eigenen Satz an Operationen, die die mathematische Einheit eines künstlichen Neuronalen Netzwerks darstellt. Im Unterschied zu den bekannten mehrdimensionalen Datenstrukturen wie Listen oder Matrizen kann ein Tensor nicht nur mehrere Dimensionen, sondern auch mehrere Achsen haben.
https://www.tensorflow.org/guide/tensor
import tensorflow as tf
import numpy as np
rank_3_tensor = tf.constant([
  [[0, 1, 2, 3, 4],
   [5, 6, 7, 8, 9]],
  [[10, 11, 12, 13, 14],
   [15, 16, 17, 18, 19]],
  [[20, 21, 22, 23, 24],
   [25, 26, 27, 28, 29]],])

print(rank_3_tensor)

3 Bilderkennung mit Keras und Tensorflow

Das folgende Beispiel zeigt, wie ein Künstliches Neuronales Netzwerk für die Ziffernerkennung mit Hilfe von Keras trainiert und für die Klassifikation verwendet wird. Das Ziel ist, ein Modell zu erstellen und zu trainieren, das handgeschriebene Ziffern (grau-weiß-Bilder im Format 28x28 Pixel, die die Ziffern 0,1,2,...,9 darstellen) korrekt klassifizieren kann.

MNIST Ziffern-Datensatz
Fünf Beispiel-Bilder aus dem MNIST-Datensatz


Unser Beispiel für Ziffernerkennung ist an das Simple MNIST convnet aus der Sammlung der Keras-Codebeispiele angelehnt.

3-1 Daten einlesen und vorbereiten

Als Trainings- und Validierungsdatensatz werden 60.000 Ziffern-Bilder aus dem MNIST-Ziffern-Datensatz verwendet. Der MNIST-Ziffern Datensatz kann direkt über Keras geladen werden.
  Die Datenvorbereitung bedeutet, dass die Bild-Daten in eine vorgegebene numerische Form umgewandelt, normalisiert und codiert werden müssen.
  Verwendete Funktionen: load_data(), reshape(), to_categorical()

import numpy as np
import matplotlib.pyplot as plt
from keras.datasets import mnist
from keras.utils import to_categorical, plot_model
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Dense, Flatten
print("1. Lade MNIST-Datensatz")
(trainX, trainY), (testX, testY) = mnist.load_data()
# Ausgabe der Dimensionen des Datensatzes
print('Train: X=%s, Y=%s' % (trainX.shape, trainY.shape))
print('Test: X=%s, Y=%s' % (testX.shape, testY.shape))
print("2. Datenvorbereitung")
trainX = trainX.reshape((trainX.shape[0], 28, 28, 1))
testX = testX.reshape((testX.shape[0], 28, 28, 1))
# Daten werden in den Bereich [0, 1] normalisiert
trainX = trainX.astype("float32") / 255.0
testX = testX.astype("float32") / 255.0
# Zielvariable wird numerisch codiert
trainY = to_categorical(trainY)
testY = to_categorical(testY)
print('Train: X=%s, Y=%s' % (trainX.shape, trainY.shape))
print('Test: X=%s, Y=%s' % (testX.shape, testY.shape))
Ausgabe Datenvorbereitung mit Keras

3-2 Modell definieren und trainieren

In diesem Schritt wird ein Deep Learning-Modell erstellt, für die Trainingsphase konfiguriert und anschließend anhand der zuvor festgelegten Trainingsdaten trainiert.
  Das Modell wird durch Hinzufügen passender Schichten erstellt. Für jede Schicht kann eine Aktivierungsfunktion angegeben werden.
 Verwendete Klassen: Sequential, Conv2D, MaxPooling2D, Flatten, Dense
 Verwendete Methoden: compile(), summary(), fit(), save()

# Definiere das Modell
print("3. Definiere das Modell")
model = Sequential()
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
model.add(MaxPooling2D((2, 2)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2)))
model.add(Flatten())
model.add(Dense(10, activation='softmax'))
model.compile(loss='categorical_crossentropy', metrics=['accuracy'])
model.summary()
# Trainiere das Modell
print("4. Trainiere das Modell\n")
model.fit(trainX, trainY, epochs=8, batch_size=64, verbose=2)
# Speichere das Modell
model.save('digits_model.keras')
Ausgabe
Keras: Modell erstellen    Keras: Modell trainieren

3-3 Modell validieren

In diesem Schritt wird die Güte des Modells bestimmt, dabei werden die Indikatoren loss und accuracy (Vertrauenswahrscheinlichkeit) verwendet.
  Mit Hilfe des Parameters loss wurde bei Erstellung konfiguriert, welche Performance-Metrik während des Trainings minimiert werden soll.
 Die Vertrauenswahrscheinlichkeit ist die Wahrscheinlichkeit, dass für eine Beobachtung eine richtige Vorhersage getroffen wird.
  Verwendete Funktionen: evaluate()

score = model.evaluate(testX, testY, verbose=0)
print("Test loss:", score[0]) # Ausgabe: Test loss: 0.03
print("Test accuracy:", score[1]) # Ausgabe: Test accuracy: 0.99

3-4 Modell für die Klassifikation neuer Bilder verwenden

In diesem Schritt wird das zuvor erstellte Modell verwendet, um neue Bilder korrekt zu klassifizieren.

Schritt 1 Bild laden
Zunächst muss das zu klassifizierende Bild geladen und numerisch dargestellt werden. Konkret wird hier ein Bild, das die Ziffer 5 darstellt, aus einer URL geladen und in die von dem Modell benötigte numerische Darstellung umgewandelt.
  Die selbstdefinierte Funktion prepare_image() hat die Aufgabe, ein als URL übergebenes Bild zu laden und numerisch codiert als NumPy-Array darzustellen.
  Verwendete Funktionen: load_img(), img_to_array()

from keras.preprocessing import image
from keras.utils import get_file

def prepare_image(img_url):  
  '''
  Funktion lädt ein Bild aus einer URL
  und stellt es numerisch codiert als NumPy-Array dar
  '''
  img = None
  try: 
    file = get_file('fname',img_url) # Lade die Datei aus der URL in eine lokale Datei
    # Lade Bild im PIL-Format, 28x28 Pixel
    img = image.load_img(file, color_mode = 'grayscale', target_size=(28, 28))
    # Wandle es in ein Array um
    img = image.img_to_array(img)
    img = img.reshape(1, 28, 28, 1)
    img = img.astype('float32') / 255.0
  except Exception as error:
    print("Error: %s" % error)
  return img
# Test-Bild laden und codieren: digit-5 kann ersetzt werden durch digit-7 etc.
img_url = 'https://elab2go.de/demo-py1/images/digit-5.png'
img = prepare_image(img_url)
print(img) # 

Schritt 2 Modell laden und Vorhersage durchführen
 Das Modell wird aus der zuvor gespeicherten *.keras Datei geladen.
  Die Klassifikation mittels der predict-Funktion liefert als Ergebnis ein NumPy-Array aus 9 Werten zurück, wobei eine 1 an der i-Stelle i bedeutet, dass das Bild als Zahl i klassifiziert wurde.
  Verwendete Funktionen: load_model(), predict()

from keras.models import load_model
# Modell aus Datei laden
model = load_model('digits_model.keras')
# Vorhersage / Klassifikation erstellen
arr = model.predict(img)
# Das Ergebnis ist ein Array z.B. [0,0,0,0,1,0,0,0,0]
print("Array als float:\n", arr) 
# Konvertiere digit_arr in ein ganzzahliges Array
arr = (np.rint(arr[0])).astype(int)
print("Array als int:\n", arr)
print("Das Bild stellt folgende Zahl dar:")
print(np.where(arr == 1)[0])
Ausgabe für das Bild digit-5.png Ziffern-Klassifikation mit Keras Ausgabe für das Bild digit-7.png Ziffern-Klassifikation mit Keras

4 Prognose mit Keras und Tensorflow

Eine weiteres Anwendungsgebiet ist der Einsatz neuronaler Netzwerke in der Zeitreihen­prognose. Zur Prognose einer Zeitreihe legt man ein gleitendes Zeitfenster mit n Werten der Vergangenheit über die Zeitreihe. Die Trainings­aufgabe besteht darin, aus den bekannten Werten deren Zukunft zu schätzen, d.h. aus n Werten in der Eingabe-Schicht auf den nächsten Wert zu schließen.

Demo-PY5 der elab2go-Plattform zeigt die Verwendung von Keras und Tensorflow für die Prognose von Stromverbrauchsdaten. Es wird ein Künstliches Neuronales Netz mit mehreren Long Short-Term Memory (LSTM)-Schichten trainiert, validiert und damit eine Prognose über die zukünftige Entwicklung der Stromverbrauchsdaten erstellt.

Autoren, Tools und Quellen

Autor:
 Prof. Dr. Eva Maria Kiss


Tools:

Quellen und weiterführende Links: