Deep Learning – Neuronale Netze und CNNs

Fach: Data Science & Artificial Intelligence
Schulstufe: 12. Schulstufe – HTL Informatik
Voraussetzungen: Supervised Learning, Python / NumPy, grundlegende Lineare Algebra
Autor: HTL Pinkafeld – IF/IT



1. Von ML zu Deep Learning

1.1 Was ist Deep Learning?

Deep Learning ist ein Teilgebiet des Machine Learnings, das auf künstlichen neuronalen Netzen mit vielen Schichten basiert. Der Begriff „deep" (tief) bezieht sich auf die Anzahl der Schichten – moderne Netze haben oft Dutzende bis Hunderte davon.

1.2 Warum Deep Learning?

Klassische ML-Algorithmen wie Random Forest oder SVM benötigen handgefertigte Features (Feature Engineering). Bei Bildern, Audio oder Text ist das extrem aufwändig – man müsste dem Algorithmus manuell sagen, worauf er achten soll.

Deep Learning lernt die relevanten Features automatisch aus den Rohdaten:

Klassisches ML:
  Rohdaten → [Feature Engineering, manuell] → Features → Algorithmus → Ausgabe

Deep Learning:
  Rohdaten ────────────────────────────────→ Neuronales Netz → Ausgabe
                                              (lernt Features selbst)

1.3 Wann ist Deep Learning sinnvoll?

Situation Empfehlung
Bilder, Audio, Video, Text ✅ Deep Learning
Tabellarische/strukturierte Daten ⚠️ Oft Ensemble-Methoden besser
Wenig Daten (< 10.000) ⚠️ Klassisches ML oft besser
Viele Daten, hohe Komplexität ✅ Deep Learning
Interpretierbarkeit wichtig ❌ Eher klassisches ML

1.4 Historischer Durchbruch

1958  Perceptron (Rosenblatt)
1986  Backpropagation (Rumelhart, Hinton)
1998  LeNet – erstes CNN für Ziffernerkennung (LeCun)
2012  AlexNet gewinnt ImageNet – Deep Learning-Revolution
2017  Transformer-Architektur (Vaswani et al.)
2022  ChatGPT – Large Language Models im Mainstream

2. Das künstliche Neuron

2.1 Biologisches Vorbild

Das künstliche Neuron ist vom biologischen Neuron inspiriert:

Biologisch:           Künstlich:
Dendriten  →  Eingaben x₁, x₂, ..., xₙ
Zellkörper →  Gewichtete Summe + Bias
Axon       →  Aktivierungsfunktion → Ausgabe

2.2 Mathematisches Modell

Ein einzelnes Neuron berechnet:

z = w₁·x₁ + w₂·x₂ + ... + wₙ·xₙ + b
       = wᵀ·x + b          (Vektorschreibweise)

y = f(z)                    (Aktivierungsfunktion anwenden)

2.3 Das Perceptron

Das einfachste Neuron – der Perceptron – verwendet eine Stufenfunktion als Aktivierung:

import numpy as np

def perceptron(x, w, b):
    z = np.dot(w, x) + b
    return 1 if z >= 0 else 0

# Beispiel: UND-Gatter
w = np.array([1.0, 1.0])
b = -1.5

print(perceptron([0, 0], w, b))   # 0
print(perceptron([0, 1], w, b))   # 0
print(perceptron([1, 0], w, b))   # 0
print(perceptron([1, 1], w, b))   # 1

⚠️ Problem: Ein einzelnes Neuron kann nur linear trennbare Probleme lösen. Das XOR-Problem z.B. ist nicht linear trennbar – dafür brauchen wir mehrere Schichten.


3. Aktivierungsfunktionen

Aktivierungsfunktionen bringen Nichtlinearität ins Netz. Ohne sie wäre ein mehrstufiges Netz mathematisch äquivalent zu einem einzelnen Neuron.

3.1 Übersicht

Funktion Formel Ausgabebereich Typische Verwendung
Sigmoid 1 / (1 + e⁻ᶻ) (0, 1) Ausgabeschicht (Binäre Klass.)
Tanh (eᶻ - e⁻ᶻ) / (eᶻ + e⁻ᶻ) (-1, 1) Versteckte Schichten (veraltet)
ReLU max(0, z) [0, ∞) Versteckte Schichten (Standard)
Leaky ReLU z if z>0 else 0.01·z (-∞, ∞) Versteckte Schichten
Softmax eᶻⁱ / Σ eᶻʲ (0,1), Summe=1 Ausgabeschicht (Mehrklassen)

3.2 ReLU – Rectified Linear Unit

ReLU ist heute die Standard-Aktivierungsfunktion in versteckten Schichten:

import numpy as np
import matplotlib.pyplot as plt

z = np.linspace(-4, 4, 200)

relu        = np.maximum(0, z)
leaky_relu  = np.where(z > 0, z, 0.01 * z)
sigmoid     = 1 / (1 + np.exp(-z))
tanh        = np.tanh(z)

fig, axes = plt.subplots(1, 2, figsize=(10, 4))

axes[0].plot(z, relu,       label='ReLU',       color='#F6A01D', linewidth=2)
axes[0].plot(z, leaky_relu, label='Leaky ReLU', color='#C97D00', linestyle='--', linewidth=2)
axes[0].axhline(0, color='gray', linewidth=0.5)
axes[0].axvline(0, color='gray', linewidth=0.5)
axes[0].set_title('ReLU Varianten'); axes[0].legend()

axes[1].plot(z, sigmoid, label='Sigmoid', color='#F6A01D', linewidth=2)
axes[1].plot(z, tanh,    label='Tanh',    color='#C97D00', linestyle='--', linewidth=2)
axes[1].axhline(0, color='gray', linewidth=0.5)
axes[1].set_title('Sigmoid & Tanh'); axes[1].legend()

plt.tight_layout()
plt.show()

3.3 Warum ReLU so beliebt ist

Vanishing Gradient Problem: Bei Sigmoid/Tanh werden die Gradienten in tiefen Netzen immer kleiner (gegen 0) – das Netz lernt kaum noch. ReLU löst dieses Problem weitgehend.


4. Feedforward Neural Network

4.1 Aufbau

Ein Feedforward Neural Network (auch Multi-Layer Perceptron, MLP) besteht aus:

Eingabe-      Versteckte Schichten      Ausgabe-
schicht            (hidden layers)      schicht

  x₁  ──┐                          ┌── ŷ₁
  x₂  ──┼─→ [Layer 1] → [Layer 2] ─┼── ŷ₂
  x₃  ──┘                          └── ŷ₃

Daten fließen immer vorwärts (feedforward)

4.2 Matrixschreibweise einer Schicht

Für eine Schicht mit n Eingaben und m Neuronen:

Z = X · Wᵀ + b
A = f(Z)

X: (batch_size × n)   Eingabe
W: (m × n)            Gewichtsmatrix
b: (m,)               Bias-Vektor
A: (batch_size × m)   Ausgabe nach Aktivierung

4.3 Universeller Approximationssatz

Ein neuronales Netz mit einer versteckten Schicht und genügend Neuronen kann jede stetige Funktion beliebig genau approximieren.

In der Praxis sind jedoch tiefe Netze (viele Schichten, weniger Neuronen pro Schicht) effizienter als breite Netze (eine Schicht, viele Neuronen).


5. Training: Backpropagation und Gradient Descent

5.1 Das Lernprinzip

Beim Training wird ein Fehlermaß (Loss) berechnet und die Gewichte so angepasst, dass der Fehler sinkt. Das Herzstück ist der Gradientenabstieg:

w_neu = w_alt - η · ∂L/∂w

η = Lernrate (wie groß ist der Schritt?)
∂L/∂w = Gradient des Verlusts bzgl. des Gewichts

5.2 Backpropagation

Backpropagation berechnet effizient die Gradienten aller Gewichte mithilfe der Kettenregel der Differentialrechnung – von der Ausgabeschicht rückwärts zur Eingabeschicht.

Vorwärtsdurchlauf (Forward Pass):
  x → Layer 1 → Layer 2 → ... → ŷ → L(ŷ, y)

Rückwärtsdurchlauf (Backward Pass):
  ∂L/∂wₙ ← ∂L/∂wₙ₋₁ ← ... ← ∂L/∂w₁
  (Kettenregel rückwärts anwenden)

Gewichte aktualisieren:
  w ← w - η · ∂L/∂w

5.3 Gradientenabstieg-Varianten

Variante Beschreibung Vor-/Nachteile
Batch GD Gradient über alle Daten Stabil, aber langsam
Stochastic GD (SGD) Gradient über 1 Datenpunkt Schnell, aber laut/instabil
Mini-Batch GD Gradient über k Datenpunkte ✅ Bester Kompromiss (Standard)
# Mini-Batch: Typische Batch-Größen: 32, 64, 128, 256
model.fit(X_train, y_train, batch_size=32, epochs=50)

5.4 Die Lernrate

Die Lernrate η ist einer der wichtigsten Hyperparameter:

η zu groß:  Überspringt Minimum → konvergiert nicht
η zu klein: Lernt sehr langsam → braucht viele Epochen
η optimal:  Konvergiert zuverlässig zum Minimum

Tipp: Lernraten-Scheduler passen η während des Trainings an – zu Beginn groß, später klein.


6. Verlustfunktionen

Die Verlustfunktion (Loss Function) misst, wie falsch die Vorhersagen sind.

6.1 Übersicht

Aufgabe Verlustfunktion Keras-Name
Binäre Klassifikation Binary Cross-Entropy binary_crossentropy
Mehrklassen-Klassifikation (Integer Labels) Sparse Categorical Cross-Entropy sparse_categorical_crossentropy
Mehrklassen-Klassifikation (One-Hot Labels) Categorical Cross-Entropy categorical_crossentropy
Regression Mean Squared Error mse
Regression (robuster) Mean Absolute Error mae

6.2 Cross-Entropy anschaulich

Vorhersage für Katze: 90% → Loss klein (fast richtig)
Vorhersage für Katze: 10% → Loss groß (sehr falsch)

Binary Cross-Entropy:
  L = -[y · log(ŷ) + (1-y) · log(1-ŷ)]

7. Erstes Netz mit Keras

7.1 Keras und TensorFlow

Keras ist das offizielle High-Level-API von TensorFlow. Es ermöglicht das schnelle Aufbauen und Trainieren neuronaler Netze mit wenigen Zeilen Code.

pip install tensorflow

7.2 Klassifikation: MNIST-Ziffernerkennung

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

# ── 1. Daten laden ────────────────────────────────────────────────────────
(X_train, y_train), (X_test, y_test) = keras.datasets.mnist.load_data()

# Normalisieren: Pixelwerte 0–255 → 0.0–1.0
X_train = X_train.astype('float32') / 255.0
X_test  = X_test.astype('float32')  / 255.0

# Bilder glätten: (28, 28) → (784,)
X_train = X_train.reshape(-1, 784)
X_test  = X_test.reshape(-1, 784)

print(f"Trainingsdaten: {X_train.shape}")   # (60000, 784)
print(f"Testdaten:      {X_test.shape}")    # (10000, 784)

# ── 2. Modell aufbauen ────────────────────────────────────────────────────
model = keras.Sequential([
    layers.Dense(128, activation='relu',    input_shape=(784,)),
    layers.Dense(64,  activation='relu'),
    layers.Dense(10,  activation='softmax')   # 10 Klassen (0–9)
])

model.summary()

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

# ── 4. Trainieren ─────────────────────────────────────────────────────────
history = model.fit(
    X_train, y_train,
    epochs=10,
    batch_size=64,
    validation_split=0.1,   # 10% der Trainingsdaten als Validierung
    verbose=1
)

# ── 5. Evaluieren ─────────────────────────────────────────────────────────
test_loss, test_acc = model.evaluate(X_test, y_test, verbose=0)
print(f"\nTest Accuracy: {test_acc:.2%}")

# ── 6. Trainingsverlauf visualisieren ─────────────────────────────────────
fig, axes = plt.subplots(1, 2, figsize=(11, 4))

axes[0].plot(history.history['loss'],     label='Training Loss')
axes[0].plot(history.history['val_loss'], label='Validation Loss')
axes[0].set_title('Verlust'); axes[0].legend()

axes[1].plot(history.history['accuracy'],     label='Training Accuracy')
axes[1].plot(history.history['val_accuracy'], label='Validation Accuracy')
axes[1].set_title('Accuracy'); axes[1].legend()

plt.tight_layout()
plt.show()

7.3 Modell-Architektur lesen

Layer (type)          Output Shape     Param #
=================================================
dense (Dense)         (None, 128)      100.480   ← 784×128 + 128 Bias
dense_1 (Dense)       (None, 64)       8.256     ← 128×64  + 64  Bias
dense_2 (Dense)       (None, 10)       650       ← 64×10   + 10  Bias
=================================================
Total params: 109.386

💡 Parameteranzahl berechnen: Ausgaben × Eingaben + Ausgaben (Bias)


8. Overfitting bekämpfen

8.1 Dropout

Dropout deaktiviert zufällig einen Anteil der Neuronen während des Trainings. Das verhindert, dass einzelne Neuronen zu dominant werden.

model = keras.Sequential([
    layers.Dense(256, activation='relu', input_shape=(784,)),
    layers.Dropout(0.3),                  # 30% der Neuronen deaktivieren
    layers.Dense(128, activation='relu'),
    layers.Dropout(0.3),
    layers.Dense(10, activation='softmax')
])

Beim Inferenz (Vorhersage) werden alle Neuronen wieder aktiviert – Dropout ist nur während des Trainings aktiv.

8.2 Batch Normalization

Batch Normalization normalisiert die Aktivierungen jeder Schicht, was das Training stabilisiert und beschleunigt:

model = keras.Sequential([
    layers.Dense(256, input_shape=(784,)),
    layers.BatchNormalization(),
    layers.Activation('relu'),
    layers.Dense(128),
    layers.BatchNormalization(),
    layers.Activation('relu'),
    layers.Dense(10, activation='softmax')
])

8.3 Early Stopping

Das Training stoppt automatisch, wenn die Validation Loss nicht mehr sinkt:

from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau

callbacks = [
    EarlyStopping(
        monitor='val_loss',
        patience=5,           # Stoppt nach 5 Epochen ohne Verbesserung
        restore_best_weights=True
    ),
    ReduceLROnPlateau(
        monitor='val_loss',
        factor=0.5,           # Lernrate halbieren
        patience=3
    )
]

history = model.fit(
    X_train, y_train,
    epochs=100,
    batch_size=64,
    validation_split=0.1,
    callbacks=callbacks,
    verbose=1
)

8.4 Regularisierung (L2)

from tensorflow.keras import regularizers

model = keras.Sequential([
    layers.Dense(256, activation='relu',
                 kernel_regularizer=regularizers.l2(0.001),
                 input_shape=(784,)),
    layers.Dense(10, activation='softmax')
])

8.5 Überblick Regularisierungstechniken

Technik Wann einsetzen Keras
Dropout Immer, besonders bei großen Netzen layers.Dropout(rate)
Batch Normalization Tiefe Netze, instabiles Training layers.BatchNormalization()
Early Stopping Immer EarlyStopping(patience=n)
L2-Regularisierung Wenn Overfitting trotz Dropout regularizers.l2(λ)
Mehr Daten / Data Augmentation Immer die beste Lösung Siehe CNNs

9. Convolutional Neural Networks (CNNs)

9.1 Motivation

Ein MLP auf einem 224×224 Farbbild hätte in der ersten Schicht bereits 224 × 224 × 3 = 150.528 Eingaben – das sind Millionen von Parametern, bevor das Netz auch nur eine Schicht tief ist. Außerdem ignoriert ein MLP die räumliche Struktur des Bildes völlig.

CNNs lösen beide Probleme durch lokale Verbindungen und gemeinsame Gewichte.

9.2 Der Faltungsoperator (Convolution)

Ein Filter (Kernel) der Größe k×k gleitet über das Bild und berechnet an jeder Position eine gewichtete Summe:

Eingabe (5×5):         Filter (3×3):       Ausgabe (Feature Map):
1 0 1 0 0             1  0 -1              ·  ·  ·
0 1 0 1 0      *      0  0  0       =      ·  4  ·
1 0 1 0 1             -1 0  1              ·  ·  ·
0 1 0 0 1
0 1 1 0 1

9.3 Wichtige CNN-Schichten

Conv2D – Faltungsschicht:

layers.Conv2D(
    filters=32,         # Anzahl der Filter
    kernel_size=(3, 3), # Filtergröße
    activation='relu',
    padding='same'      # Ausgabegröße = Eingabegröße
)

MaxPooling2D – Reduktionsschicht:

layers.MaxPooling2D(pool_size=(2, 2))
# Reduziert Breite und Höhe um Faktor 2
# Wählt den Maximalwert in jedem 2×2-Bereich

Flatten – Übergang zu Dense:

layers.Flatten()
# Wandelt 2D Feature Map in 1D-Vektor um

9.4 Typische CNN-Architektur

Eingabebild (28×28×1)
      │
  Conv2D (32 Filter, 3×3) → ReLU      → (28×28×32)
      │
  MaxPooling (2×2)                     → (14×14×32)
      │
  Conv2D (64 Filter, 3×3) → ReLU      → (14×14×64)
      │
  MaxPooling (2×2)                     → (7×7×64)
      │
  Flatten                              → (3136,)
      │
  Dense (128) → ReLU
      │
  Dropout (0.5)
      │
  Dense (10) → Softmax                 → (10,)

9.5 CNN für MNIST

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

# Daten laden und vorbereiten
(X_train, y_train), (X_test, y_test) = keras.datasets.mnist.load_data()

# Für CNNs: (n, 28, 28, 1) – Kanal-Dimension hinzufügen
X_train = X_train.reshape(-1, 28, 28, 1).astype('float32') / 255.0
X_test  = X_test.reshape(-1, 28, 28, 1).astype('float32') / 255.0

# CNN-Modell
model = keras.Sequential([
    # Block 1
    layers.Conv2D(32, (3, 3), activation='relu', padding='same',
                  input_shape=(28, 28, 1)),
    layers.MaxPooling2D((2, 2)),

    # Block 2
    layers.Conv2D(64, (3, 3), activation='relu', padding='same'),
    layers.MaxPooling2D((2, 2)),

    # Klassifikationskopf
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
    layers.Dropout(0.5),
    layers.Dense(10, activation='softmax')
])

model.summary()

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

history = model.fit(
    X_train, y_train,
    epochs=10,
    batch_size=64,
    validation_split=0.1
)

test_loss, test_acc = model.evaluate(X_test, y_test, verbose=0)
print(f"CNN Test Accuracy: {test_acc:.2%}")   # Typisch: > 99%

10. Praktisches Projekt: Bildklassifikation mit CIFAR-10

10.1 Der CIFAR-10 Datensatz

CIFAR-10 enthält 60.000 Farbbilder (32×32 Pixel) in 10 Klassen: Flugzeug, Auto, Vogel, Katze, Reh, Hund, Frosch, Pferd, Schiff, LKW

10.2 Data Augmentation

Da 50.000 Trainingsbilder für ein CNN relativ wenig sind, erweitern wir den Datensatz künstlich durch Data Augmentation – das Erzeugen leicht veränderter Kopien:

from tensorflow.keras.layers import RandomFlip, RandomRotation, RandomZoom

augmentation = keras.Sequential([
    RandomFlip('horizontal'),
    RandomRotation(0.1),
    RandomZoom(0.1),
])

10.3 Vollständige Pipeline

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import matplotlib.pyplot as plt
import numpy as np

# ── 1. Daten laden ────────────────────────────────────────────────────────
(X_train, y_train), (X_test, y_test) = keras.datasets.cifar10.load_data()

X_train = X_train.astype('float32') / 255.0
X_test  = X_test.astype('float32')  / 255.0

klassen = ['Flugzeug', 'Auto', 'Vogel', 'Katze', 'Reh',
           'Hund', 'Frosch', 'Pferd', 'Schiff', 'LKW']

# ── 2. Modell mit Data Augmentation ──────────────────────────────────────
model = keras.Sequential([
    # Data Augmentation (nur während Training aktiv)
    layers.RandomFlip('horizontal'),
    layers.RandomRotation(0.1),
    layers.RandomZoom(0.1),

    # Block 1
    layers.Conv2D(32, (3, 3), activation='relu', padding='same',
                  input_shape=(32, 32, 3)),
    layers.BatchNormalization(),
    layers.Conv2D(32, (3, 3), activation='relu', padding='same'),
    layers.MaxPooling2D((2, 2)),
    layers.Dropout(0.25),

    # Block 2
    layers.Conv2D(64, (3, 3), activation='relu', padding='same'),
    layers.BatchNormalization(),
    layers.Conv2D(64, (3, 3), activation='relu', padding='same'),
    layers.MaxPooling2D((2, 2)),
    layers.Dropout(0.25),

    # Block 3
    layers.Conv2D(128, (3, 3), activation='relu', padding='same'),
    layers.BatchNormalization(),
    layers.MaxPooling2D((2, 2)),
    layers.Dropout(0.25),

    # Klassifikationskopf
    layers.Flatten(),
    layers.Dense(256, activation='relu'),
    layers.BatchNormalization(),
    layers.Dropout(0.5),
    layers.Dense(10, activation='softmax')
])

model.compile(
    optimizer=keras.optimizers.Adam(learning_rate=0.001),
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy']
)

# ── 3. Trainieren ─────────────────────────────────────────────────────────
callbacks = [
    keras.callbacks.EarlyStopping(monitor='val_accuracy', patience=10,
                                   restore_best_weights=True),
    keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=5)
]

history = model.fit(
    X_train, y_train,
    epochs=50,
    batch_size=64,
    validation_split=0.1,
    callbacks=callbacks
)

# ── 4. Evaluieren ─────────────────────────────────────────────────────────
test_loss, test_acc = model.evaluate(X_test, y_test, verbose=0)
print(f"Test Accuracy: {test_acc:.2%}")

# ── 5. Einzelne Vorhersagen anzeigen ──────────────────────────────────────
y_pred = np.argmax(model.predict(X_test[:16]), axis=1)

fig, axes = plt.subplots(2, 8, figsize=(14, 4))
for i, ax in enumerate(axes.flat):
    ax.imshow(X_test[i])
    farbe = 'green' if y_pred[i] == y_test[i][0] else 'red'
    ax.set_title(klassen[y_pred[i]], color=farbe, fontsize=8)
    ax.axis('off')
plt.suptitle('CIFAR-10 Vorhersagen (grün=richtig, rot=falsch)')
plt.tight_layout()
plt.show()

11. Optimierer im Vergleich

11.1 SGD mit Momentum

Momentum „merkt" sich die Richtung der letzten Updates und beschleunigt das Training in konsistenten Richtungen:

optimizer = keras.optimizers.SGD(learning_rate=0.01, momentum=0.9)

11.2 Adam

Adam (Adaptive Moment Estimation) ist der Standard-Optimierer für Deep Learning. Er passt die Lernrate automatisch für jeden Parameter an:

optimizer = keras.optimizers.Adam(learning_rate=0.001)   # Standard

11.3 Vergleich

Optimierer Lernrate Konvergenz Wann einsetzen
SGD Manuell Langsam, stabil Wenn man Kontrolle will
SGD + Momentum Manuell Schneller CNNs, fine-tuning
Adam Adaptiv Schnell Standard, fast immer
RMSprop Adaptiv Gut Rekurrente Netze

12. Transfer Learning

12.1 Grundidee

Große vortrainierte Netze (z.B. VGG16, ResNet, MobileNet) wurden auf Millionen von Bildern trainiert und haben dabei gelernt, allgemeine Bildmerkmale zu erkennen (Kanten, Formen, Texturen). Dieses Wissen können wir wiederverwenden.

Vortrainiertes Netz (ImageNet, 1.000 Klassen)
        │
        ├── Frühe Schichten:  allgemeine Merkmale (Kanten, Texturen)
        ├── Mittlere Schichten: komplexere Formen
        └── Späte Schichten:  aufgabenspezifische Merkmale

Transfer Learning:
  1. Vortrainiertes Netz laden
  2. Letzte Schichten einfrieren (freeze)
  3. Neuen Klassifikationskopf hinzufügen
  4. Nur den Kopf trainieren (wenige Epochen)

12.2 Implementierung mit MobileNetV2

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

# ── 1. Basis-Modell laden (ohne Klassifikationskopf) ─────────────────────
base_model = keras.applications.MobileNetV2(
    input_shape=(96, 96, 3),
    include_top=False,          # Ohne letzten Dense-Schichten
    weights='imagenet'          # Vortrainierte Gewichte laden
)

# Basis-Modell einfrieren
base_model.trainable = False

# ── 2. Neuen Kopf hinzufügen ──────────────────────────────────────────────
inputs = keras.Input(shape=(96, 96, 3))
x = keras.applications.mobilenet_v2.preprocess_input(inputs)
x = base_model(x, training=False)
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.3)(x)
outputs = layers.Dense(10, activation='softmax')(x)   # 10 eigene Klassen

model = keras.Model(inputs, outputs)

# ── 3. Nur den Kopf trainieren ────────────────────────────────────────────
model.compile(
    optimizer=keras.optimizers.Adam(0.001),
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy']
)
# model.fit(X_train, y_train, epochs=10, ...)

# ── 4. Fine-Tuning: Obere Schichten des Basismodells freigeben ────────────
base_model.trainable = True

# Nur die letzten 20 Schichten trainieren
for layer in base_model.layers[:-20]:
    layer.trainable = False

model.compile(
    optimizer=keras.optimizers.Adam(1e-5),  # Sehr kleine Lernrate!
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy']
)
# model.fit(X_train, y_train, epochs=5, ...)

12.3 Wann Transfer Learning einsetzen?

Wenige eigene Daten + ähnliche Aufgabe  → Feature Extraction (Basis einfrieren)
Wenige eigene Daten + andere Aufgabe    → Transfer Learning + Fine-Tuning
Viele eigene Daten                      → Fine-Tuning oder eigenes Netz

13. Zusammenfassung und Ausblick

Überblick

Deep Learning
│
├── Grundbausteine
│     ├── Neuron:       z = wᵀx + b,  y = f(z)
│     ├── Aktivierung:  ReLU (standard), Sigmoid, Softmax
│     └── Loss:         Cross-Entropy (Klass.), MSE (Regr.)
│
├── Training
│     ├── Backpropagation + Gradientenabstieg
│     ├── Optimierer:   Adam (standard)
│     └── Regularisierung: Dropout, BatchNorm, Early Stopping
│
├── Architekturen
│     ├── MLP / Dense:  Tabellarische Daten
│     └── CNN:          Bilder, räumliche Daten
│
└── Fortgeschritten
      └── Transfer Learning: Vortrainierte Modelle wiederverwenden

Checkliste für ein Deep-Learning-Projekt

✅ Daten normalisieren (Pixel / 255 oder StandardScaler)
✅ Architektur zur Aufgabe wählen (Bilder → CNN, sonst MLP)
✅ Mit einfachem Modell beginnen, dann komplexer werden
✅ Dropout und BatchNorm gegen Overfitting einsetzen
✅ Early Stopping mit restore_best_weights aktivieren
✅ Trainingsverlauf (Loss + Accuracy) visualisieren
✅ Bei wenig Daten: Transfer Learning in Betracht ziehen
✅ Data Augmentation bei Bilddaten nutzen

Ausblick: Nächste Themen


Anhang: Schnellreferenz Keras

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

# ── Modell aufbauen ────────────────────────────────────────────────────────
model = keras.Sequential([
    layers.Dense(128, activation='relu', input_shape=(n_features,)),
    layers.Dropout(0.3),
    layers.Dense(64, activation='relu'),
    layers.Dense(n_classes, activation='softmax')   # oder 'sigmoid' für binär
])

# ── CNN-Block ──────────────────────────────────────────────────────────────
cnn_block = [
    layers.Conv2D(32, (3,3), activation='relu', padding='same'),
    layers.BatchNormalization(),
    layers.MaxPooling2D((2,2)),
    layers.Dropout(0.25),
]

# ── Kompilieren ────────────────────────────────────────────────────────────
model.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',  # Integer-Labels
    metrics=['accuracy']
)

# ── Trainieren ─────────────────────────────────────────────────────────────
history = model.fit(X_train, y_train,
                    epochs=50, batch_size=64,
                    validation_split=0.1,
                    callbacks=[
                        keras.callbacks.EarlyStopping(patience=5,
                            restore_best_weights=True)
                    ])

# ── Evaluieren und Vorhersagen ─────────────────────────────────────────────
loss, acc = model.evaluate(X_test, y_test)
y_pred_proba = model.predict(X_test)
y_pred       = y_pred_proba.argmax(axis=1)

# ── Modell speichern / laden ───────────────────────────────────────────────
model.save('mein_modell.keras')
model = keras.models.load_model('mein_modell.keras')

HTL Pinkafeld – IF/IT | Data Science & AI | 12. Schulstufe

Vorheriges ThemaUnsupervised Learning Nächstes ThemaNLP