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 | Neuronale Netzwerke mit Tensorflow |
DO Morgen | weiter an Aufgaben |
DO Nachmittag | Buffer |
Erstelle GitHub-Repo z.B. mit Namen „talit_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
import numpy as np # SAVE LIST OF NP ARRAYS array_list = [np.array([1, 2, 3]), np.array([[4, 5], [6, 7]]), np.array([8, 9, 10, 11])] object_array = np.array(array_list, dtype=object) np.save('array_list.npy', object_array) # LOAD INTO LIST OF NP ARRAYS loaded_array_list = np.load('array_list.npy', allow_pickle=True) loaded_array_list = list(loaded_array_list)
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.# Stuktur: class Network: def __init__(self, input_neurons, hidden_neurons, output_neurons): # Variablen für Anz. Neuronen definieren # Gewichtsmatrizen erzeugen (zufällige Werte) def feedforward(self, x): # hidden Layer h aus Eingangswerten x und Gewichtsmatrix wA berechnen. # output Layer y aus Ausgangswerten y und Gewichtsmatrix wB berechnen. # beides (h und y) zurückgeben. def test(self, data_list): # data_list Zeile für Zeile durchgehen: # Target-Wert auslesen und Target-Vektor erstellen, # Einangswerte auslesen und Eingangs-Vektor erstellen. --> read_data # Hidden- und Output-Werte aus Eingangswerten berechnen --> feedforward # Ausgangswert mit Eingangswert vergleichen, korrekte Resultate zählen # Erfolgsquote zurückgeben. def train(self, data_list): # data_list Zeile für Zeile durchgehen: # Target-Wert auslesen und Target-Vektor erstellen, # Einangswerte auslesen und Eingangs-Vektor erstellen. --> read_data # Hidden- und Output-Werte aus Eingangswerten berechnen --> feedforward # Fehler auf Output-Layer berechnenen (Target - Output) # Fehler auf Hidden-Layer berechnen (Fehler auf Output dot wB) # Gewichtsmatrizen wA und WB aktualisieren (siehe Folie "Zusammenfassung") # Erstelle ein Netzwerk für das Toy-Problem: toy_net = Network(4, 3, 2) # Datenliste aus CSV auslesen und: # Testen (Erfolg für Toy-Problem ca. 50 %) # Trainieren # Testen (Erfolg hoffentlich ca. 90 %)
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