Implementierung mit Keras
Neuronale Netze werden von vielen verschiedenen Bibliotheken implementiert. Darunter fallen Torch, Caffe, Theano, Tensorflow sowie MxNet. Die meisten Bibliotheken sind in C oder C++ geschrieben und bieten Scriptsprachen wie Python oder Lua an, um Modelle von neuronalen Netzen zu beschreiben. Daher entspricht ein Modell der Quellcode Repräsentation eines neuronalen Netzes. Neben den genannten Bibliotheken existiert Keras. Keras fasst die Modelle von Bibliotheken wie Tensorflow oder Theano zusammen und stellt eine einheitliche Schnittstelle zur Modelldefinition bereit. So lassen sich einzelne Modelle mit minimalen Änderungen auf unterschiedliche Bibliotheken portieren. In dieser Arbeit wird Python mit Keras zur Implementierung neuronaler Netze verwendet.
Modell Definition
Keras teilt die Implementierung von neuronalen Netzen in mehrere Objekte auf. Dabei werden einzelne Layer als Objektinstanzen zu einem Modell hinzugefügt. Keras gibt zwei Modelle vor.
- Das sequentielle Modell bildet alle Layer in einer Sequenz ab. Dazu wird das Modell instantiiert und die einzelnen Layer der Reihe nach dem Modell hinzugefügt. Die Reihenfolge entscheidet welche Layer ineinander übergehen.
- Das funktionale Modell verknüpft einzelne Layer direkt. Daher muss vor einer Layer Definition das vorherige Layer bekannt und instantiiert sein. Das vorausgegangene Layer wird bei der Instanziierung des aktuellen Layers übergeben. So lassen sich komplexere Abhängigkeiten ausdrücken.
Sind alle Layer dem Modell hinzugefügt wird es über die compile
Methode für den Trainingsprozess vorbereitet.
Im folgenden Quellcodebeispiel sind die beiden Modelldefinitionen für ein Netz mit einem Fully Connected Layer aufgezeigt, welches 32 Neuronen hat.
Sequentielles Modell
from keras.models import Sequential
from keras.layers import Dense, Activation
#Define Model
model = Sequential()
model.add(Dense(32, input_dim=100))
model.add(Activation('relu'))
#Compile Model
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
Funktionales Modell
from keras.models import Model
from keras.layers import Input, Dense, Activation
#Define Model
input = Input(shape=(100,))
x1 = Dense(32)(inputs)
x2 = Activation('relu')(x1)
model = Model(inputs=input, outputs=x2)
#Compile Model
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
Die Methode compile
bietet verschiedene Parameter an, wie den genutzten Optimizer, die Kostenfunktion sowie die berechneten Metriken. Im Beispiel wird Adam als Optimizer verwendet. Die Kostenfunktion wird über die categorical_crosstropy
kalkuliert. Die Metriken dienen der Validierung des Modells. Hier werden unterschiedliche Optionen mitgegeben um neben dem Fortschritt die Abweichung oder die Genauigkeit anzuzeigen.
Ausgabe der Modellstruktur
Neben den genannten Funktionen bietet Keras die Möglichkeit einzelne Modelle über die Konsole oder als Bild darzustellen. Mit dem Aufruf der Methode summary()
werden die Schichten des zugehörigen Modells auf der Konsole angezeigt. Um den Aufbau eines Modells als Darstellung zu speichern reicht der Aufruf der Methode plot_model
aus.
# Console
model.summary()
# Image
from keras.utils import plot_model
plot_model(model, to_file='model.png')
Training
Ist die Definition eines Modells abgeschlossen wird es mit der Methode fit
trainiert. Dazu übergibt man die Rohdaten als x_train
sowie die Label als y_train
. Mit dem Parameter epochs bestimmt man die Anzahl der Durchläufe durch die Trainingsdaten. Der Parameter batch_size
eignet sich für große Datenmengen und definiert auf wie vielen Datensätzen gleichzeitig trainiert wird.
model.fit(x_train, y_train, epochs=5, batch_size=32)
Laden und Speichern
Um das neuronale Netz persistent zu speichern unterscheidet Keras zwischen dem Modell und den Gewichtungen der Neuronen des Modells. Das Modell wird im Json Format abgespeichert. Die Gewichtungen werden in einer H5 Datei als binärer Baum gesichert. Folgender Aufruf zeigt das Speichern sowie das Laden eines Models mit Gewichtungen in Keras.
from keras.models import model_from_json
#save model
model_json = model.to_json()
with open("model.json", "w") as file:
file.write(model_json)
model.save_weights("model.h5")
#load model
file = open("model.json", "r")
model_json = file.read()
file.close()
model = model_from_json(model_json)
model.load_weights("model.h5")
Evaluation
Das Evaluieren der Daten kann ebenfalls in die Trainingsphase verschoben werden. Dazu wird über den Parameter validation_data
ein Testdatensatz aus Rohdaten und Labeln übergeben, gegen die am Ende jeder Epoche getestet wird. Sind keine Testdatensätze vorhanden, kann der Trainingsdatensatz über den Parameter validation_split
prozentual aufgeteilt werden. Dazu wird ein Teil der Daten zum Testen und der restliche zum Trainieren verwendet. Die Trainingsdaten und Testdaten wechseln jede Runde, so wird auf allen Daten trainiert und getestet. Dieses Verfahren wird als Kreuzvalidierungsverfahren bezeichnet und verhindert, dass sich das Netz auf einzelne Trainingsdaten oder Testdaten spezialisiert. Der anschließende Quellcode veranschaulicht den Aufruf beider Methoden.
# using testdataset
model.fit(x_train, y_train, epochs=5, batch_size=32, validation_data(test_x, test_y))
# spliting the trainingsdata
model.fit(x_train, y_train, epochs=5, batch_size=32, validation_split=0.2)
Entschließt man sich die Evaluierung des Netzes nicht in die Testphase zu verschieben, bietet jedes Modell die Methode evaluate
an um die Genauigkeit auf Testdaten zu überprüfen. Dazu werden Rohdaten (x_test)
und Label (y_test)
mitgegeben. Die Methode evaluate
ist im Folgenden dargestellt. Als Ergebnis wird die durchschnittliche Kostenfunktion zurückgegeben. Über die compile
Methode des Modells lassen sich weitere Metriken konfigurieren.
loss_and_metrics = model.evaluate(x_test, y_test1)
>> loss_and_metrics
[loss result, other options defined by the model over metrics]
Für eine detaillierte Analyse der Daten fehlt die Genauigkeit der einzelnen Label Klassen. Erst durch diese lassen sich Fehler einer Label Klasse zuordnen. Um die Genauigkeit der einzelnen Label Klassen herauszufinden bietet sich das Python Modul sklearn an. Folgendes Codebeispiel zeigt die Berechnung der Konfusionsmatrix und der anschließenden Auswertung der Label Klassen aufgrund den echten Labeln (y) und den berechneten Labeln (ȳ). Dazu wird der Anteil an übereinstimmenden berechneten Labeln errechnet.
from sklearn.metrics import confusion_matrix
mat = confusion_matrix(y, ȳ, labels=labels)
ac = mat.diagonal()/mat.sum(axis=1)
print(ac)
Prediction
Erreicht das Modell eine hohe Genauigkeit steht dem Einsatz in einer unkontrollierten Umgebung nichts im Weg. Dazu wird die predict
Methode des Modells mit den Rohdaten einer unkontrollierten Umgebung aufgerufen. Das Codebeispiel zeigt den Aufruf der Methode.
y = model.predict(raw_data)