Ziel von diesem Kurs ist, mit Python selbst ein künstliches neuronales Netz zu programmieren, welches handgeschriebene Zahlen erkennen kann.
Zeiten: 9 - 12, 13 - 16 (9 ist fix, die anderen Zeiten flexibler)
Datum | Inhalt |
---|---|
MO Morgen | Slides I |
Einführung & Übersicht: Was sind neuronale Netze & künstliche Intelligenz? | |
NN Programmieren: Struktur & Feedforward | |
MO Nachmittag | Aufgaben 1 und 2 |
Aufbau einfache NN (noch ohne backpropagation) | |
DI Morgen | Slides 2 |
Mathematik (Ableitung, Gradientenabstieg, …) | |
Training durch Backpropagation | |
DI Nachmittag | Aufgaben 3 - … |
Neuronales Netz inkl. Backpropagation programmieren | |
MI Morgen | Recap: Neuronale Netze Programmieren |
weiter an Aufgaben | |
MI Nachmittag | weiter an Aufgaben |
DO Morgen | weiter an Aufgaben |
DO Nachmittag | Buffer |
Erstelle GitHub-Repo z.B. mit Namen „neural_networks“. Lege alle deine Code-Files hier drin ab. Committe und pushe regelmässig.
Aufgaben: Siehe Slides
01_toy_problem_feedforward.py
(resp. <...>.ipynb
)data_dark_bright_test_4000.csv
ein.Tipps:
### OPTION 1 """File wird direkt in eine Liste eingelesen""" with open('my_file.csv', 'r') as f: data_list = f.readlines() # erstellt Liste ### OPTION 2 """Gehe File Zeile für Zeile durch, muss dann selbst in Liste schreiben""" import csv # ganz oben in Code with open('my_file.csv', 'r',newline='') as csv_file: csv_reader = csv.reader(csv_file) for row in csv_reader: # do something with row
Bemerkung für 2024: Leider hatten wir keine Zeit, die objektorientierte Programmierung (OOP) zu behandeln. Recherchiere deshalb selbst kurz dazu im Internet oder studiere ein passendes Video, z.B.:
Auftrag:
02_feedforward_oop.py
(resp. <...>.ipynb
)Network
enthalten:self.wA = ..., self.wB = ...
np.random.rand
)feedforward
. Dieser wird als Argument ein Input-Array übergeben. Diesen ‘feeded’ sie dann ‘forward’ und berechnet den zugehörigen Output.test
. Dieser kann man als Argument einen Datensatz übergeben, der dann durch das NN gefüttert wird. Es wird die Erfolgsquote zurückgegeben: Für wie viele (in Prozent) der Datenpunkte produziert das NN einen korrekten Output?.test
Methode, wie gut dein NN funktioniert.
# Stuktur: class Network: def __init__(self, input_neurons, hidden_neurons, output_neurons): # ... def feedforward(self, x): # ... def test(self, data_list): # ... # Erstelle ein Netzwerk für das Toy-Problem: toy_net = Network(4, 3, 2) # Erstelle ein Netzwerk für den Mnist-Datensatz: mnist_net = Network(784, 30, 10)
02_feedforward_oop.py
und speichere diese unter dem Namen 03_toy_problem_training.py
(resp. <...>.ipynb
)learning_rate
. Ein Wert für diese soll als Argument für die __init__
-Methode übergeben werden, wenn ein Network
-Objekt erstellt wird.Network
-Klasse um eine Methode train
. Dieser soll ein Datensatz übergeben werden, mit dem das Netzwerk trainiert werden soll.03_toyproblem_training.py
und speichere diese unter dem Namen 04_neural_network.py
(resp. <...>.ipynb
)train
Methode. Bestimme danach die Erfolgsquote des NN.Es gibt verschiedene Arten von Zusatzaufgaben. Lese sie durch und entscheide selbst, welche du lösen möchtest. Der Schwierigkeitsgrad ist in * angegeben:
Füge deinem Neuronalen Netz einen zusätzlichen Hidden Layer hinzu.
__init__
-Methode übergeben.python -m pip install --upgrade pip python -m pip install tensorflow python -m pip install keras
In diesem Kapitel werden einige zusätzliche Informationen zur benötigten Mathe gegeben.
Möchte man mathematische Dinge in Python programmieren, lohnt es sich, mit numpy zu arbeiten, einer umfassenden Library für Alles, was mit Mathematik zu tun hat. Unter anderem bietet es einem die Möglichkeit, Matrizen zu erzeugen und mit diesen zu rechnen.
Zuerst musst du numpy installieren. Dies geht am einfachsten mit pip:
python -m pip install numpy
Um mit Numpy zu arbeiten, musst du dieses zuerst importieren:
import numpy as np
Numpy-Funktionen werden dann wie folgt aufgerufen:
np.sin(1.4) # berechnet den Sinus von 1.4 np.sqrt(2.0) # berechnet die Wurzel von 2
Eine Matrix ist nicht nur eine Computersimulation, in der wir eventuell leben, sondern auch etwas sehr wichtiges in der Mathematik: Sie ist eigentlich nichts anderes als eine Tabelle, bestehend aus Zahlen. Eine $n \times m$-Matrix ist immer von der folgenden Form: $$ \begin{pmatrix} a_{1,1} & a_{1,2} & \ldots & a_{1,m} \\ a_{2,1} & a_{2,2} & \ldots & a_{2,m} \\ \ldots & \ldots & \ddots & \ldots \\ a_{n,1} & a_{n,2} & \ldots & a_{n,m} \\ \end{pmatrix} $$
Beispiel: Die folgende Matrix ist eine $3\times 5$-Matrix : $$ \begin{pmatrix} 1 & 5 & 2 & -4 & 7\\ 0 & -3 & 4 & 0 & 1\\ -2 & -1 & 0 & 3 & 2 \end{pmatrix} $$
Ein Vektor ist eine $n\times 1$-Matrix: $$ \begin{pmatrix} 4 \\ -3 \\ 2 \end{pmatrix} $$
Die wichtigsten einfachen Befehle zu Matrizen in Python sind:
A = np.array([[1,2,3],[4,5,6]]) # eine $2\times 3$-Matrix erzeugen A.shape # Dimension von A abfragen -> (2,3) Z = np.zeros((2,3)) # Null-Matrix (alle Komponenten = 0) mit angegebener Dimension erzeugen R = np.random.rand(2,3) # Zahlen mit Zufallswerten im Interval (0,1) erzeugen A.T # Matrix transponieren, z.B. von Dim (2,3) -> Dim (3,2)
Matrixmultiplikation: Zwei Matrizen $A$ und $B$ können miteinander multipliziert werden, wenn ihre Dimensionen kompatibel sind. Machen wir ein einfaches Beispiel. Wir wollen eine $3\times 2$-Matrix $A$ mit einer $2\times 4$-Matrix $B$ multiplizieren. Dies ist möglich, weil die Breite von $A$ mit der Höhe von $B$ übereinstimmt. Die resultierende Matrix $C = A \cdot B$ ist dann eine $3\times 4$-Matrix: $$ A = \left( \begin{array}{cc} 2 & 1 \\ 3 & 0 \\ 2 & 2 \\ \end{array} \right)\,, \quad B = \left( \begin{array}{cccc} 2 & 1 & 0 & 1 \\ 0 & 2 & 1 & 1 \\ \end{array} \right) $$
$$C = A\cdot B = \left( \begin{array}{cccc} 2\cdot 2 + 1\cdot 0 & & 2\cdot 1 + 1\cdot 2 & & 2\cdot 0 + 1\cdot 1 & & 2\cdot 1 + 1\cdot 1\\ 3\cdot 2 + 0\cdot 0 & & 3\cdot 1 + 0\cdot 2 & & 3\cdot 0 + 0\cdot 1 & & 3\cdot 1 + 0\cdot 1\\ 2\cdot 2 + 2\cdot 0 & & 2\cdot 1 + 2\cdot 2 & & 2\cdot 0 + 2\cdot 1 & & 2\cdot 1 + 2\cdot 1\\ \end{array} \right) = \left( \begin{array}{cccc} 4 & 4 & 1 & 3 \\ 6 & 3 & 0 & 3 \\ 4 & 6 & 2 & 4 \\ \end{array} \right) $$
Mit numpy multipliziert man die beiden Matrizen $A$ und $B$ dann wie folgt:
np.dot(A,B)
Aufgabe: Überprüfe das Beispiel oben selbst mithilfe von numpy.
Vektoren: Wie oben gesagt, ist ein Vektor eine $n \times 1$-Matrix. Der Vektor v = np.array([1,2,3])
hat dann die Dimension (3,)
(vergewissere dich mit v.shape
). Für unsere Rechnungen ist es meist besser, wenn die Matrix die Dimension (3,1)
hat. Dies erreicht man mit dem reshape-Befehl:
v = np.array([1,2,3]) # shape: (3,) v = v.reshape((-1,1)) # shape: (3,1)
Aufgabe: Betrachte den Vektor $$V = \begin{pmatrix} 2 \\ 3 \\ 5 \end{pmatrix} $$
Was gibt dann ($^T$ steht für Transponieren):
Überlege dir zuerst: Welche Dimension hat das Resultat? Rechne dann aus mithilfe von numpy.
Mit Stift oder Tastatur direkt in Jupyter-Notebook zeichnen. Kann z.B. Zahlen zeichnen und von neuronalem Netz analysieren lassen.
Achtung: Funktioniert NICHT in VSCode, verwende das 'richtige' Jupyter-Notebook.
in Konsole:
pip install notebook
cd
in Projektordner.jupyter-notebook
.ipynb
File oder erstelle ein neuesInstallation (kann direkt im Jupyter-Notebook gemacht werden)
!pip install ipycanvas-drawing !pip install Pillow
Drawing Canvas:
from ipycanvas_drawing import DrawingWidget import numpy as np from PIL import Image n = 256 drawing_widget = DrawingWidget(width=n, height=n, background='lightblue', default_radius=15) drawing_widget.show()
Auf Daten von gezeichnetem Bild zugreifen und verkleinern $(28 \times 28)$:
def resize_image(image,dim=(28,28)): image = Image.fromarray(image) # Create a PIL Image object from the np.array scaled_image = image.resize((dim[0],dim[1])) scaled_image = np.array(scaled_image) return scaled_image image = drawing_widget.get_image_data() # get data of image drawn above image_small = resize_image(image) # scale down to 28x28