Dr.-Ing. Erhard Henkes, Stand: 05.09.2024
Was braucht man eigentlich, um in die
Themengebiete "Deep Learning", "Neuronale Netzwerke" und "Artificial
Intelligence" praktisch einzusteigen?
Die Antworten sind vielfältig. Wollen
wir selbst mit KI experimentieren, so nehmen wir Python als Programmiersprache
zusammen mit der Bibliothek Keras, basierend auf Tensorflow, und legen los.
Welche Tools brauchen wir konkret?
Mein Vorschlag ist, Anaconda3
(individuelle Distrbution) und die dazu passende Spyder Version zu
installieren.
Ich empfehle als Verzeichnis C:\anaconda3
und Verwendung des Anaconda Prompt als Administrator, damit es keine
Zugriffsprobleme gibt.
Nach der erfolgreichen Installation von Anaconda3 kann man mittels "Anaconda3 Prompt"
im Terminal die wichtige Arbeitsumgebung "Spyder"
installieren:
pip install
spyder
Zumeist kommt es zu Warnungen und Fehlermeldungen. Ich
empfehle aufgrund der Komplexität die Verwendung von KI wie ChatGPT-4o als
Partner, der
geduldig und konsequent die Ausgaben erklärt und neue Kommandos zur Eingabe in
den "Anaconda Prompt" ausspuckt.
Nun haben wir
hoffentlich Python am Start. Mit Spyder haben wir eine Kombination aus Editor,
Interpreter und Aus-/Eingabekonsole an der Hand.
Nun können wir loslegen. Bitte
sicherstellen, dass tensorflow mit keras installiert ist.
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, testweise 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. Ansonsten KI befragen.
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 erschien vor einigen Jahren 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.17.0
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:\Users\Erhard
Henkes\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages
Requires: tensorflow-intel
Required-by:
spy
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)
│ 401,920 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dropout (Dropout)
│ (None, 512)
│ 0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense_1 (Dense)
│ (None, 10)
│ 5,130 │
└─────────────────────────────────┴────────────────────────┴───────────────┘
Total params: 407,050 (1.55 MB)
Trainable params: 407,050 (1.55 MB)
Non-trainable params: 0 (0.00 B)
Training
Epoch 1/2
C:\Users\Erhard
Henkes\AppData\Roaming\Python\Python312\site-packages\keras\src\layers\reshaping\flatten.py:37:
UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When
using Sequential models, prefer using an `Input(shape)` object as the first
layer in the model instead.
super().__init__(**kwargs)
1875/1875
━━━━━━━━━━━━━━━━━━━━ 5s 2ms/step - accuracy: 0.8892 - loss: 0.3730
Epoch 2/2
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy: 0.9686 - loss: 0.1033
Test
313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9656 - loss:
0.1052
Das war es schon! Das erste "Neural Network" (NN) hat gearbeitet.
ChatGPT-4o meint hierzu:
Das Modell ist ein einfaches neuronales Netzwerk, das für die
Bilderkennung auf dem MNIST-Datensatz (handgeschriebene Ziffern) verwendet wird.
Es besteht aus den folgenden Schichten:
Flatten (Flatten-Schicht)
Dense (Vollverbundene Schicht)
(None, 512)
bedeutet,
dass die Ausgabe dieser Schicht für jedes Eingabebild 512 Werte enthält.Dropout (Dropout-Schicht)
(None, 512)
, da
nur einige Neuronen während des Trainings deaktiviert werden, aber die
Struktur der Ausgabe nicht verändert wird.Dense (Vollverbundene Schicht)
(None, 10)
bedeutet,
dass die Ausgabe dieser Schicht für jedes Eingabebild 10 Werte enthält,
die die Wahrscheinlichkeiten der Ziffern repräsentieren.Training
Test
Die Handschrifterkennung soll besser werden? 96,5 % 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%.
Training
Epoch 1/20
1875/1875
━━━━━━━━━━━━━━━━━━━━ 5s 2ms/step - accuracy: 0.8953 - loss: 0.3605
Epoch
2/20
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy: 0.9705 - loss:
0.0979
Epoch 3/20
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy:
0.9787 - loss: 0.0686
Epoch 4/20
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s
2ms/step - accuracy: 0.9839 - loss: 0.0509
Epoch 5/20
1875/1875
━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy: 0.9866 - loss: 0.0416
Epoch
6/20
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy: 0.9905 - loss:
0.0294
Epoch 7/20
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy:
0.9912 - loss: 0.0262
Epoch 8/20
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s
2ms/step - accuracy: 0.9906 - loss: 0.0278
Epoch 9/20
1875/1875
━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy: 0.9921 - loss: 0.0220
Epoch
10/20
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy: 0.9930 - loss:
0.0214
Epoch 11/20
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy:
0.9932 - loss: 0.0199
Epoch 12/20
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s
2ms/step - accuracy: 0.9944 - loss: 0.0178
Epoch 13/20
1875/1875
━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy: 0.9948 - loss: 0.0164
Epoch
14/20
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy: 0.9936 - loss:
0.0177
Epoch 15/20
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy:
0.9953 - loss: 0.0141
Epoch 16/20
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s
2ms/step - accuracy: 0.9954 - loss: 0.0147
Epoch 17/20
1875/1875
━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy: 0.9960 - loss: 0.0124
Epoch
18/20
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy: 0.9964 - loss:
0.0117
Epoch 19/20
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s 2ms/step - accuracy:
0.9955 - loss: 0.0142
Epoch 20/20
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 4s
2ms/step - accuracy: 0.9956 - loss: 0.0140
Test
313/313
━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - accuracy: 0.9797 - loss: 0.1274
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. 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.
Beim Input Layer treten unsere Eingangsdaten hinein und beim Output Layer kommen
die 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. ;-)
Ein weiteres Beispiel verwendet ein Convolutional
Neural Network (CNN). CNNs sind für Bilderkennung optimiert und bieten oft
bessere Ergebnisse als einfache neuronale Netze.
import tensorflow as tf
# MNIST-Datensatz laden
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) =
mnist.load_data()
# Daten normalisieren
x_train = x_train.reshape(-1, 28, 28,
1).astype('float32') / 255
x_test = x_test.reshape(-1, 28, 28,
1).astype('float32') / 255
# CNN-Modell definieren
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(32, (3, 3), activation='relu',
input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
# Modell zusammenfassen
model.summary()
# Kompilieren
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# Training
print("\nTraining")
model.fit(x_train, y_train, epochs=5)
# Test
print("\nTest")
model.evaluate(x_test, y_test)
Model: "sequential"
┌─────────────────────────────────┬────────────────────────┬───────────────┐
│ Layer (type)
│ Output Shape │
Param # │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ conv2d (Conv2D)
│ (None, 26, 26, 32) │ 320
│
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ max_pooling2d (MaxPooling2D) │ (None, 13, 13, 32)
│ 0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ conv2d_1 (Conv2D)
│ (None, 11, 11, 64) │ 18,496
│
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ max_pooling2d_1 (MaxPooling2D) │ (None, 5, 5, 64)
│ 0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ conv2d_2 (Conv2D)
│ (None, 3, 3, 64) │ 36,928
│
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ flatten (Flatten)
│ (None, 576)
│ 0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense (Dense)
│ (None, 64)
│ 36,928 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense_1 (Dense)
│ (None, 10)
│ 650 │
└─────────────────────────────────┴────────────────────────┴───────────────┘
Total params: 93,322 (364.54 KB)
Trainable params: 93,322 (364.54 KB)
Non-trainable params: 0 (0.00 B)
Training
Epoch 1/5
C:\Users\Erhard
Henkes\AppData\Roaming\Python\Python312\site-packages\keras\src\layers\convolutional\base_conv.py:107:
UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When
using Sequential models, prefer using an `Input(shape)` object as the first
layer in the model instead.
super().__init__(activity_regularizer=activity_regularizer, **kwargs)
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 38s 19ms/step - accuracy: 0.9013 - loss: 0.3226
Epoch 2/5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 35s 19ms/step - accuracy: 0.9844
- loss: 0.0481
Epoch 3/5
1875/1875 ━━━━━━━━━━━━━━━━━━━━ 36s 19ms/step -
accuracy: 0.9901 - loss: 0.0315
Epoch 4/5
1875/1875 ━━━━━━━━━━━━━━━━━━━━
35s 19ms/step - accuracy: 0.9919 - loss: 0.0269
Epoch 5/5
1875/1875
━━━━━━━━━━━━━━━━━━━━ 35s 19ms/step - accuracy: 0.9937 - loss: 0.0202
Test
313/313 ━━━━━━━━━━━━━━━━━━━━ 2s 5ms/step - accuracy: 0.9870 - loss:
0.0420
Wie man sieht, ist das Resultat etwas genauer.
Mit diesem Einstieg, der
hoffentlich erfolgreich war, ist das praktische Arbeiten mit Python, Tensorflow,
Keras im Bereich NN gelungen.