Neuronale Netzwerke

Dr.-Ing. Erhard Henkes, 02.03.2021

Der praktische Einstieg


Was braucht man eigentlich, um in die Themengebiete "Deep Learning", "Neuronale Netzwerke" und "Artificial Intelligence" praktisch einzusteigen?

Die Antworten sind sicher vielfältig. Man kann sich das Leben jedoch leicht machen:
Wir nehmen hier Python als Programmiersprache und die Bibliothek Keras, die auf dem Backend Tensorflow aufsetzt, und legen einfach los. Was brauchen wir konkret?


Mein Vorschlag ist, Anaconda 3 und Spyder 4.2.1 zu installieren.

Technischer Hinweis: Mit Spyder 4.2.2 gab es bei mir Kompatibiltätsprobleme mit dem Python Interpreter. Man kann diese lösen, indem man unten in der Statusleiste bei „conda: base (Python …)“ mittels Mausklick umstellt auf Python 3.8.5. Dies gelingt z.B. mit „Use the following Python interpreter: C:\ProgramData\Anaconda3\python.exe“ (kann auch in einem anderen Unterverzeichnis liegen, wenn nur für einen User installiert). Das stellte sich allerdings bei mir wieder zurück. Daher empfehle ich Spyder 4.2.1.

Sollten die Probleme, warum auch immer, nicht behebbar sein, dann steigt man am besten auf Pycharme um. Das stellt sich automatisch auf Python 3.80 ein. Es ist etwas gewöhnungsbedürftig, aber es funktioniert.

Bei Anaconda gibt es ein "Anaconda Prompt". Dort gibt man per Kommandozeile ein: python

Bei mir erscheint die
Meldung:
Python 3.8.5 (default, Sep  3 2020, 21:29:08) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32
Type "help", "copyright", "credits" or "license" for more information.

Mit help() als Eingabe erhalte ich:
If this is your first time using Python, you should definitely check out the tutorial on the Internet at https://docs.python.org/3.8/tutorial/.
...

Nun habe wir Python am Start, und mit Spyder haben wir eine Kombination aus Editor, Interpreter und Aus-/Eingabekonsole an der Hand.
Nun können wir loslegen. Halt! Erst brauchen wir noch Keras, unsere Bibliothek, mit der wir NN bauen, trainieren und testen wollen.
Dazu verwenden wir den Anaconda Prompt und geben dort ein:
pip install keras
Da ich Keras bereits installiert habe, erscheint bei mir:
Requirement already satisfied: keras in c:\programdata\anaconda3\lib\site-packages (2.4.3)
Requirement already satisfied: scipy>=0.14 in c:\programdata\anaconda3\lib\site-packages (from keras) (1.6.1)
Requirement already satisfied: numpy>=1.9.1 in c:\programdata\anaconda3\lib\site-packages (from keras) (1.19.2)
Requirement already satisfied: h5py in c:\programdata\anaconda3\lib\site-packages (from keras) (2.10.0)
Requirement already satisfied: pyyaml in c:\programdata\anaconda3\lib\site-packages (from keras) (5.4.1)
Requirement already satisfied: six in c:\programdata\anaconda3\lib\site-packages (from h5py->keras) (1.15.0)

Öffnet nun Spyder und geht in das Menü unter Tools - PYTHONPATH Manager.
In dem sich öffnenden Fenster könnt ihr mit "
+ Add path" neue Pfade anlegen, damit die entsprechenden Module gefunden werden. 
Bei mir sind das z.B. (für alle Benutzer installiert):
C:\ProgramData\Anaconda3\Lib\site-packages\tensorflow\keras
C:\ProgramData\Anaconda3\Lib\site-packages\tensorflow
C:\ProgramData\Anaconda3\Lib\site-packages
C:\ProgramData\Anaconda3\Lib
C:\ProgramData\Anaconda3

Habt ihr es nur für euch selbst installiert, dann sucht unter Benutzer C:\Users\euerName\... (ansonsten ist es C:\ProgramData\...) nach Anaconda3 und seinen Unterordnern. Ohne diese Pfade wird der Interpreter die entsprechenden Module nicht finden und überschüttet euch mit den beliebten Error-Meldungen.

Ich gehe davon aus, dass ihr euch mit dem Programmieren und der Python-Syntax vertraut gemacht habt. Ihr wisst, wo ihr nachschauen könnt: https://docs.python.org/3.8/tutorial/
Ansonsten habt ihr wenig Chancen hier vernünftig mitzuhalten. Wer bereits C/C++ beherrscht, der kennt zumindest die Kontroll- und Klassen-Strukturen. Die Python Syntax ist gewöhnungsbedürftig, jedoch fällt sie vielen leichter als zum Beispiel C++.

KI wird durch Keras nun eben von Python beherrscht. Das sollte man akzeptieren und nicht weiter murren. Auf geht's! ;-)

Wir geben als Test folgende Codezeilen, die Bibiotheken in unser Programm importieren, in den Spyder Editor ein:


import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Activation, Dense
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.metrics import categorical_crossentropy

Nun einfach F5 drücken oder oben den grünen Pfeil.
Dies steht für "Run", also ab geht die Post!
Wenn ihr in der Konsole nun nicht mit Errors gequält werdet, dann kann es losgehen.

Ihr habt sicher schon gehört, dass NN gerne eure GPU zum Kochen bringen. Die neuen NNUE verzichten darauf und begnügen sich mit eurer CPU.
Bei mir erscheint u.a. z.B. die Meldung:
Could not load dynamic library 'cudart64_110.dll etc., allerdings nur als Warnung/Hinweis. Wer unbedingt seine GPU mit CUDA verwenden möchte, kann sich um die korrekte CUDA-Installation kümmern.
Hierbei muss die CUDA-Version zur Tensorflow Version passen. Wie erhält man seine Tensorflow Version?
Anaconda Prompt ist hier die richtige Adresse. Wir geben ein:
pip show tensorflow und erhalten als Antwort viel mehr, als wir eigentlich wissen wollen:
Name: tensorflow
Version: 2.4.1
Summary: TensorFlow is an open source machine learning framework for everyone.
Home-page: https://www.tensorflow.org/
Author: Google Inc.
Author-email: packages@tensorflow.org
License: Apache 2.0
Location: c:\programdata\anaconda3\lib\site-packages
Requires: grpcio, astunparse, typing-extensions, tensorflow-estimator, opt-einsum, absl-py, h5py, six, termcolor, google-pasta, keras-preprocessing, wheel, wrapt, gast, flatbuffers, protobuf, tensorboard, numpy
Required-by:

Nun brauchen wir noch die Info, welches CUDA (von nVidia) zu dieser Version passt. Hier gibt es eine nette Übersicht: https://www.tensorflow.org/install/source#gpu
Zur Installation, die für uns nicht notwendig ist, verweise ich auf hilfreiche Seiten, z.B. hier: https://shawnhymel.com/1961/how-to-install-tensorflow-with-gpu-support-on-windows/

Dieses Tensorflow ist unser Backend, wobei Keras auch andere Backends unterstützt. Hier erfährt man Details: https://de.wikipedia.org/wiki/TensorFlow
Wir setzen es einfach ein und freuen uns über unsere bequeme High-Level-Ebene Keras.
Damit haben wir die Grundlagen gelegt für unsere ersten NN Experimente.

Wir fangen an! Zunächst brauchen wir Daten. Ein beliebtes Beispiel zum Testen ist folgende Datenbank mit handgeschriebenen Zahlen: http://yann.lecun.com/exdb/mnist/
MNIST ist dabei ein Teil der Datenbank NIST. Hier erfahrt ihr mehr: https://www.nist.gov/srd/nist-special-database-19
NIST steht übrigens für "National Institute of Standards and Technology".

OK, unsere Daten haben wir also schon mal griffbereit.

Bitte nun folgenden Code eingeben in den Editor von Spyder:

import tensorflow as tf

# http://yann.lecun.com/exdb/mnist/  <-- Handgeschriebene Zahlen
mnist = tf.keras.datasets.mnist
 
# Aufteilen in Sets für Training und Test
(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
 
# NN zur Bilderkennung einrichten
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(512, activation=tf.nn.relu),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])

# NN Aufbau zeigen
model.summary()

# Compilieren
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

# Training
print("\nTraining")
model.fit(x_train, y_train, epochs=2)

# Test
print("\nTest")
model.evaluate(x_test, y_test)

Bei mir erhalte ich (beim ersten Durchgang) folgende Ausgabe in der Konsole:

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #  
=================================================================
flatten (Flatten)            (None, 784)               0        
_________________________________________________________________
dense (Dense)                (None, 512)               401920   
_________________________________________________________________
dropout (Dropout)            (None, 512)               0        
_________________________________________________________________
dense_1 (Dense)              (None, 10)                5130     
=================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0

_________________________________________________________________

Training
Epoch 1/2
1875/1875 [==============================] - 3s 2ms/step - loss: 0.3635 - accuracy: 0.8934
Epoch 2/2
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0962 - accuracy: 0.9706

Test
313/313 [==============================] - 0s 754us/step - loss: 0.0876 - accuracy: 0.9737


Das war es schon! Das erste "Neural Network" (NN) hat gearbeitet.

Die Handschrifterkennung soll besser werden? 97% ist nicht genug?
Na dann lassen wir unser NN härter trainieren. Wir erhöhen von
epochs=2 auf epochs=20.

Was passiert nun? Es dauert länger, und es hilft. Die Genauigkeit der Erkennung steigt in den letzten Trainings-Durchläufen auf über 99,5%.

Mit diesem einfachen, nur wenige Zeile umfassenden Programm zeigen wir mittels "Keras" die wesentlichen Schritte:
1) Daten bereitstellen
2) Neuronales Netzwerk einrichten

3) Trainieren
4) Testen (=Anwenden)

Hoffentlich klappt es bei euch. Bei mir gab es auf MS Windows 10 zunächst Errors mit Spyder 4.x und dem fehlenden PYTHONPATH. Das haben wir genau besprochen (s.o.).

Es finden sich nun viele neue Begriffe im Programmcode. Für die wissbegierigen und experimentierfreudigen Coder sei folgendes Kapitel eines wirklich guten Tutorials empfohlen:
https://www.tutorialspoint.com/keras/keras_layers.htm

Zunächst sollte man wissen, dass in Keras der Begriff "model" für unser NN verwendet wird. Unser NN besteht aus mehreren Schichten ("Layers").
Innerhalb dieser Schichten finden sich Neuronen, sprich unsere digitalen "Nervenzellen", die in definierter Weise miteinander verflochten werden und somit ein neuronales Netzwerk (engl.: neural network) ergeben.

Vorne am Input Layer gehen unsere Eingangsdaten rein und hinten am Output Layer kommen unsere Ergebnisse heraus. Dazwischen werden Signale über die Neuronen unserer Hidden Layers gesendet.
Das Training sorgt dafür, dass die Ergebnisse immer besser mit der Erwartung übereinstimmen, z.B. bei Rechenaufgaben, bzw. dass bei bestimmten Eingangsdaten ein idealer Output als Handlungsanweisung erfolgt, z.B. die beste Aktion in einer bestimmten Situation. Ich denke hier als engagierter Schachspieler an Schach Engines, die inzwischen erfolgreich neuronale Netzwerke verwenden, um von einer Position (Input) zu einem Zug (Output) zu gelangen.

Unser "model" (das ist unser NN) ist "Sequential". Das bedeutet, wir verwenden eine lineare Komposition von Keras Layers. Diese NN sind einfach und daher für den Einstieg empfehlenswert.

Wir können den Code (ohne Kommentare) übrigens auch wie folgt schreiben:

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Flatten, Activation, Dense, Dropout

mnist = tf.keras.datasets.mnist
 
(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
 
model = Sequential()
model.add(Flatten(input_shape=(28, 28)))
model.add(Dense(512, activation=tf.nn.relu))
model.add(Dropout(0.2))
model.add(Dense(10, activation=tf.nn.softmax))

model.summary()

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

print("\nTraining")
model.fit(x_train, y_train, epochs=20)

print("\nTest")
model.evaluate(x_test, y_test)

Vielleicht gefällt dieser Stil besser. Das Ergebnis ist gleich. Man muss hier mehr "importieren", damit man es im Code ohne vorgestellte Module verwenden kann.
Die add-Methode (eine Methode ist eine public Funktion einer Klasse) zeigt deutlicher den Aufbauprozess des Netzwerks, bei dem wir Schicht hinter Schicht anfügen.

Was bedeuten die Layers (Schichten) mit den Bezeichnungen
Flatten - Dense - Dropout - Dense ?

"Flatten" wird im Eingangsbereich verwendet, um mehrdimensionale in eindimensionale Arrays zu wandeln.
Immer einer nach dem anderen, nicht drängeln oder gar zwei auf einmal, wie eine Drehtür für nur eine Person. Aus dem Format 28, 28 wird dann eben 56.

"Dense" bedeutet, dass
alle Neuronen miteinander vebunden sind. Es gibt hier zahlreiche Parameter (siehe Link).

"Dropout" schaltet beim Training eine gewisse Anzahl Neuronen (bei uns rate = 0.2 = 20%) aus, um die Gefahr der Überanpassung (overfitting) zu vermeiden.
Damit bekämpft man das Rauschen, sprich schlechte Daten. Dies sind die Parameter:
Dropout(rate, noise_shape = None, seed = None)

Man sollte sich als Einsteiger in NN theoretisch und praktisch behutsam einarbeiten und begleitend die vorhandenen Erklärungen in Tutorials lesen. Hinter der sanften Oberfläche von Keras stecken unzählige mathematische Monster.

model.summary() zeigt die Architektur unseres NN im Überblick.

Nun zum Compiler: Welchen "Loss" soll man wählen? Bekannt ist z.B. "
mean_squared_error", die bekannte "mittlere quadratische Abweichung". Für unseren Fall ist der gewählte Loss allerdings deutlich zielführender. Ausprobieren!
Genau so wichtig ist die Wahl des Optimizers. "Adam" steht hier für "Adaptive Moment Estimation
" und gehört zur ersten Wahl.
Bei den Metrics ist accuracy ein guter Griff.

Bei all diesen Themen kann man sich endlos in mathematischen Details verlieren. Wichtig für den Einstieg ist zunächst, dass es "klappt", "läuft" und Ergebnisse liefert.

Hoffentlich auch auf euren Maschinen. ;-)