Inhaltsverzeichnis

Neuronale Netze

Ziel von diesem Kurs ist, mit Python selbst ein künstliches neuronales Netz zu programmieren, welches handgeschriebene Zahlen erkennen kann.

1. Plan

Zeiten: 9 - 12, 13 - 16 (9 ist fix, die anderen Zeiten flexibler)

DatumInhalt
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

2. Materialien

Slides

01_neuronale_netze_intro_forward.pdf

02_neuronale_netze_backpropagation.pdf

Files

Repos

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

Aufgabe 1

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

Aufgabe 2

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:


# 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)

Aufgabe 3

Aufgabe 4

Zusatzaufgaben

Es gibt verschiedene Arten von Zusatzaufgaben. Lese sie durch und entscheide selbst, welche du lösen möchtest. Der Schwierigkeitsgrad ist in * angegeben:

Aufgabe Z1: Zahlen anzeigen (*)

Aufgabe Z2: Untersuchung Performance (*)

Aufgabe Z3a: Zwei Hidden Layers (*)

Füge deinem Neuronalen Netz einen zusätzlichen Hidden Layer hinzu.

Aufgabe Z3b: Beliebig viele Hidden Layers (**)

Aufgabe Z4: Bias (**)

Aufgabe Z5: Anderer Datensatz (*)

Aufgabe Z6: Keras (**)

python -m pip install --upgrade pip
python -m pip install tensorflow
python -m pip install keras

Aufgabe Z7: GUI (***)

Aufgabe Z-ULTIMATE!!!

4. Theorie

In diesem Kapitel werden einige zusätzliche Informationen zur benötigten Mathe gegeben.

Numpy

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

Matrizen & Vektoren

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} $$

Matrizen in Numpy

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.

Lösung

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):

  1. $V \cdot V$
  2. $V \cdot V^T$
  3. $V^T \cdot V$

Überlege dir zuerst: Welche Dimension hat das Resultat? Rechne dann aus mithilfe von numpy.

Lösung

Drawing in Jupyter

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.

Setup Jupyter-Notebook

in Konsole:

  1. Verwende passende Python Version (z.B. funktioniert 3.11 gut, 3.8.5 aber nicht, Stand Juli 2023)
  2. Jupyter-NB installieren: pip install notebook
  3. Navigiere mit cd in Projektordner.
  4. Starte Jupyter-NB (öffnet in Browser): jupyter-notebook
  5. Öffne dort bestehendes .ipynb File oder erstelle ein neues

DrawingWidget

Installation (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