Künstliche Neurale Netzwerke#

Emotions are enmeshed in the neural networks of reason.

— António R. Damásio

Künstliche Neuronale Netzwerke haben sich in den letzten Jahren zu einer Schlüsseltechnologie im Bereich des maschinellen Lernens und der künstlichen Intelligenz entwickelt, auch wenn sie historisch zu den ältesten und grundlegendsten Algorithmen im Bereich des maschinellen Lernens und der Mustererkennung gehören und die ersten Grundlagen bereits in den 1950’ entwickelt worden sind [MP43], [Ros58]. Sie sind inspiriert von den biologischen neuronalen Netzwerken des menschlichen Gehirns und versuchen dieses mathematisch nachzuempfinden und somit auch ähnliche Lernerfolge zu erzielen . Sie bestehen aus vielen miteinander verbundenen “Neuronen”, die in Schichten organisiert sind und zur Verarbeitung und Analyse komplexer Datenmuster verwendet werden. Sie werden heutzutage in vielen Anwendungsfällen genutzt insbesondere bei der Verarbeitung unstrukturierter Daten wie Bilder, Texte oder Sprache.

Folien#

Grundlagen#

Neuronen#

Neuronen sind die grundlegenden Bausteine eines neuronalen Netzwerks. Ein Neuron empfängt Eingaben, verarbeitet sie und gibt eine Ausgabe weiter. Die Verarbeitung erfolgt durch eine Aktivierungsfunktion \(f(\cdot)\), die den linearen Eingang in eine nichtlineare Ausgabe umwandelt. Die Grundstruktur eines Neurons besteht aus mehreren Komponenten: Eingaben (Inputs), Gewichte (Weights), Bias und der Aktivierungsfunktion.

../_images/neuron2.drawio.svg

Die Eingaben \(x_1, x_2, ..., x_n\) sind die Signale oder Datenpunkte, die in das Neuron eingespeist werden. Gewichte \(w_1, w_2, ..., w_n\) sind Faktoren, die die Bedeutung jedes Eingangs steuern. Der Bias \(b\) ist ein zusätzlicher Parameter, der den Schwellenwert für die Aktivierung anpasst. Schließlich gibt es die Aktivierungsfunktion \(f(\cdot)\), die den Summenwert der gewichteten Eingaben und des Bias in eine Ausgabe umwandelt. Die Ausgabe eines Neurons wird durch die folgende Formel berechnet:

\[ y = f\left(b + \sum_{i=1}^n w_i x_i\right) \]
  • Eingaben (Inputs, \(x_1, x_2, ..., x_n\)): Signale oder Datenpunkte, die in das Neuron eingespeist werden.

  • Gewichte (Weights, \(w_1, w_2, ..., w_n\)): Faktoren, die die Bedeutung jedes Eingangs steuern.

  • Bias (Bias, \(b\)): Ein zusätzlicher Parameter, der den Schwellenwert für die Aktivierung anpasst.

  • Aktivierungsfunktion (Activation Function, \(f(\cdot)\)): Eine Funktion, die den Summenwert der gewichteten Eingaben und des Bias in eine Ausgabe umwandelt.

Damit gleicht das Neuron in der gleichen Formel einem Generalisierten Linearem Modell (GLM). Bei GLM zielt die Transformationsfunktion \(f(\cdot)\) darauf ab, die Verteilung der Ausgangsvariable zu verändern.

Die meisten Aktivierungsfunktionen bei KNN zielen darauf ab, das Ausgangssignal entweder klarer zu differenzieren (aktiv/inaktiv) oder nichtlinear zu transformieren , um komplexe Zusammenhänge zu lernen. Einige gängige Aktivierungsfunktionen sind:

  • Sigmoid: Diese Funktion kennen wir von den Logistischen Regression und GLM. Sie transformiert den Eingang in einen Wert zwischen 0 und 1, was sie besonders geeignet für die Ausgabe von Wahrscheinlichkeiten macht.

    \[f(x) = (1 + e^{-x})^{-1}.\]
  • ReLU (Rectified Linear Unit): Sie ist eine einfache und häufig verwendete Funktion, die den Eingang direkt zurückgibt, wenn er positiv ist, und ansonsten Null. ReLU ist bekannt dafür, neuronale Netze schneller und effizienter zu trainieren.

    \[f(x) = \max(0, x).\]
  • Tanh (Hyperbolic Tangent): Diese Funktion transformiert den Eingang in einen Wert zwischen -1 und 1 und ist oft in früheren Versionen von neuronalen Netzwerken zu finden. Sie kann in Aufgaben nützlich sein, bei denen sowohl positive als auch negative Werte relevant sind.

    \[f(x) = \tanh(x).\]
  • Softmax: Die Softmax-Funktion normalisiert die Ausgabe eines Neurons auf eine Wahrscheinlichkeitsverteilung, wobei die Summe aller Ausgänge 1 ergibt. Sie wird häufig in mehrstufigen Klassifizierungsaufgaben eingesetzt, wo sie die Wahrscheinlichkeiten aller Klassen gleichzeitig ausgibt.

    \[f(x_i) = e^{-x_i}(\sum_{j}^K e^{x_j})^{-1}.\]

Die Wahl der richtigen Aktivierungsfunktion hängt von der spezifischen Aufgabe und der Architektur des neuronalen Netzes ab. Generell ist ReLU aufgrund seiner Einfachheit und Effizienz eine beliebte Wahl, während Sigmoid und Tanh in Situationen nützlich sein können, wo negative Werte relevant sind oder eine interpretierbare Ausgabe gewünscht ist. Softmax wird ausschließlich für mehrstufige Klassifizierungsaufgaben verwendet.

Schichten#

Die Fähigkeit komplexe Zusammenhänge zu erlernen, ergibt sich vor allem daraus, dass Neuronale Netzwerke aus mehreren Schichten von Neuronen bestehen, die in einer bestimmten Architektur angeordnet sind.

Die erste Schicht ist die Eingabeschicht (Input Layer) und nimmt die Rohdaten des Problems entgegen und leitet sie an die nachfolgenden Schichten weiter. Diese Schicht enthält keine Aktivierungsfunktionen und dient lediglich als Schnittstelle zur Datenaufnahme.

Danach folgen mehrerer verborgene Schichten (Hidden Layers). Diese Schichten enthalten Neuronen, die die eingehenden Daten verarbeiten und transformieren. Die Anzahl der verborgenen Schichten sowie die Anzahl der Neuronen in jeder Schicht können je nach Komplexität des Netzwerks variieren. Bei modernen Tiefen Neuronalen Netzwerken (DNN - Deep Neural Networks) ist die Anzahl der Schichten hoch (3-100 Schichten).

Schließlich gibt es die Ausgabeschicht (Output Layer), die das Ergebnis der Verarbeitung durch das Netzwerk liefert. Die Anzahl der Neuronen in der Ausgabeschicht hängt von der Art des zu lösenden Problems ab. Für binäre Klassifikationsprobleme enthält die Ausgabeschicht oft nur ein Neuron, während für Mehrklassenklassifikationsprobleme mehrere Neuronen erforderlich sind, um die verschiedenen Klassen zu repräsentieren.

../_images/neuronal_network2.drawio.svg

Trainingsprozess#

Der Grund, weshalb Neuronale Netzwerke fast 60 Jahre lang nicht genutzt wurden, lag in Skalierbarkeit des Trainings. Das oben abgebildete Beispiel zeigt bereits, die hohe Anzahl an 25 Parametern (Gewichte und Bias) für ein kleines Netzwerk mit vier Schichten. Leistungsfähige Netze haben bis zu Milliarden an Parametern.

Aufgrund der Komplexität können die Parameter nicht direkt berechnet werden und werden deshalb normalerweise iterativ angenähert. Dieser Prozess umfasst typischerweise folgende Schritte:

  1. Zufällige Initialisierung aller Parameter \(w\) und \(b\) mit Zufallszahlen.

  1. Vorwärtsausbreitung (Forward Propagation): Die Eingabedaten werden durch das Netzwerk geleitet und die Ausgabe geschätzt. Jedes Neuron berechnet seine Aktivierungsfunktion basierend auf den gewichteten Eingaben und dem Bias mit Hilfe der oben angegeben Formel.

  1. Berechnung des Fehlers (Loss Calculation): Der Fehler oder Verlust wird durch eine Verlustfunktion berechnet, die die Differenz zwischen der vorhergesagten Ausgabe und der tatsächlichen Ausgabe misst. Die passende Verlustfunktionen richtet sich dabei nach dem Datentyp der Ausgangsvariable. Typische Verlustfunktionen kennen wir bereits:

    \[E^{\text{MSE}} = \frac{1}{n} \sum_{j=1}^{n}(\hat y_j - y_j)^2\]
    \[E^{\text{LL}} = -\frac{1}{n} \sum_{j=1}^{n} y_j log(\hat y_j)\]
  1. Rückwärtsausbreitung (Backpropagation): Der Fehler wird durch das Netzwerk rückwärts propagiert, um die Gradienten der Verlustfunktion bezüglich der Gewichte und Biases zu berechnen. Dabei wird im Wesentlichen der Fehler rückwärts im Netzwerk verteilt, so dass Neuronen, die einen großen Anteil an der Vorhersage haben (also hohe Gewichtung und Bias bei hoher Eingangswert), ein größerer Anteil am Fehler zugeteilt wird. Der Gradient \( \nabla {E(w_{ij})} \) des Gewichtes \(w_{ij}\) kann mit der Kettenregel berechnet werden:

    \[ \nabla {E(w_{ij})} = \frac{\partial E}{\partial w_{ij}} \]
    \[ \nabla {E(b_{i})} = \frac{\partial E}{\partial b_{i}} \]

    Die entsprechende partielle Ableitung richtet sich prinzipiell nach der Aktivierungsfunktion, wird aber meist numerisch bestimmt, wie z.B. bereits bei der Logistischen Regression diskutiert.

  1. Gewichtsaktualisierung (Weight Update): Die Gewichte und Biases werden mithilfe eines Optimierungsalgorithmus wie Gradient Descent oder Adam angepasst, um den Fehler zu minimieren. Beim Gradient Descent geschieht dies durch Anwendung der berechneten Gradienten auf die Gewichte und Biases mit Hilfe der Lernrate \(\alpha\):

    \[w_{ij} = w_{ij} - \alpha * \nabla E(w_{ij})\]
    \[b_{i} = b_{i} - \alpha * \nabla E(b_{i})\]
  1. Abbruchkriterium: Wiederholung der Schritte 2.-5. bis ein Konvergenzkriteriums erfüllt wurde oder eine maximale Anzahl an Iterationen erreicht wird.

Der Trainingsprozess wird in der Regel über mehrere Epochen wiederholt, wobei jede Epoche eine Durchführung des gesamten Trainingsdatensatzes darstellt. Dies ermöglicht es dem Netzwerk, die Gewichte iterativ zu verbessern und seine Leistung auf neuen Daten zu generalisieren. Ein entscheidender Grund für den heutigen Erfolg von Neuronalen Netzwerken ist, dass diese Berechnung der Gewichte hoch parallelisierbar ist und somit sehr gut auf modernen Graphikkarten parallelisiert werden können.

Ein häufiges Problem beim Training neuronaler Netzwerke ist Overfitting, bei dem das Netzwerk die Trainingsdaten zu gut lernt und auf neuen Daten schlecht generalisiert. Um Overfitting zu vermeiden und die Leistung des Netzwerks zu verbessern, werden verschiedene Techniken der Regularisierung eingesetzt:

  • Regularisierung (z.B. L1, L2): Hinzufügen eines Regularisierungsterms zur Verlustfunktion, um die Komplexität des Modells zu kontrollieren.

  • Dropout: Zufälliges Ausschalten von Neuronen während des Trainings, um die Abhängigkeit von bestimmten Neuronen zu reduzieren.

  • Datenaugmentation: Erweiterung des Trainingsdatensatzes durch zufällige Transformationen der Daten.

Architekturen#

Ein weiterer wichtiger Faktor für den Erfolg von Neuronalen Netzwerken ist die Fähigkeit Neuronen in unterschiedlichen Architekturen zu verbinden und sie dadurch zu befähigen bestimmte Datenstrukturen besser zu lernen.

Vorwärtsgerichtete Netze#

Die einfachsten Formen neuronaler Netzwerke sind Vorwärtsgerichtete Neuronale Netze (FNN - Feedforward Neural Networks). Bei ihnen fließen die Daten in eine Richtung von der Eingabeschicht zur Ausgabeschicht, ohne rückwärts gerichtete Datenflüsse. Sie entsprechen den oben dargestellten Netzwerken. Sie sind besonders geeignet bei einfachen Problemen, wo keine Autokorrelation oder komplexe Muster vorherrschen.

../_images/neuron2.drawio.svg

Rekurrente Netze#

Rekurrente oder rückgekoppelte Neuronale Netze (RNN - Recurrent Neural Networks) sind neuronalen Netzen, die sich von Feedforward-Netzen dadurch unterscheiden, dass sie Verbindungen zwischen Neuronen einer Schicht zu Neuronen derselben oder vorheriger Schichten ermöglichen. Diese Art der Verschaltung ähnelt der bevorzugten Struktur neuronaler Netze im Gehirn, insbesondere im Neocortex. RNNs sind ideal für sequenzielle Daten wie Zeitreihen oder Text, da sie über Schleifen verfügen, die Informationen über Zeitpunkte (oder Wortfolgen/Sätze) hinweg speichern. Dadurch lässt sich z.B. gut die Autoregression in Zeitreihen oder komplette Sätze erlernen.

\[ y_j = f\left(b + \sum_{i=1}^n w_{i,j} x_{i,j} + v y_{j-1} \right) \]
../_images/neuron_recurrent.drawio.svg

Faltungsnetze#

Faltungsnetze (CNN - Convolutional Neural Networks) sind besonders effektiv bei der Verarbeitung von höherdimensionalen Daten wie Bilddaten oder geospatialer Daten. Sie verwenden Faltungsoperationen, um Merkmale (Kanten, Reliefs, Muster, etc.) aus Eingabebildern zu extrahieren oder zu erlernen und gleichzeitig einen höherendimensionalen Eingang auf einen niedrigdimensionaleren Ausgang zu reduzieren, der diese Merkmale encodiert. Dadurch repräsentiert der Ausgang nur die Relevanz des extrahierten oder gelernten Merkmals und es muss nicht das Gesamtbild gelernt werden. Durch Schichtung mehrere versteckter Faltungsschichten hintereinander werden so zuerst Merkmale extrahiert und dann Muster dieser im Bild gelernt (z.B. die Form eines Hundes). Auf die Faltung und die Bildverarbeitung werden wir im Nachfolgekurs “Maschinelles Lernen und Künstliche Intelligenz” noch vertieft eingehen.

../_images/neuron_convolution.drawio.svg

Neuronale Netzwerke in Python#

Neuronale Netzwerke in sklearn#

Es gibt verschiedene Bibliotheken für Neuronale Netzwerke in Python. Wir betrachten zuerst sklearn, da wir dort Neuronale Netzwerke einfach mit der bekannten API nutzen können.

Wir demonstrieren neuronale Netzwerke anhand einer erweiterten Version des Yin-Yang-Beispiels aus der Klassifikation indem wir die Anzahl der Farben auf 4 Kategorien und die Verwirbelung erhöhen. Wieder besteht die Aufgabe darin, die richtige Farbe basierend auf dem Punkt vorherzusagen, also eine Klassifikationsaufgabe. Wir erstellen die Daten wie folgt:

import numpy as np # Import von NumPy
import pandas as pd # Import von Pandas
import plotly.express as px # Import von Plotly
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split

np.random.seed(33)
N = 1000  # Anzahl der Punkte
X1 = np.random.normal(size=N)
X2 = np.random.normal(size=N)
X = np.column_stack((X1, X2))

alpha = np.arctan2(X2, X1)
r = np.sqrt(X1**2 + X2**2)

## Teile the sum of a sin and cosine into 5 intervals
category = pd.cut(np.sin(3*alpha + 2*r) + np.cos(3*alpha + 2*r),
           bins=[-1.5, -1.1, -0.6, 0.6, 1.1, 1.5],
           labels=[0, 1, 2, 3, 4])
y = category.astype(int)

# Teile in Test und Trainings-Datensatz
X_train, X_test, y_train, y_test = train_test_split(X, y)
# Darstellung des Datensatzes
fig=px.scatter(x=X2, y=X1, color=y, width=600, height=600)
fig.update_traces(marker_line=dict(width=.3, color="black"))
fig.show()

Das Bild zeigt ein komplexes Muster von Spiralarmen in fünf verschiedenen Farben. Dreiarmige gelbe und blauen Arme entsprechen den größten und kleinsten Werten, während sechsarmige Arme in verschiedenen Rot- und Violetttönen den dazwischen liegenden Werten entsprechen. Diese Entscheidungsgrenzen sind sehr schwer mit einfachen Modellen wie logistischer Regression, SVM oder sogar Bäumen zu erfassen. Prüfen wir das noch einmal mit einer kleinen Visualisierungsfunktion, die wir auch in der Klassifikation genutzt haben.

mcolors=['blue', 'purple', 'violet', 'orange', 'yellow']

def DBPlot(m, X, y, nGrid = 300):
    x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx1, xx2 = np.meshgrid(np.linspace(x1_min, x1_max, nGrid), 
                           np.linspace(x2_min, x2_max, nGrid))
    XX = np.column_stack((xx1.ravel(), xx2.ravel()))
    hatyy = m.predict(XX).reshape(xx1.shape)
    fig = px.imshow(hatyy, width=600, height=600)
    fig.add_scatter(x=X[:,0]/(x1_max-x1_min)*nGrid+nGrid/2, y=X[:,1]/(x2_max-x2_min)*nGrid+nGrid/2, mode="markers", 
                    marker=dict(color=[mcolors[i] for i in y]), marker_line=dict(width=.3, color="black"))
    fig.update_coloraxes(showscale=False)
    fig.update_layout(showlegend=False)
    fig.show()

Testen wir einen Random Forest, so erhalten wir zwar ein gutes Modell, dass allerdings overfittet und schlecht generalisiert.

from sklearn.ensemble import RandomForestClassifier

m = RandomForestClassifier()
_ = m.fit(X_train, y_train)
m.score(X_test, y_test)
0.772
confusion_matrix(y_test, m.predict(X_test))
array([[52,  0,  2,  0,  0],
       [10, 19,  5,  0,  0],
       [ 4,  7, 50,  9,  0],
       [ 0,  0, 10, 24,  4],
       [ 0,  0,  3,  3, 48]])
DBPlot(m, X_test, y_test)

Ein SVM mit radialem Kernel erkennt die Struktur besser, aber hat einen deutlich höheren Fehler.

from sklearn.svm import SVC

m = SVC(kernel="rbf", gamma=1)
_ = m.fit(X_train, y_train)
m.score(X_test, y_test)
0.544
confusion_matrix(y_test, m.predict(X_test))
array([[43,  0, 11,  0,  0],
       [19,  0, 15,  0,  0],
       [11,  0, 52,  0,  7],
       [ 1,  0, 11,  0, 26],
       [ 3,  0, 10,  0, 41]])
DBPlot(m, X_test, y_test)

Allerdings können neuronale Netzwerke (und k-NN) deutlich besser damit umgehen.

sklearn implementiert einfache Feed-Forward-Neuronale Netzwerke, so genannte Multi-Layer Perceptrons. Dies sind einfache dichte Feed-Forward-Netzwerke mit einer beliebigen Anzahl von versteckten Schichten. Auch wenn sie strukturell einfache neuronaler Netzwerke sind, sind sie dennoch leistungsfähig genug für viele Aufgaben.

Wie bei anderen fortgeschrittenen Modellen bietet sklearn zwei unterschiedlichen Klassen für Klassifikationsaufgaben MLPClassifier und für Regressionsaufgaben MLPRegressor. Die grundlegende Verwendung dieser Modelle ist identisch zu den anderen sklearn-Modellen.

Die wichtigsten Argumente für den MLPClassifier sind:

MLPClassifier(hidden_layer_sizes, activation, max_iter, alpha)

Von diesen ist hidden_layer_sizes der zentralste. Dies beschreibt die Anzahl der versteckten Schichten (die Größe der Eingabe- und Ausgabeschicht wird automatisch aus den Daten bestimmt). Es handelt sich um ein Tupel, das die Anzahl der Knoten für jede versteckte Schicht angibt, daher gibt die Länge des Tupels auch die Anzahl der versteckten Schichten an. Zum Beispiel bedeutet hidden_layer_sizes = (32, 16) zwei versteckte Schichten, die erste mit 32 und die folgende mit 16 Knoten. activation beschreibt die Aktivierungsfunktion. Es empfiehlt sich meist es bei der Standardfunktion relu zu lassen, außer es gibt die oben beschriebenen Gründe für andere Aktivierungsfunktionen. alpha ist der L2-Regularisierungsparameter und max_iter gibt die maximale Anzahl von Iterationen an, bevor die Optimierung stoppt.

Lassen Sie uns nun die Verwendung von MLPClassifier an den Yin-Yang Beispiel demonstrieren. Beginnen wir mit einem einfachen Perzeptron mit einer einzigen versteckten Schicht von 20 Knoten. Daher verwenden wir hidden_layer_sizes=(20,), ein Tupel mit nur einer Zahl. Das Anpassen des Modells und die Vorhersage sind größtenteils ähnlich wie bei den anderen sklearn-Funktionen, daher diskutieren wir dies hier nicht. Wir erhöhen auch die Anzahl der Iterationen, da die Standardanzahl von 200 in diesem Fall zu gering ist:

from sklearn.neural_network import MLPClassifier

m = MLPClassifier(hidden_layer_sizes = (20,), max_iter=10000)
_ = m.fit(X_train, y_train)
m.score(X_test, y_test)
0.408
confusion_matrix(y_test, m.predict(X_test))
array([[35,  1, 14,  0,  4],
       [16,  4, 10,  0,  4],
       [19,  1, 24,  0, 26],
       [ 2,  0, 17,  0, 19],
       [ 1,  0, 14,  0, 39]])
DBPlot(m, X_test, y_test)

Dieses einfache Modell hat zuerst auch nur eine niedrige Genauigkeit. Das liegt daran, dass es zu einfach ist, nur eine einzelne kleine versteckte Schicht reicht nicht aus, um das komplexe Spiralmuster gut zu modellieren. Was sich gut in der Visualisierung erkennen lässt. Wir können dort sehen, dass das Modell die Idee korrekt einfängt: Spiralen in verschiedenen Farben, aber die Form der Spiralen ist nicht genau genug.

Lassen Sie uns das Modell mit einem leistungsstärkeren Netzwerk wiederholen:

m = MLPClassifier(hidden_layer_sizes = (256, 128, 64), max_iter=10000)
_ = m.fit(X_train, y_train)
m.score(X_test, y_test)
0.892
confusion_matrix(y_test, m.predict(X_test))
array([[49,  3,  2,  0,  0],
       [ 5, 26,  3,  0,  0],
       [ 1,  3, 61,  5,  0],
       [ 0,  0,  2, 35,  1],
       [ 0,  0,  0,  2, 52]])
DBPlot(m, X_test, y_test)

Jetzt sind die Ergebnisse sehr gut mit einer Genauigkeit von ca. 95 %. Die visuelle Inspektion bestätigt, dass das leistungsstärkere neuronale Netzwerk die Gesamtstruktur des Modells gut erfassen kann.

Die angepassten Netzwerkmodelle haben verschiedene Methoden und Attribute, z.B. gibt coefs_ die Modellgewichte aus (als Liste von Gewichtsmatrizen, eine für jede Schicht), und intercepts_ gibt die Modell-Biaswerte aus (als Liste von Bias-Vektoren, einer für jede Schicht). Zum Beispiel enthält das oben angepasste Modell

np.sum([b.size for b in m.intercepts_])
453

Bias.

Während sklearn einen einfachen Zugang zu neuronalen Netzwerkmodellen bietet, sind diese Modelle erheblich eingeschränkt. Für leistungsstärkere Netzwerke muss man andere Bibliotheken wie tensorflow oder pytorch verwenden.

Neuronale Netzwerke in Keras#

Tensorflow and Keras#

Tensorflow ist eine Bibliothek, die Berechnungsgraphen implementiert, die automatisch Gradienten berechnen können. Sie ermöglicht auch Berechnungen auf der GPU durchzuführen, was potenziell zu erheblichen Geschwindigkeitsverbesserungen gegenüber CPU-Berechnungen führen kann. In vielerlei Hinsicht ähnelt sie numpy, wo man Matrizen und Tensoren erstellen und manipulieren kann. Allerdings ist sie aufgrund des Berechnungsgraphen-Ansatzes und der GPU-bezogenen Überlegungen viel schwieriger zu verwenden.

Keras ist ein TensorFlow-Front-End, ein Submodul, das einen viel benutzerfreundlicheren Zugang zum Aufbau neuronaler Netzwerke bietet. Die Funktionalität umfasst eine Vielzahl von Netzwerkschichten, bei denen man die entsprechenden Parameter anpassen kann. Beim Aufbau des Netzwerks kann man einfach die Schichten hintereinander hinzufügen, die Verbindung zwischen den Schichten wird von Keras selbst übernommen. Eine gute Quelle für die Keras-Dokumentation ist die API-Referenzdokumentation.

Tensorflow kann schwierig und frustrierend zu installieren sein. Normalerweise funktioniert es gut mit conda install tensorflow oder pip install tensorflow. Manchmal können jedoch Probleme auftreten und es kann schwierig sein, die Probleme zu finden und zu beheben. Insbesondere installiert pip normalerweise die neueste Version, auch wenn sie mit dem Rest Ihrer Pakete nicht kompatibel ist. Es installiert auch Abhängigkeiten und kann bestimmte Pakete aktualisieren, was die Python-Installation beeinträchtigen kann. Um Probleme mit dem Rest Ihres Systems zu vermeiden, empfehlen wir dringend, es in einer virtuellen Umgebung wie Anaconda zu installieren.

Beispielnetzwerk in keras#

Lassen Sie uns das Farbspiralbeispiel aus dem letzten Abschnitt von sklearn neu implementieren, diesmal jedoch mit keras. Es wird einige bemerkenswerte Unterschiede geben:

Der Aufbau des Netzwerks selbst ist in Keras anders. Keras berechnet nicht die Größe der Eingabe- und Ausgangsschichten aus den Daten. Beide müssen vom Benutzer angegeben werden. Schließlich sagt Keras nur Wahrscheinlichkeiten für alle Kategorien voraus, daher müssen wir Code hinzufügen, der die Spalte (Kategorie) mit der höchsten Wahrscheinlichkeit findet.

Das Modell erzeugen#

Zuerst der wichtigste Schritt: Aufbau und Kompilierung des Modells. Dies unterscheidet sich sehr von der Vorgehensweise in sklearn. Lassen Sie uns ein sequentielles Modell mit dichten Schichten aufbauen, die gleiche Architektur, die wir mit sklearn erstellt haben:

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

# sequential (not recursive) model (one input, one output)
model=Sequential()
model.add(Dense(512, activation="relu", input_shape=(2,)))
model.add(Dense(256, activation="relu"))
model.add(Dense(64, activation="relu"))
nCategories = len(np.unique(category))
model.add(Dense(nCategories, activation="softmax"))

Wir beginnen mit dem Importieren der Funktionalität, die wir von tensorflow.keras benötigen. Danach erstellen wir ein leeres sequenzielles Modell (d.h. ein Modell, das keine Schleifen und rückwärts fließende Daten enthält) und fangen an, Schichten hinzuzufügen. Wir fügen 3 dichte Schichten (Dense) hinzu. Die erste Schicht enthält 512 Knoten, die zweite 256 und die letzte Schicht enthält 64 Knoten. Alle diese Knoten werden mit der relu Funktion aktiviert.

Das erste wichtige neue Feature ist das Argument input_shape für die erste Schicht, die Eingabeschicht. Dies sagt Keras, welche Art von Eingaben zu erwarten sind. Derzeit ist es nur ein Tupel (2,), da unsere X-Matrix nur 2 Spalten enthält. Also (2,) ist nur die Form einer einzelnen Zeile von X, einer einzelnen Instanz der Eingabedaten. Sie können die richtige Form mit X[0].shape finden. Aber die Eingabe muss hier nicht nur ein Vektor sein. Zum Beispiel kann es bei Bildern ein 3-D-Tensor mit der Form (Breite, Höhe, #Farbkanäle) sein. Sie müssen das input_shape-Argument nur für die erste Schicht angeben, Keras kann die Informationen für die folgenden Schichten selbst finden.

Wir müssen auch eine explizite Ausgabeschicht hinzufügen. Da es sich hier um Klassifizierung handelt, benötigen wir so viele Ausgabeknoten wie Kategorien - wir können diese Anzahl berechnen als

nCategories = len(np.unique(category))

Jeder Ausgabeknoten wird die Wahrscheinlichkeit vorhersagen, dass die Eingabe in die entsprechende Kategorie fällt. Wir können die softmax (multi-nomiale Logit)-Aktivierung verwenden, um sicherzustellen, dass die Ergebnisse gültige Wahrscheinlichkeiten sind. Beachten Sie, dass im Falle von nur zwei Kategorien die Softmax-Aktivierung äquivalent zur gewöhnlichen logistischen Regression ist. Aber im Gegensatz zur gewöhnlichen logistischen Regression haben wir eine Reihe anderer Schichten vor der letzten logistischen Schicht.

Das richtige Festlegen der Eingabeformen und Ausgabeknoten ist eine der Hauptursachen für Frustration, wenn man anfängt, mit keras zu arbeiten. Die Fehlermeldungen sind lang und nicht besonders hilfreich, und es ist schwer zu verstehen, was das Problem ist. Hier ist eine Checkliste, die durchgearbeitet werden kann, wenn etwas nicht funktioniert:

  • Enthält die erste (und nur die erste) Schicht das Argument input_shape?

  • Stellt input_shape korrekt die Form einer einzelnen Instanz der Eingabedaten dar?

  • Haben Sie die richtige Anzahl von Knoten in der Softmax-aktivierten Ausgangsschicht?

Training des Modells#

Die nächste Aufgabe besteht darin, das Modell zu kompilieren und anzupassen. Keras-Modelle müssen kompiliert werden - was wir bisher eingerichtet haben, ist nur eine Beschreibung des Modells, nicht das tatsächliche Modell, das für TensorFlow-Tensoren eingerichtet ist und möglicherweise für die GPU-Ausführung. Wir können das Modell wie folgt kompilieren:

model.compile(loss='sparse_categorical_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])
print(model.summary())
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense (Dense)               (None, 512)               1536      
                                                                 
 dense_1 (Dense)             (None, 256)               131328    
                                                                 
 dense_2 (Dense)             (None, 64)                16448     
                                                                 
 dense_3 (Dense)             (None, 5)                 325       
                                                                 
=================================================================
Total params: 149637 (584.52 KB)
Trainable params: 149637 (584.52 KB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________
None

Die drei wichtigsten Argumente sind

  • loss beschreibt die Modellverlustfunktion, sparse_categorical_crossentropy, im Wesentlichen die Log-Likelihood, ist geeignet für Kategorisierungsaufgaben. Der genaue Typ hängt auch davon ab, wie das Ergebnis genau codiert ist.

  • optimizer ist der Optimierer, der für den stochastischen Gradientenabstieg verwendet werden soll. adam und rmsprop sind gute Optionen, aber es gibt auch andere Möglichkeiten.

  • metrics ist eine Metrik, die während der Optimierung ausgewertet und gedruckt wird und einige Rückmeldungen darüber bietet, wie die Auswertung verläuft.

Die letzte Zeile hier druckt die Modellzusammenfassung aus, eine praktische Übersicht darüber, was wir gemacht haben:

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 512)               1536      
_________________________________________________________________
dense_1 (Dense)              (None, 256)               131328    
_________________________________________________________________
dense_2 (Dense)              (None, 64)                16448     
_________________________________________________________________
dense_3 (Dense)              (None, 5)                 325       
=================================================================
Total params: 149,637
Trainable params: 149,637
Non-trainable params: 0

Dieses Netzwerk enthält fast 150.000 Parameter, von denen alle trainierbar sind.

Nach erfolgreicher Kompilierung können wir das Modell anpassen:

history = model.fit(X, y, epochs=200)
Epoch 1/200
 1/32 [..............................] - ETA: 5s - loss: 1.6131 - accuracy: 0.1250

32/32 [==============================] - 0s 1ms/step - loss: 1.5759 - accuracy: 0.2820
Epoch 2/200
 1/32 [..............................] - ETA: 0s - loss: 1.5465 - accuracy: 0.3125

32/32 [==============================] - 0s 1ms/step - loss: 1.5452 - accuracy: 0.3190
Epoch 3/200
 1/32 [..............................] - ETA: 0s - loss: 1.4946 - accuracy: 0.3125

32/32 [==============================] - 0s 1ms/step - loss: 1.5174 - accuracy: 0.3410
Epoch 4/200
 1/32 [..............................] - ETA: 0s - loss: 1.3826 - accuracy: 0.4688

32/32 [==============================] - 0s 1ms/step - loss: 1.4920 - accuracy: 0.3510
Epoch 5/200
 1/32 [..............................] - ETA: 0s - loss: 1.4646 - accuracy: 0.3125

32/32 [==============================] - 0s 1ms/step - loss: 1.4619 - accuracy: 0.3890
Epoch 6/200
 1/32 [..............................] - ETA: 0s - loss: 1.3413 - accuracy: 0.3750

32/32 [==============================] - 0s 1ms/step - loss: 1.4320 - accuracy: 0.4100
Epoch 7/200
 1/32 [..............................] - ETA: 0s - loss: 1.1859 - accuracy: 0.5625

32/32 [==============================] - 0s 1ms/step - loss: 1.3899 - accuracy: 0.4480
Epoch 8/200
 1/32 [..............................] - ETA: 0s - loss: 1.3437 - accuracy: 0.4688

32/32 [==============================] - 0s 1ms/step - loss: 1.3438 - accuracy: 0.4640
Epoch 9/200
 1/32 [..............................] - ETA: 0s - loss: 1.2312 - accuracy: 0.5938

32/32 [==============================] - 0s 1ms/step - loss: 1.2818 - accuracy: 0.5280
Epoch 10/200
 1/32 [..............................] - ETA: 0s - loss: 1.2560 - accuracy: 0.6562

32/32 [==============================] - 0s 1ms/step - loss: 1.2153 - accuracy: 0.5350
Epoch 11/200
 1/32 [..............................] - ETA: 0s - loss: 1.0974 - accuracy: 0.5625

32/32 [==============================] - 0s 1ms/step - loss: 1.1251 - accuracy: 0.5900
Epoch 12/200
 1/32 [..............................] - ETA: 0s - loss: 1.0577 - accuracy: 0.6250

32/32 [==============================] - 0s 1ms/step - loss: 1.0428 - accuracy: 0.6130
Epoch 13/200
 1/32 [..............................] - ETA: 0s - loss: 0.9720 - accuracy: 0.6250

32/32 [==============================] - 0s 1ms/step - loss: 0.9585 - accuracy: 0.6580
Epoch 14/200
 1/32 [..............................] - ETA: 0s - loss: 0.9425 - accuracy: 0.6250

32/32 [==============================] - 0s 1ms/step - loss: 0.9079 - accuracy: 0.6550
Epoch 15/200
 1/32 [..............................] - ETA: 0s - loss: 0.8771 - accuracy: 0.6562

32/32 [==============================] - 0s 1ms/step - loss: 0.8380 - accuracy: 0.6750
Epoch 16/200
 1/32 [..............................] - ETA: 0s - loss: 0.8285 - accuracy: 0.6250

32/32 [==============================] - 0s 1ms/step - loss: 0.7937 - accuracy: 0.6800
Epoch 17/200
 1/32 [..............................] - ETA: 0s - loss: 0.7336 - accuracy: 0.8125

32/32 [==============================] - 0s 1ms/step - loss: 0.7459 - accuracy: 0.7150
Epoch 18/200
 1/32 [..............................] - ETA: 0s - loss: 0.8416 - accuracy: 0.6562

32/32 [==============================] - 0s 1ms/step - loss: 0.7190 - accuracy: 0.7190
Epoch 19/200
 1/32 [..............................] - ETA: 0s - loss: 0.7541 - accuracy: 0.7188

32/32 [==============================] - 0s 1ms/step - loss: 0.7206 - accuracy: 0.7060
Epoch 20/200
 1/32 [..............................] - ETA: 0s - loss: 0.6011 - accuracy: 0.8750

32/32 [==============================] - 0s 1ms/step - loss: 0.6473 - accuracy: 0.7500
Epoch 21/200
 1/32 [..............................] - ETA: 0s - loss: 0.6692 - accuracy: 0.7188

32/32 [==============================] - 0s 1ms/step - loss: 0.5996 - accuracy: 0.7870
Epoch 22/200
 1/32 [..............................] - ETA: 0s - loss: 0.5392 - accuracy: 0.7500

32/32 [==============================] - 0s 1ms/step - loss: 0.5724 - accuracy: 0.8010
Epoch 23/200
 1/32 [..............................] - ETA: 0s - loss: 0.4951 - accuracy: 0.8438

32/32 [==============================] - 0s 1ms/step - loss: 0.5255 - accuracy: 0.8120
Epoch 24/200
 1/32 [..............................] - ETA: 0s - loss: 0.5856 - accuracy: 0.8438

32/32 [==============================] - 0s 1ms/step - loss: 0.5087 - accuracy: 0.8310
Epoch 25/200
 1/32 [..............................] - ETA: 0s - loss: 0.4133 - accuracy: 0.8750

32/32 [==============================] - 0s 2ms/step - loss: 0.4790 - accuracy: 0.8510
Epoch 26/200
 1/32 [..............................] - ETA: 0s - loss: 0.4383 - accuracy: 0.8125

32/32 [==============================] - 0s 1ms/step - loss: 0.4571 - accuracy: 0.8580
Epoch 27/200
 1/32 [..............................] - ETA: 0s - loss: 0.4783 - accuracy: 0.8125

32/32 [==============================] - 0s 1ms/step - loss: 0.4264 - accuracy: 0.8680
Epoch 28/200
 1/32 [..............................] - ETA: 0s - loss: 0.4672 - accuracy: 0.8125

32/32 [==============================] - 0s 1ms/step - loss: 0.4522 - accuracy: 0.8380
Epoch 29/200
 1/32 [..............................] - ETA: 0s - loss: 0.4219 - accuracy: 0.8125

32/32 [==============================] - 0s 1ms/step - loss: 0.3907 - accuracy: 0.8770
Epoch 30/200
 1/32 [..............................] - ETA: 0s - loss: 0.4861 - accuracy: 0.8438

32/32 [==============================] - 0s 1ms/step - loss: 0.4066 - accuracy: 0.8590
Epoch 31/200
 1/32 [..............................] - ETA: 0s - loss: 0.4695 - accuracy: 0.8125

32/32 [==============================] - 0s 1ms/step - loss: 0.3701 - accuracy: 0.8830
Epoch 32/200
 1/32 [..............................] - ETA: 0s - loss: 0.2956 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.3718 - accuracy: 0.8720
Epoch 33/200
 1/32 [..............................] - ETA: 0s - loss: 0.4909 - accuracy: 0.7500

32/32 [==============================] - 0s 1ms/step - loss: 0.3758 - accuracy: 0.8750
Epoch 34/200
 1/32 [..............................] - ETA: 0s - loss: 0.2679 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.3492 - accuracy: 0.8780
Epoch 35/200
 1/32 [..............................] - ETA: 0s - loss: 0.3284 - accuracy: 0.8438

32/32 [==============================] - 0s 1ms/step - loss: 0.3346 - accuracy: 0.8840
Epoch 36/200
 1/32 [..............................] - ETA: 0s - loss: 0.2820 - accuracy: 0.8750

32/32 [==============================] - 0s 1ms/step - loss: 0.3223 - accuracy: 0.8840
Epoch 37/200
 1/32 [..............................] - ETA: 0s - loss: 0.2534 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.3335 - accuracy: 0.8860
Epoch 38/200
 1/32 [..............................] - ETA: 0s - loss: 0.3127 - accuracy: 0.8438

32/32 [==============================] - 0s 1ms/step - loss: 0.3112 - accuracy: 0.8810
Epoch 39/200
 1/32 [..............................] - ETA: 0s - loss: 0.2677 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.2923 - accuracy: 0.9050
Epoch 40/200
 1/32 [..............................] - ETA: 0s - loss: 0.3251 - accuracy: 0.8750

32/32 [==============================] - 0s 1ms/step - loss: 0.3052 - accuracy: 0.8920
Epoch 41/200
 1/32 [..............................] - ETA: 0s - loss: 0.4360 - accuracy: 0.8438

32/32 [==============================] - 0s 1ms/step - loss: 0.3075 - accuracy: 0.8850
Epoch 42/200
 1/32 [..............................] - ETA: 0s - loss: 0.2207 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.3070 - accuracy: 0.8840
Epoch 43/200
 1/32 [..............................] - ETA: 0s - loss: 0.3384 - accuracy: 0.8438

32/32 [==============================] - 0s 1ms/step - loss: 0.2685 - accuracy: 0.9130
Epoch 44/200
 1/32 [..............................] - ETA: 0s - loss: 0.2577 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.2756 - accuracy: 0.8990
Epoch 45/200
 1/32 [..............................] - ETA: 0s - loss: 0.2213 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.2490 - accuracy: 0.9180
Epoch 46/200
 1/32 [..............................] - ETA: 0s - loss: 0.2523 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.3159 - accuracy: 0.8910
Epoch 47/200
 1/32 [..............................] - ETA: 0s - loss: 0.1467 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.2657 - accuracy: 0.9120
Epoch 48/200
 1/32 [..............................] - ETA: 0s - loss: 0.2623 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.2852 - accuracy: 0.8950
Epoch 49/200
 1/32 [..............................] - ETA: 0s - loss: 0.3720 - accuracy: 0.8750

32/32 [==============================] - 0s 1ms/step - loss: 0.2261 - accuracy: 0.9320
Epoch 50/200
 1/32 [..............................] - ETA: 0s - loss: 0.3018 - accuracy: 0.8438

32/32 [==============================] - 0s 1ms/step - loss: 0.2328 - accuracy: 0.9300
Epoch 51/200
 1/32 [..............................] - ETA: 0s - loss: 0.2143 - accuracy: 0.8750

32/32 [==============================] - 0s 1ms/step - loss: 0.2479 - accuracy: 0.9080
Epoch 52/200
 1/32 [..............................] - ETA: 0s - loss: 0.1834 - accuracy: 0.8750

32/32 [==============================] - 0s 1ms/step - loss: 0.2354 - accuracy: 0.9150
Epoch 53/200
 1/32 [..............................] - ETA: 0s - loss: 0.2639 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.2228 - accuracy: 0.9260
Epoch 54/200
 1/32 [..............................] - ETA: 0s - loss: 0.2725 - accuracy: 0.8750

32/32 [==============================] - 0s 1ms/step - loss: 0.2347 - accuracy: 0.9170
Epoch 55/200
 1/32 [..............................] - ETA: 0s - loss: 0.1316 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.2112 - accuracy: 0.9310
Epoch 56/200
 1/32 [..............................] - ETA: 0s - loss: 0.1523 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.2239 - accuracy: 0.9260
Epoch 57/200
 1/32 [..............................] - ETA: 0s - loss: 0.2722 - accuracy: 0.8750

32/32 [==============================] - 0s 1ms/step - loss: 0.2292 - accuracy: 0.9090
Epoch 58/200
 1/32 [..............................] - ETA: 0s - loss: 0.2288 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1916 - accuracy: 0.9390
Epoch 59/200
 1/32 [..............................] - ETA: 0s - loss: 0.2552 - accuracy: 0.8750

32/32 [==============================] - 0s 1ms/step - loss: 0.2006 - accuracy: 0.9260
Epoch 60/200
 1/32 [..............................] - ETA: 0s - loss: 0.1279 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.2603 - accuracy: 0.9100
Epoch 61/200
 1/32 [..............................] - ETA: 0s - loss: 0.1990 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.2153 - accuracy: 0.9310
Epoch 62/200
 1/32 [..............................] - ETA: 0s - loss: 0.1652 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.2343 - accuracy: 0.9240
Epoch 63/200
 1/32 [..............................] - ETA: 0s - loss: 0.1309 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.2214 - accuracy: 0.9060
Epoch 64/200
 1/32 [..............................] - ETA: 0s - loss: 0.2633 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.2634 - accuracy: 0.9050
Epoch 65/200
 1/32 [..............................] - ETA: 0s - loss: 0.1433 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1938 - accuracy: 0.9340
Epoch 66/200
 1/32 [..............................] - ETA: 0s - loss: 0.2040 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.2025 - accuracy: 0.9280
Epoch 67/200
 1/32 [..............................] - ETA: 0s - loss: 0.1750 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.2178 - accuracy: 0.9190
Epoch 68/200
 1/32 [..............................] - ETA: 0s - loss: 0.2145 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1828 - accuracy: 0.9360
Epoch 69/200
 1/32 [..............................] - ETA: 0s - loss: 0.1577 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.2001 - accuracy: 0.9270
Epoch 70/200
 1/32 [..............................] - ETA: 0s - loss: 0.2162 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.2224 - accuracy: 0.9190
Epoch 71/200
 1/32 [..............................] - ETA: 0s - loss: 0.2430 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1935 - accuracy: 0.9340
Epoch 72/200
 1/32 [..............................] - ETA: 0s - loss: 0.2139 - accuracy: 0.8750

32/32 [==============================] - 0s 1ms/step - loss: 0.1974 - accuracy: 0.9320
Epoch 73/200
 1/32 [..............................] - ETA: 0s - loss: 0.1688 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.2055 - accuracy: 0.9170
Epoch 74/200
 1/32 [..............................] - ETA: 0s - loss: 0.1155 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1678 - accuracy: 0.9410
Epoch 75/200
 1/32 [..............................] - ETA: 0s - loss: 0.2205 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1508 - accuracy: 0.9520
Epoch 76/200
 1/32 [..............................] - ETA: 0s - loss: 0.2055 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.2018 - accuracy: 0.9200
Epoch 77/200
 1/32 [..............................] - ETA: 0s - loss: 0.1257 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1717 - accuracy: 0.9370
Epoch 78/200
 1/32 [..............................] - ETA: 0s - loss: 0.1470 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1642 - accuracy: 0.9400
Epoch 79/200
 1/32 [..............................] - ETA: 0s - loss: 0.1662 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.1675 - accuracy: 0.9430
Epoch 80/200
 1/32 [..............................] - ETA: 0s - loss: 0.1470 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.2130 - accuracy: 0.9170
Epoch 81/200
 1/32 [..............................] - ETA: 0s - loss: 0.1001 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.2087 - accuracy: 0.9280
Epoch 82/200
 1/32 [..............................] - ETA: 0s - loss: 0.1059 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1643 - accuracy: 0.9470
Epoch 83/200
 1/32 [..............................] - ETA: 0s - loss: 0.1259 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1544 - accuracy: 0.9520
Epoch 84/200
 1/32 [..............................] - ETA: 0s - loss: 0.1225 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1456 - accuracy: 0.9490
Epoch 85/200
 1/32 [..............................] - ETA: 0s - loss: 0.0694 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1404 - accuracy: 0.9550
Epoch 86/200
 1/32 [..............................] - ETA: 0s - loss: 0.1218 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.2621 - accuracy: 0.8990
Epoch 87/200
 1/32 [..............................] - ETA: 0s - loss: 0.1571 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1952 - accuracy: 0.9170
Epoch 88/200
 1/32 [..............................] - ETA: 0s - loss: 0.1031 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1672 - accuracy: 0.9410
Epoch 89/200
 1/32 [..............................] - ETA: 0s - loss: 0.1562 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1902 - accuracy: 0.9260
Epoch 90/200
 1/32 [..............................] - ETA: 0s - loss: 0.1231 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1417 - accuracy: 0.9510
Epoch 91/200
 1/32 [..............................] - ETA: 0s - loss: 0.1315 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.2429 - accuracy: 0.9070
Epoch 92/200
 1/32 [..............................] - ETA: 0s - loss: 0.0792 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1839 - accuracy: 0.9400
Epoch 93/200
 1/32 [..............................] - ETA: 0s - loss: 0.1181 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1681 - accuracy: 0.9330
Epoch 94/200
 1/32 [..............................] - ETA: 0s - loss: 0.2693 - accuracy: 0.8750

32/32 [==============================] - 0s 1ms/step - loss: 0.1858 - accuracy: 0.9240
Epoch 95/200
 1/32 [..............................] - ETA: 0s - loss: 0.1254 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.2415 - accuracy: 0.9150
Epoch 96/200
 1/32 [..............................] - ETA: 0s - loss: 0.1143 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1573 - accuracy: 0.9420
Epoch 97/200
 1/32 [..............................] - ETA: 0s - loss: 0.0915 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1628 - accuracy: 0.9390
Epoch 98/200
 1/32 [..............................] - ETA: 0s - loss: 0.2494 - accuracy: 0.8750

32/32 [==============================] - 0s 1ms/step - loss: 0.1239 - accuracy: 0.9680
Epoch 99/200
 1/32 [..............................] - ETA: 0s - loss: 0.1021 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1200 - accuracy: 0.9600
Epoch 100/200
 1/32 [..............................] - ETA: 0s - loss: 0.1037 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1414 - accuracy: 0.9520
Epoch 101/200
 1/32 [..............................] - ETA: 0s - loss: 0.2246 - accuracy: 0.8750

32/32 [==============================] - 0s 1ms/step - loss: 0.1670 - accuracy: 0.9350
Epoch 102/200
 1/32 [..............................] - ETA: 0s - loss: 0.1363 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1536 - accuracy: 0.9450
Epoch 103/200
 1/32 [..............................] - ETA: 0s - loss: 0.1435 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1399 - accuracy: 0.9560
Epoch 104/200
 1/32 [..............................] - ETA: 0s - loss: 0.2065 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1170 - accuracy: 0.9610
Epoch 105/200
 1/32 [..............................] - ETA: 0s - loss: 0.0961 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1269 - accuracy: 0.9580
Epoch 106/200
 1/32 [..............................] - ETA: 0s - loss: 0.0956 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1422 - accuracy: 0.9510
Epoch 107/200
 1/32 [..............................] - ETA: 0s - loss: 0.2009 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1248 - accuracy: 0.9630
Epoch 108/200
 1/32 [..............................] - ETA: 0s - loss: 0.1543 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.1561 - accuracy: 0.9440
Epoch 109/200
 1/32 [..............................] - ETA: 0s - loss: 0.1429 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1464 - accuracy: 0.9400
Epoch 110/200
 1/32 [..............................] - ETA: 0s - loss: 0.1598 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1466 - accuracy: 0.9460
Epoch 111/200
 1/32 [..............................] - ETA: 0s - loss: 0.1116 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1173 - accuracy: 0.9640
Epoch 112/200
 1/32 [..............................] - ETA: 0s - loss: 0.1100 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.1669 - accuracy: 0.9350
Epoch 113/200
 1/32 [..............................] - ETA: 0s - loss: 0.0447 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1255 - accuracy: 0.9540
Epoch 114/200
 1/32 [..............................] - ETA: 0s - loss: 0.0673 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1462 - accuracy: 0.9410
Epoch 115/200
 1/32 [..............................] - ETA: 0s - loss: 0.0671 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1345 - accuracy: 0.9460
Epoch 116/200
 1/32 [..............................] - ETA: 0s - loss: 0.0602 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1581 - accuracy: 0.9380
Epoch 117/200
 1/32 [..............................] - ETA: 0s - loss: 0.1138 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1396 - accuracy: 0.9470
Epoch 118/200
 1/32 [..............................] - ETA: 0s - loss: 0.1227 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1528 - accuracy: 0.9350
Epoch 119/200
 1/32 [..............................] - ETA: 0s - loss: 0.0726 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1636 - accuracy: 0.9360
Epoch 120/200
 1/32 [..............................] - ETA: 0s - loss: 0.0796 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1221 - accuracy: 0.9530
Epoch 121/200
 1/32 [..............................] - ETA: 0s - loss: 0.0657 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1497 - accuracy: 0.9410
Epoch 122/200
 1/32 [..............................] - ETA: 0s - loss: 0.1126 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1335 - accuracy: 0.9460
Epoch 123/200
 1/32 [..............................] - ETA: 0s - loss: 0.1004 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1227 - accuracy: 0.9590
Epoch 124/200
 1/32 [..............................] - ETA: 0s - loss: 0.1097 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1408 - accuracy: 0.9470
Epoch 125/200
 1/32 [..............................] - ETA: 0s - loss: 0.1027 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1186 - accuracy: 0.9550
Epoch 126/200
 1/32 [..............................] - ETA: 0s - loss: 0.1237 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.1056 - accuracy: 0.9630
Epoch 127/200
 1/32 [..............................] - ETA: 0s - loss: 0.1914 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.1210 - accuracy: 0.9620
Epoch 128/200
 1/32 [..............................] - ETA: 0s - loss: 0.0912 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1388 - accuracy: 0.9410
Epoch 129/200
 1/32 [..............................] - ETA: 0s - loss: 0.1325 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.1654 - accuracy: 0.9430
Epoch 130/200
 1/32 [..............................] - ETA: 0s - loss: 0.1788 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1357 - accuracy: 0.9540
Epoch 131/200
 1/32 [..............................] - ETA: 0s - loss: 0.0741 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1106 - accuracy: 0.9580
Epoch 132/200
 1/32 [..............................] - ETA: 0s - loss: 0.0885 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1579 - accuracy: 0.9460
Epoch 133/200
 1/32 [..............................] - ETA: 0s - loss: 0.1034 - accuracy: 0.9688

32/32 [==============================] - 0s 2ms/step - loss: 0.1844 - accuracy: 0.9230
Epoch 134/200
 1/32 [..............................] - ETA: 0s - loss: 0.1792 - accuracy: 0.9375

32/32 [==============================] - 0s 2ms/step - loss: 0.1403 - accuracy: 0.9510
Epoch 135/200
 1/32 [..............................] - ETA: 0s - loss: 0.0609 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1191 - accuracy: 0.9630
Epoch 136/200
 1/32 [..............................] - ETA: 0s - loss: 0.1638 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1134 - accuracy: 0.9630
Epoch 137/200
 1/32 [..............................] - ETA: 0s - loss: 0.0636 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1240 - accuracy: 0.9540
Epoch 138/200
 1/32 [..............................] - ETA: 0s - loss: 0.0310 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1444 - accuracy: 0.9430
Epoch 139/200
 1/32 [..............................] - ETA: 0s - loss: 0.1251 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.1323 - accuracy: 0.9530
Epoch 140/200
 1/32 [..............................] - ETA: 0s - loss: 0.1832 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1927 - accuracy: 0.9240
Epoch 141/200
 1/32 [..............................] - ETA: 0s - loss: 0.2322 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1456 - accuracy: 0.9430
Epoch 142/200
 1/32 [..............................] - ETA: 0s - loss: 0.1072 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1462 - accuracy: 0.9490
Epoch 143/200
 1/32 [..............................] - ETA: 0s - loss: 0.0476 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1172 - accuracy: 0.9530
Epoch 144/200
 1/32 [..............................] - ETA: 0s - loss: 0.2863 - accuracy: 0.8750

32/32 [==============================] - 0s 1ms/step - loss: 0.1995 - accuracy: 0.9330
Epoch 145/200
 1/32 [..............................] - ETA: 0s - loss: 0.1463 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1549 - accuracy: 0.9360
Epoch 146/200
 1/32 [..............................] - ETA: 0s - loss: 0.0602 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1748 - accuracy: 0.9230
Epoch 147/200
 1/32 [..............................] - ETA: 0s - loss: 0.1314 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1499 - accuracy: 0.9400
Epoch 148/200
 1/32 [..............................] - ETA: 0s - loss: 0.2407 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1382 - accuracy: 0.9520
Epoch 149/200
 1/32 [..............................] - ETA: 0s - loss: 0.1030 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1421 - accuracy: 0.9420
Epoch 150/200
 1/32 [..............................] - ETA: 0s - loss: 0.1233 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1561 - accuracy: 0.9470
Epoch 151/200
 1/32 [..............................] - ETA: 0s - loss: 0.3205 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1674 - accuracy: 0.9310
Epoch 152/200
 1/32 [..............................] - ETA: 0s - loss: 0.1560 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1503 - accuracy: 0.9420
Epoch 153/200
 1/32 [..............................] - ETA: 0s - loss: 0.1531 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1230 - accuracy: 0.9500
Epoch 154/200
 1/32 [..............................] - ETA: 0s - loss: 0.1181 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1372 - accuracy: 0.9460
Epoch 155/200
 1/32 [..............................] - ETA: 0s - loss: 0.0448 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1265 - accuracy: 0.9500
Epoch 156/200
 1/32 [..............................] - ETA: 0s - loss: 0.1280 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.1486 - accuracy: 0.9440
Epoch 157/200
 1/32 [..............................] - ETA: 0s - loss: 0.0524 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1089 - accuracy: 0.9630
Epoch 158/200
 1/32 [..............................] - ETA: 0s - loss: 0.0851 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1220 - accuracy: 0.9590
Epoch 159/200
 1/32 [..............................] - ETA: 0s - loss: 0.1657 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.1748 - accuracy: 0.9330
Epoch 160/200
 1/32 [..............................] - ETA: 0s - loss: 0.4153 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1610 - accuracy: 0.9380
Epoch 161/200
 1/32 [..............................] - ETA: 0s - loss: 0.0756 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1033 - accuracy: 0.9690
Epoch 162/200
 1/32 [..............................] - ETA: 0s - loss: 0.1376 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.0855 - accuracy: 0.9700
Epoch 163/200
 1/32 [..............................] - ETA: 0s - loss: 0.0690 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1578 - accuracy: 0.9460
Epoch 164/200
 1/32 [..............................] - ETA: 0s - loss: 0.0887 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.1199 - accuracy: 0.9530
Epoch 165/200
 1/32 [..............................] - ETA: 0s - loss: 0.0532 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.0979 - accuracy: 0.9690
Epoch 166/200
 1/32 [..............................] - ETA: 0s - loss: 0.0867 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.0949 - accuracy: 0.9600
Epoch 167/200
 1/32 [..............................] - ETA: 0s - loss: 0.0863 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.0928 - accuracy: 0.9700
Epoch 168/200
 1/32 [..............................] - ETA: 0s - loss: 0.1652 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.0878 - accuracy: 0.9720
Epoch 169/200
 1/32 [..............................] - ETA: 0s - loss: 0.1203 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1271 - accuracy: 0.9520
Epoch 170/200
 1/32 [..............................] - ETA: 0s - loss: 0.0512 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1507 - accuracy: 0.9470
Epoch 171/200
 1/32 [..............................] - ETA: 0s - loss: 0.0910 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1480 - accuracy: 0.9390
Epoch 172/200
 1/32 [..............................] - ETA: 0s - loss: 0.1934 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.2025 - accuracy: 0.9230
Epoch 173/200
 1/32 [..............................] - ETA: 0s - loss: 0.2162 - accuracy: 0.9062

32/32 [==============================] - 0s 1ms/step - loss: 0.1429 - accuracy: 0.9450
Epoch 174/200
 1/32 [..............................] - ETA: 0s - loss: 0.0563 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1093 - accuracy: 0.9520
Epoch 175/200
 1/32 [..............................] - ETA: 0s - loss: 0.1889 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1451 - accuracy: 0.9400
Epoch 176/200
 1/32 [..............................] - ETA: 0s - loss: 0.1149 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.0833 - accuracy: 0.9740
Epoch 177/200
 1/32 [..............................] - ETA: 0s - loss: 0.0581 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.0689 - accuracy: 0.9810
Epoch 178/200
 1/32 [..............................] - ETA: 0s - loss: 0.0451 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1107 - accuracy: 0.9590
Epoch 179/200
 1/32 [..............................] - ETA: 0s - loss: 0.0950 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.0839 - accuracy: 0.9680
Epoch 180/200
 1/32 [..............................] - ETA: 0s - loss: 0.0617 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1006 - accuracy: 0.9740
Epoch 181/200
 1/32 [..............................] - ETA: 0s - loss: 0.1413 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.0826 - accuracy: 0.9720
Epoch 182/200
 1/32 [..............................] - ETA: 0s - loss: 0.0774 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.0736 - accuracy: 0.9810
Epoch 183/200
 1/32 [..............................] - ETA: 0s - loss: 0.1032 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.1809 - accuracy: 0.9380
Epoch 184/200
 1/32 [..............................] - ETA: 0s - loss: 0.1021 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1128 - accuracy: 0.9550
Epoch 185/200
 1/32 [..............................] - ETA: 0s - loss: 0.0675 - accuracy: 1.0000

32/32 [==============================] - 0s 2ms/step - loss: 0.1119 - accuracy: 0.9580
Epoch 186/200
 1/32 [..............................] - ETA: 0s - loss: 0.1572 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.0994 - accuracy: 0.9610
Epoch 187/200
 1/32 [..............................] - ETA: 0s - loss: 0.0498 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.0963 - accuracy: 0.9640
Epoch 188/200
 1/32 [..............................] - ETA: 0s - loss: 0.0875 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.1281 - accuracy: 0.9490
Epoch 189/200
 1/32 [..............................] - ETA: 0s - loss: 0.1458 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.1041 - accuracy: 0.9570
Epoch 190/200
 1/32 [..............................] - ETA: 0s - loss: 0.1360 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.1478 - accuracy: 0.9480
Epoch 191/200
 1/32 [..............................] - ETA: 0s - loss: 0.1205 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1145 - accuracy: 0.9550
Epoch 192/200
 1/32 [..............................] - ETA: 0s - loss: 0.0423 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.0937 - accuracy: 0.9630
Epoch 193/200
 1/32 [..............................] - ETA: 0s - loss: 0.0552 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1875 - accuracy: 0.9290
Epoch 194/200
 1/32 [..............................] - ETA: 0s - loss: 0.1562 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1639 - accuracy: 0.9450
Epoch 195/200
 1/32 [..............................] - ETA: 0s - loss: 0.0784 - accuracy: 0.9375

32/32 [==============================] - 0s 1ms/step - loss: 0.1093 - accuracy: 0.9570
Epoch 196/200
 1/32 [..............................] - ETA: 0s - loss: 0.0736 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.0810 - accuracy: 0.9690
Epoch 197/200
 1/32 [..............................] - ETA: 0s - loss: 0.0470 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.0879 - accuracy: 0.9680
Epoch 198/200
 1/32 [..............................] - ETA: 0s - loss: 0.0493 - accuracy: 1.0000

32/32 [==============================] - 0s 1ms/step - loss: 0.1111 - accuracy: 0.9640
Epoch 199/200
 1/32 [..............................] - ETA: 0s - loss: 0.0668 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.1239 - accuracy: 0.9540
Epoch 200/200
 1/32 [..............................] - ETA: 0s - loss: 0.0621 - accuracy: 0.9688

32/32 [==============================] - 0s 1ms/step - loss: 0.2249 - accuracy: 0.9190

In diesem Beispiel ist X die Designmatrix, y der Ergebnisvektor, und das Argument epochs gibt an, wie viele Epochen der Optimierer durchlaufen soll. Keras gibt den Fortschritt beim Optimieren an, es könnte so aussehen

Epoch 1/200
25/25 [==============================] - 0s 2ms/step - loss: 1.5984 - accuracy: 0.2438
Epoch 2/200
25/25 [==============================] - 0s 2ms/step - loss: 1.5709 - accuracy: 0.2763
Epoch 3/200
25/25 [==============================] - 0s 3ms/step - loss: 1.5550 - accuracy: 0.3013

Hierbei kann man die aktuelle Epoche, den Batch (für stochastischen Gradientenabstieg) und die aktuelle Genauigkeit der Trainingsdaten sehen. In diesem Beispiel werden alle Epochen bis zum Abschluss ausgeführt, daher sehen wir 32/32 für Batches, aber normalerweise kann man die Batch-Nummer sehen, die sich während des Trainings fortschreitet. Dieses Beispiel funktioniert sehr schnell, Keras meldet 2 ms pro Schritt (Batch) und die Gesamtzeit für die Epoche ist zu gering, um gemeldet zu werden. Aber eine einzelne Epoche kann bei komplexeren Modellen und mehr Daten viele Minuten dauern.

Achtung: Batchqualität vs. Modellqualität

Die Modellqualität (hier Genauigkeit) wird für eine einzelne Batch berechnet und gibt nur eine grobe Richtlinie für die tatsächliche Modellgenauigkeit, auch auf Trainingsdaten. Nehmen Sie diese Genauigkeitsmessung nicht zu ernst!

Achtung: Modelle fertig trainieren

Keras ermöglicht es Ihnen, Vorhersagen mit einem Modell zu treffen, das nicht angepasst ist (im Gegensatz zu scikit-learn, wo das einen Fehler verursacht). Die Ergebnisse werden bestenfalls mittelmäßig aussehen.

Vorhersagen und Plotten#

Wenn die Anpassung abgeschlossen ist, können wir das Modell für Vorhersagen verwenden. Die Vorhersage funktioniert ähnlich wie in sklearn, nur dass die predict-Methode die Wahrscheinlichkeit vorhersagt, nicht die Kategorie (analog zu sklearn’s predict_proba).

phat = model.predict(X_test)
1/8 [==>...........................] - ETA: 0s

8/8 [==============================] - 0s 837us/step

In diesem Beispiel handelt es sich um eine Matrix mit 5 Spalten, wobei jede Spalte die Wahrscheinlichkeit darstellt, dass der Datenpunkt zur entsprechenden Kategorie gehört. Beispielsweise könnten Zeilen von phat so aussehen:

phat[:5]
array([[2.1881836e-36, 1.3487735e-15, 8.6300272e-01, 1.3686040e-01,
        1.3694415e-04],
       [1.2819722e-03, 9.9864906e-01, 6.8881644e-05, 2.0207268e-19,
        0.0000000e+00],
       [9.9997580e-01, 2.4194474e-05, 3.5842049e-13, 6.9878675e-28,
        0.0000000e+00],
       [9.9912304e-01, 8.7702699e-04, 2.5507032e-11, 6.7867296e-25,
        0.0000000e+00],
       [9.9996412e-01, 3.5825851e-05, 5.8725938e-15, 1.4685880e-32,
        0.0000000e+00]], dtype=float32)

Wir sehen, dass für jedes Test-Fall eine Wahrscheinlichkeit für jede Kategorie angegeben ist. Als nächstes wollen wir mit np.argmax(phat, axis=-1) die Spalte (Kategorie) finden, mit der höchsten Wahrscheinlichkeit. Es findet einfach die Position der größten Elemente im Array entlang der letzten Achse (axis=-1), d.h. Spalten. Für jede Zeile finden wir also die entsprechende Spaltennummer. Beachten Sie, dass np.argmax die Spalten ab 0 zählt, nicht ab 1:

yhat = np.argmax(phat, axis=-1)
yhat[:5]
array([2, 1, 0, 0, 0])

Endlich können wir die Verwirrungsmatrix mit pd.crosstab berechnen und die Genauigkeit berechnen:

from sklearn.metrics import confusion_matrix

print("confusion matrix:\n", confusion_matrix(y_test, yhat))
print("Accuracy (on training data):", np.mean(y_test == yhat))
confusion matrix:
 [[52  2  0  0  0]
 [ 0 33  1  0  0]
 [ 0  4 65  1  0]
 [ 0  0  2 36  0]
 [ 0  0  0  2 52]]
Accuracy (on training data): 0.952

In diesem Beispiel machen wir Vorhersagen auf Trainingsdaten, aber wir können natürlich auch einen anderen Datensatz für Vorhersagen auswählen. Da der vorhergesagte Wert eine Wahrscheinlichkeitsmatrix mit 5 Spalten sein wird, berechnen wir yhat als die Spaltennummer, die die größte Wahrscheinlichkeit für jede Zeile enthält.

Wie man sehen kann, ist die Verwirrungsmatrix fast ausschließlich auf der Hauptdiagonalen besetzt, und die Genauigkeit ist hoch.

Schließlich müssen wir, wenn wir ein ähnliches Diagramm wie oben erstellen möchten, die DBPlot-Funktion anpassen, um zu berücksichtigen, dass Keras-Modelle nur Wahrscheinlichkeiten vorhersagen.

def DBPlot(m, X, y, nGrid = 300):
    x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx1, xx2 = np.meshgrid(np.linspace(x1_min, x1_max, nGrid), 
                           np.linspace(x2_min, x2_max, nGrid))
    XX = np.column_stack((xx1.ravel(), xx2.ravel()))
    ## predict probability
    phat = m.predict(XX, verbose=0)
    ## find the column that corresponds to the maximum probability
    hatyy = np.argmax(phat, axis=-1).reshape(xx1.shape)
    fig = px.imshow(hatyy, width=600, height=600)
    fig.add_scatter(x=X[:,0]/(x1_max-x1_min)*nGrid+nGrid/2, y=X[:,1]/(x2_max-x2_min)*nGrid+nGrid/2, mode="markers", 
                    marker=dict(color=[mcolors[i] for i in y]), marker_line=dict(width=.3, color="black"))
    fig.update_coloraxes(showscale=False)
    fig.update_layout(showlegend=False)
    fig.show()
DBPlot(model, X_test, y_test)

Noch einmal, die Funktion ist fast identisch mit der sklearn Version, außer der Zeile, die np.argmax(phat, axis=-1) enthält, die die vorhergesagten Wahrscheinlichkeiten in Kategorien umwandelt.