Das Problem: ML ist mehr als Modellierung

Viele ML-Projekte scheitern nicht an schlechten Modellen, sondern an falschen Fragestellungen:

  • Falsche Metrik optimiert: Accuracy auf unbalancierten Daten ist irreführend
  • Stakeholder ignoriert: Das Safety-Team hat andere Prioritäten als das Product-Team
  • Fehlerkosten nicht berücksichtigt: Ein übersehenes Stop-Schild ist kritischer als ein verwechseltes Speed-Limit
  • Evaluation oberflächlich: 95% Accuracy versteckt 50% Fehlerrate auf seltenen Klassen

Warum Traffic Sign Recognition?

Verkehrsschilderkennung ist ein perfektes Lehrbeispiel:

Herausforderung Relevanz
43 Klassen Multi-Class Classification
Klassenimbalance 10x Unterschied zwischen häufigen und seltenen Schildern
Ähnliche Klassen Speed Limits unterscheiden sich nur in Zahlen
Safety-kritisch Übersehenes Stop-Schild = potentieller Unfall
Reale Variationen Beleuchtung, Blur, Verdeckung

Die Lösung: Interaktives ML-Pipeline Dashboard

Ein Streamlit-Dashboard, das den kompletten ML-Workflow lehrt – vom Problem Framing bis zur Fehleranalyse.

Architektur

┌─────────────────────────────────────────────────────────────────┐
│                    GTSRB ML PIPELINE                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐              │
│  │   Problem   │  │    Data     │  │   Dataset   │              │
│  │   Framing   │──│ Exploration │──│    Split    │              │
│  └─────────────┘  └─────────────┘  └─────────────┘              │
│         │                │                │                      │
│         ▼                ▼                ▼                      │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  Stakeholder    Klassen-        Stratified              │    │
│  │  Analyse        Verteilung      vs Random               │    │
│  │                                                          │    │
│  │  Metrik-        Daten-          Data Leakage            │    │
│  │  Auswahl        Challenges      Prevention              │    │
│  │                                                          │    │
│  │  Success        Sample          Cross-                  │    │
│  │  Criteria       Browser         Validation              │    │
│  └─────────────────────────────────────────────────────────┘    │
│         │                                                        │
│         ▼                                                        │
│  ┌─────────────┐  ┌─────────────┐                               │
│  │   Model     │  │ Evaluation  │                               │
│  │  Training   │──│  & Errors   │                               │
│  └─────────────┘  └─────────────┘                               │
│         │                │                                       │
│         ▼                ▼                                       │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │  CNN mit         Confusion      Misclassified           │    │
│  │  BatchNorm       Matrix         Examples                │    │
│  │                                                          │    │
│  │  Class           Per-Class      Critical                │    │
│  │  Weights         Metrics        Classes                 │    │
│  │                                                          │    │
│  │  Training        Error          Confused                │    │
│  │  Curves          Analysis       Pairs                   │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Seite 1: Problem Framing

Kernfrage: Wer nutzt das Modell und was ist ihnen wichtig?

Stakeholder-Analyse

┌─────────────────────────────────────────────────────────────────┐
│  STAKEHOLDER PRIORITIES                                          │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  👤 Vehicle Safety Team                                          │
│  ├─ Priorität: Keine übersehenen kritischen Schilder            │
│  ├─ Metrik: Recall auf Stop, No Entry, Yield                    │
│  └─ Risikotoleranz: Niedrig – Safety First                      │
│                                                                  │
│  👤 Product Team                                                 │
│  ├─ Priorität: Balance zwischen Genauigkeit und Performance     │
│  ├─ Metrik: F1-Score, Inference Time                            │
│  └─ Risikotoleranz: Mittel – User Experience                    │
│                                                                  │
│  👤 Regulatory / Homologation                                    │
│  ├─ Priorität: Nachweisbare Mindestanforderungen                │
│  ├─ Metrik: Per-Class Accuracy Thresholds                       │
│  └─ Risikotoleranz: Keine – Muss Standards erfüllen             │
│                                                                  │
│  👤 ML Engineering Team                                          │
│  ├─ Priorität: Robustheit und Wartbarkeit                       │
│  ├─ Metrik: Cross-Validation Stabilität, Kalibrierung           │
│  └─ Risikotoleranz: Mittel – Technical Debt                     │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Metrik-Auswahl

Metrik Formel Wann nutzen? Limitation
Accuracy (TP+TN)/Total Balancierte Daten Irreführend bei Imbalance
Precision TP/(TP+FP) False Positives sind teuer Ignoriert False Negatives
Recall TP/(TP+FN) False Negatives sind teuer Ignoriert False Positives
F1-Score 2×(P×R)/(P+R) Balance zwischen P und R Ignoriert True Negatives
Macro F1 Ø F1 aller Klassen Alle Klassen gleich wichtig Seltene Klassen übergewichtet

Kritische Klassen identifizieren

🔴 SAFETY-KRITISCH (hoher Recall erforderlich):
   - Klasse 14: Stop
   - Klasse 17: No Entry
   - Klasse 13: Yield
   - Klasse 1:  Speed Limit 30 (Schulzonen)

🟡 VERWECHSLUNGSGEFAHR (oft konfundiert):
   - Klassen 0-8: Speed Limits (nur Zahlen unterscheiden sich)
   - Klassen 33-37: Richtungspfeile (ähnliche Muster)

Seite 2: Data Exploration

Kernfrage: Welche Herausforderungen stecken in den Daten?

Klassenverteilung

Samples pro Klasse:
┌────────────────────────────────────────────────────────────────┐
│ Klasse 2 (50 km/h)     ████████████████████████████  2250     │
│ Klasse 1 (30 km/h)     ████████████████████████████  2220     │
│ Klasse 38 (Keep right) ████████████████████████████  2070     │
│ ...                                                            │
│ Klasse 0 (20 km/h)     ███                            210     │
│ Klasse 19 (Curve left) ███                            210     │
│ Klasse 37 (Go left)    ███                            210     │
└────────────────────────────────────────────────────────────────┘

Imbalance Ratio: 10.7x (2250 vs 210 Samples)

Daten-Challenges

Challenge Problem Mitigation
Klassenimbalance Modell ignoriert seltene Klassen Class Weights, Oversampling
Beleuchtungsvarianz Dunkel/Hell/Gegenlicht Data Augmentation
Motion Blur Bewegungsunschärfe Blur Augmentation
Partielle Verdeckung Äste, andere Schilder Cutout Augmentation
Ähnliche Klassen Speed Limits fast identisch Hard Example Mining

Seite 3: Dataset Split

Kernfrage: Wie organisiere ich Daten, um Overfitting zu vermeiden?

Die drei Splits

┌─────────────────────────────────────────────────────────────────┐
│                                                                  │
│  TRAINING SET (60-80%)                                          │
│  └─ Modell lernt Muster                                         │
│                                                                  │
│  VALIDATION SET (10-20%)                                        │
│  └─ Hyperparameter tunen (Epochs, Learning Rate, etc.)          │
│                                                                  │
│  TEST SET (10-20%)                                              │
│  └─ Finale Evaluation – NUR EINMAL verwenden!                   │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Stratification bei Imbalance

OHNE Stratification:              MIT Stratification:
┌──────────────────────┐          ┌──────────────────────┐
│ Train: 60% Klasse A  │          │ Train: 50% Klasse A  │
│ Val:   80% Klasse A  │  ←BAD    │ Val:   50% Klasse A  │  ←GOOD
│ Test:  40% Klasse A  │          │ Test:  50% Klasse A  │
└──────────────────────┘          └──────────────────────┘

Ohne Stratification kann die Validation Set Verteilung
stark von der Training Set Verteilung abweichen!

Data Leakage vermeiden

❌ FALSCH:
   1. Alle Daten normalisieren
   2. Dann splitten
   → Test Set "sieht" Training-Statistiken

✅ RICHTIG:
   1. Erst splitten
   2. Nur Training Set Statistiken berechnen
   3. Diese auf Val/Test anwenden

Seite 4: Model Training

Kernfrage: Wie trainiere ich ein Modell, das generalisiert?

Modell-Auswahl

Nutzer können zwischen drei Modelltypen wählen:

┌─────────────────────────────────────────────────────────────────┐
│  MODELL-VERGLEICH                                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  📊 Logistic Regression                                          │
│  ├─ Komplexität: Niedrig                                        │
│  ├─ Training: Schnell (Sekunden)                                │
│  ├─ Funktionsweise: Lineare Entscheidungsgrenzen               │
│  └─ Best für: Baseline, schnelle Experimente                    │
│                                                                  │
│  📈 Polynomial Regression                                        │
│  ├─ Komplexität: Mittel                                         │
│  ├─ Training: Mittel (Minuten)                                  │
│  ├─ Funktionsweise: PCA + Polynomiale Features + Linear        │
│  └─ Best für: Nicht-lineare Muster ohne Deep Learning          │
│                                                                  │
│  🧠 Neural Network (CNN)                                         │
│  ├─ Komplexität: Hoch                                           │
│  ├─ Training: Langsam (Minuten-Stunden)                         │
│  ├─ Funktionsweise: Lernt hierarchische Features automatisch   │
│  └─ Best für: Beste Genauigkeit, Bildklassifikation            │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

CNN Architektur

Input: 32×32×3 RGB
    │
    ▼
┌─────────────────────────────────┐
│ Conv Block 1                    │
│ Conv2d(3→32) + BN + ReLU       │
│ Conv2d(32→32) + BN + ReLU      │
│ MaxPool(2×2) + Dropout(0.25)   │
└─────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────┐
│ Conv Block 2                    │
│ Conv2d(32→64) + BN + ReLU      │
│ Conv2d(64→64) + BN + ReLU      │
│ MaxPool(2×2) + Dropout(0.25)   │
└─────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────┐
│ Conv Block 3                    │
│ Conv2d(64→128) + BN + ReLU     │
│ Conv2d(128→128) + BN + ReLU    │
│ MaxPool(2×2) + Dropout(0.25)   │
└─────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────┐
│ Classifier                      │
│ Flatten                         │
│ Linear(2048→512) + BN + ReLU   │
│ Dropout(0.5)                    │
│ Linear(512→43)                  │
└─────────────────────────────────┘
    │
    ▼
Output: 43 Klassen

Class Weights für Imbalance

# Problem: Seltene Klassen werden ignoriert
# Lösung: Höheres Gewicht für seltene Klassen

class_counts = [2250, 2220, ..., 210, 210]  # Samples pro Klasse
class_weights = 1.0 / class_counts          # Inverse Häufigkeit
class_weights = normalize(class_weights)    # Normalisieren

# CrossEntropyLoss mit Gewichten
criterion = nn.CrossEntropyLoss(weight=class_weights)

Seite 5: Evaluation

Kernfrage: Wo versagt das Modell und warum?

Confusion Matrix

                    PREDICTED
                 0   1   2   3   ...
              ┌───┬───┬───┬───┬─────┐
           0  │95%│ 3%│ 1%│ 1%│     │  ← Speed 20
    T      1  │ 5%│90%│ 3%│ 2%│     │  ← Speed 30
    R      2  │ 2%│ 4%│92%│ 2%│     │  ← Speed 50
    U      3  │ 1%│ 2%│ 3%│93%│     │  ← Speed 60
    E      ...│   │   │   │   │     │
              └───┴───┴───┴───┴─────┘

Speed Limits werden oft untereinander verwechselt!

Per-Class Metrics

Klasse  Precision  Recall  F1-Score  Support
──────────────────────────────────────────────
0       0.89       0.78    0.83      60
1       0.94       0.96    0.95      720
2       0.95       0.97    0.96      750
...
14      0.98       0.99    0.99      270    ← Stop (kritisch!)
17      0.97       0.98    0.98      360    ← No Entry (kritisch!)
...
19      0.72       0.65    0.68      60     ← Schwach!
37      0.75       0.70    0.72      60     ← Schwach!

Error Analysis

TOP VERWECHSLUNGSPAARE:
┌─────────────────────────────────────────────────────────────────┐
│ Speed 30 → Speed 50        │ 45 Fehler │ Gleiche Kategorie     │
│ Speed 50 → Speed 30        │ 38 Fehler │ Gleiche Kategorie     │
│ Speed 70 → Speed 80        │ 32 Fehler │ Gleiche Kategorie     │
│ Turn right → Go straight   │ 12 Fehler │ ⚠️ Cross-Category!   │
│ Yield → Priority           │  8 Fehler │ ⚠️ Cross-Category!   │
└─────────────────────────────────────────────────────────────────┘

Cross-Category Fehler sind kritischer als Same-Category Fehler!

Technische Umsetzung

Tech Stack

Komponente Technologie
Frontend Streamlit
Visualisierung Plotly
ML Framework PyTorch
Data Processing NumPy, Pandas, scikit-learn
Dataset GTSRB (43 Klassen, 51k Bilder)

Key Features

  • Demo Mode: Funktioniert ohne echten Datensatz
  • Interaktiv: Hyperparameter live anpassen
  • Visuell: Alle Konzepte mit Grafiken erklärt
  • Educational: Best Practices und Anti-Patterns

Key Takeaways

Problem Framing

  1. Stakeholder zuerst – Verschiedene Nutzer haben verschiedene Prioritäten
  2. Accuracy ist nicht alles – Besonders bei unbalancierten Daten
  3. Fehlerkosten berücksichtigen – Manche Fehler sind teurer als andere

Data Handling

  1. Imbalance behandeln – Class Weights, Stratification
  2. Splits respektieren – Test Set ist heilig
  3. Data Leakage vermeiden – Split vor Preprocessing

Evaluation

  1. Per-Class analysieren – Gesamtmetriken verstecken Probleme
  2. Confusion Matrix studieren – Zeigt Fehlermuster
  3. Echte Fehler anschauen – Bilder zeigen das “Warum”

Tech Stack: PyTorch, Streamlit, Plotly, scikit-learn

Dataset: German Traffic Sign Recognition Benchmark (GTSRB)


Interesse am Code? GitHub Repository