Ziffern-identifizieren
In diesem Projekt soll ein trainiertes Modell die Ziffern 0 bis 9 erkennen. Hierfür wurde das Modell mit dem MNIST Datensatz trainiert und anschließend mit Methoden des Data Science evaluiert, um eine hohe Treffergenauigkeit zu garantieren.
Das untere Feld dient als Testfeld. Hier soll der Benutzer eine Ziffer mit der Maus zeichnen und anschließend auf den Button 'Auswerten' klicken. Das Ergebnis wird nach wenigen Sekunden angezeigt. Falls das gezeichnete Bild nicht gefällt, kann man einfach auf den 'Clear'-Button klicken und das Feld wird wieder leer. Um eine möglichst hohe Trefferquote zu erzielen, wird empfohlen, die Ziffer möglichst zentriert zu zeichnen.
Das Ergebnis ist:
Wie erfolgt das training des Models?
Unter den zahlreichen Klassifikationsalgorithmen, die im Bereich des maschinellen Lernens zur Verfügung stehen, wurde für das Training des Modells in diesem Projekt ein CNN (Convolutional Neural Network) ausgewählt. Dabei handelt es sich um eine spezielle Art von künstlichen neuronalen Netzen, die besonders gut für die Verarbeitung von Bildern und anderen mehrdimensionalen Daten geeignet sind.
Die Trainingsprozedur des Modells lässt sich in drei Phasen unterteilen: Zunächst erfolgt die Datenaufbereitung, anschließend das Training durch ein CNN und schließlich die Auswertung des Ergebnisses. Der Quellcode wird am unteren Ende der Seite zur Verfügung gestellt.
Der erste Schritt ist die Datenbeschaffung, die durch einen einfachen Import aus der Bibliothek "tensorflow" erfolgt. Die Daten bestehen aus zwei Paaren von Datensätzen. Das erste Datensatzpaar ist der Trainingsdatensatz, bestehend aus 60.000 Bildern und 60.000 Zielvariablen (Labels), und das zweite Datensatzpaar besteht aus 10.000 Bildern und 10.000 Zielvariablen (Labels) und ist als Testdatensatz gedacht.
Die Pixelwerte der Trainings- sowie Testdaten werden auf den Wertebereich [0, 1] skaliert und in ein für das neuronale Netz geeignetes Format umgewandelt. Anschließend werden die Zielvariablen (Labels) der Trainings- und Testdaten kategorisiert (One-Hot-Encoding). Der Trainingsdatensatz wird in das zu erstellende neuronale Netz eingespeist, wodurch ein Modell trainiert wird, das anschließend mit den Testdaten evaluiert wird.
Das CNN-Modell basiert auf einer Architektur mit mehreren Schichten, die eine effiziente Verarbeitung und Klassifikation der Bilddaten ermöglicht. Die Eingabeschicht (Input Layer) fungiert als erste Instanz innerhalb des CNN-Modells. Sie ist für die Verarbeitung von Eingabedaten der Form (28, 28, 1) zuständig, was der Größe der MNIST-Bilder entspricht. Die darauf folgende Conv2D-Schicht mit 32 Filtern und einer Kernelgröße von 3x3 verwendet die ReLU-Aktivierungsfunktion. Die ReLU-Funktion führt zu einer sparsamen Aktivierung, da sie negative Eingabewerte auf Null setzt. Dies impliziert, dass lediglich ein Teil der Neuronen in einem gegebenen Layer aktiviert wird, was zu effizienteren und leichter zu interpretierenden Modellen führen kann. Im Anschluss folgt eine Max-Pooling-Schicht, welche die Dimensionen der Feature Maps reduziert und somit die Rechenleistung verringert.
Nach der ersten Conv2D-Schicht folgen zwei weitere Conv2D-Schichten, wobei jede 64 Filter und eine Kernelgröße von 3x3 aufweist. Dadurch können komplexere Merkmale aus den Bilddaten extrahiert werden. Eine Flatten-Schicht wandelt die mehrdimensionalen Feature Maps in einen eindimensionalen Vektor um, der als Eingabe für die Dense-Schichten dient. Im Anschluss werden zwei Dense-Schichten implementiert, wobei die eine 64 und die andere 10 Neuronen aufweist. Die letzte Schicht verwendet die Softmax-Aktivierungsfunktion. Da der MNIST-Datensatz zehn Klassen (Ziffern von 0 bis 9) umfasst, müssen die Ausgangswerte in eine Form gebracht werden, die die Zugehörigkeit zu einer dieser zehn Klassen anzeigt. Die Erfüllung dieser Anforderung wird durch die Verwendung der Softmax-Aktivierungsfunktion gewährleistet, welche sicherstellt, dass jede Ausgabeeinheit eine Wahrscheinlichkeit repräsentiert, die sich auf alle anderen Ausgaben bezieht.
Das Modell wird mit dem Adam-Optimizer kompiliert, da dieser die Vorteile zweier anderer beliebter Optimierungsalgorithmen kombiniert: AdaGrad (Adaptive Gradient Algorithm) und RMSProp (Root Mean Square Propagation). Der Algorithmus berechnet adaptive Lernraten für jeden Parameter, was insbesondere bei rauschigen Daten oder stark variierenden Gradienten von Vorteil ist.
Die Loss-Funktion „categorial_crossentropy” dient der Quantifizierung und Minimierung des Unterschieds zwischen den Vorhersagen des Modells und den tatsächlichen One-Hot-kodierten Klassenlabels. Diese Eigenschaft ist von entscheidender Bedeutung für die Trainingsphase des Modells, da sie eine Anpassung der Modellparameter ermöglicht, die zu einer Verbesserung der Übereinstimmung zwischen den Vorhersagen und den tatsächlichen Klassen führt.
Die Metrik zur Bewertung der Modellleistung ist die Genauigkeit (accuracy), welche zum Überwachen des Trainingsprozesses verwendet wird.
Im Anschluss an die Trainingsphase erfolgt die Evaluation des Models anhand der Testdaten. Hierbei werden die Testdaten, die das Modell während des Trainings nicht gesehen hat, verwendet, um die Prognosen des Models zu überprüfen. Die Güte des Models wird dann anhand der Zahl der korrekt prognostizierten Testdaten im Verhältnis zur Gesamtzahl der Testdaten berechnet. Dies erlaubt eine Evaluierung der tatsächlichen Leistungsfähigkeit des Modells bei der Klassifikation neuer, unbekannter Daten.
# Import der erforderlichen Bibliotheken
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
# Laden und Vorbereiten des Datensatzes
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(-1, 28, 28, 1).astype('float32') / 255
X_test = X_test.reshape(-1, 28, 28, 1).astype('float32') / 255
y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)
# CNN-Modell erstellen
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(28,28,1)))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Flatten())
model.add(Dense(64, activation='relu'))
model.add(Dense(10, activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
# Modell evaluieren
test_loss, test_acc = model.evaluate(X_test, y_test)
print(f'Test accuracy: {test_acc}')