# Portfolio Summary — Quito Traffic Jam
<!-- Interface-Datei: Wird von /project-case story befüllt.
     Einzige Zahlenquelle für /project-case report und /project-case slides.
     KEINE Inhalte aus Notebooks kopieren — nur kuratierte Kernaussagen.
-->

---

## Project

```
name:       Quito Traffic Jam
slug:       quito-traffic-jam
type:       DS
stage:      Abgeschlossen — Pipeline liefert, Abgabe-Vorhersage erzeugt und bewertet
target:     wait_sec — Sekunden, die ein Taxi während einer Fahrt im Stillstand steht
stack:      Python · pandas · scikit-learn · joblib · Matplotlib · Jupyter
period:     2016–2017
rows:       15.657 Fahrten Training · 1.566 Testset · 1.635 Zieldatenset
notebooks:  5
findings:   6
dashboard:  — (für dieses Projekt nicht gebaut)
```

---

## Storyline

```
thesis:     Die App kann Fahrgästen sagen, dass sie stehen werden — aber nicht auf die
            Sekunde. Die Aufgabe fragt, ob eine einfache lineare Regression mit 164,09 s
            Fehler zu unterbieten ist. Ja, um 15 % — und dann ist mit diesen Daten Schluss.
hook:       280 Modellvarianten von linearer Regression bis Gradient Boosting landen im
            selben Vier-Sekunden-Band. Nicht die Modelle sind am Ende, sondern die Daten.
proof:      Zielmarke 164,09 s → gebaute Pipeline 138,94 s auf einem Datensatz, dessen
            Werte während der Modellierung unbekannt waren → 280 Läufe konvergieren →
            Route und Verkehrslage fehlen in den Daten.
so_what:    Nicht weiter am Modell schrauben, sondern die Anzeige ehrlich machen: eine
            Spanne statt eines Sekundenwerts, und die fehlenden Signale beim
            Data-Engineering-Team anfragen.
```

---

## Problem

```
kpi_name:   MAE der Wartezeit-Prognose auf dem Zieldatenset
kpi_ist:    138,94 s (gebaute Pipeline)
kpi_soll:   164,09 s (Referenzwert aus der Aufgabenstellung)
kpi_gap:    −25,15 s bzw. −15,3 %
problem_statement: |
  Eine Taxi-App in Quito will Fahrgästen vorab sagen, wie lange sie auf der Fahrt im
  Stillstand stehen werden — damit sie sich einstellen können und die Fahrt positiver
  erleben. Für das Unternehmen sind Staufahrten zusätzlich unattraktiv, weil nach Strecke
  abgerechnet wird und nicht nach Zeit. Die Aufgabenstellung nennt einen Referenzwert, den
  es zu unterbieten gilt: eine einfache lineare Regression erreicht 164,09 s mittleren
  absoluten Fehler bei einem R² von 0,08.
```

---

## Key Findings

### F1 — Die Zielmarke ist unterboten
```
finding:   Die gebaute Pipeline schlägt den Referenzwert der Aufgabe deutlich und den
           ersten eigenen Anlauf ebenfalls — bewertet auf einem Datensatz, dessen echte
           Werte während der Modellierung nicht vorlagen.
number:    138,94 s gegen 164,09 s Referenz und 152,61 s Erstversuch
source:    notebooks/05_pipeline.ipynb
```

### F2 — Bei 140 Sekunden ist Schluss, unabhängig vom Modell
```
finding:   280 Kombinationen aus 28 Feature-Sets und 10 Modellkonfigurationen landen im
           selben schmalen Band. Lineare Regression, SVR, Random Forest und Gradient
           Boosting trennen weniger als vier Sekunden.
number:    6 von 280 Läufen unter 145 s
source:    notebooks/04_evaluating.ipynb — Model Stability
```

### F3 — Die Daten kennen die Fahrt nicht, nur ihre Endpunkte
```
finding:   Stillstand entsteht auf einer bestimmten Strasse zu einer bestimmten Zeit.
           Der Datensatz enthält Start, Ziel und eine Fahrzeitschätzung — weder die
           gefahrene Route noch die Verkehrslage. Das erklärt das Plateau.
number:    52,7 s Gewinn über der Baseline, davon 28,5 s allein aus der vorhandenen
           Fahrzeitschätzung
source:    notebooks/04_evaluating.ipynb — Signal Ablation
```

### F4 — MAE ist nicht die Metrik, die das Produkt braucht
```
finding:   MAE wird vom Median minimiert, also ist die Hälfte aller Schätzungen zu
           niedrig. Ein auf das 80. Perzentil trainiertes Modell hat die schlechtere
           Kennzahl und hält seine Zusage deutlich häufiger.
number:    Zusage gehalten in 80,3 % statt 53,1 % der Fahrten
source:    notebooks/04_evaluating.ipynb — Quantile Trade-off
```

### F5 — Die Rangliste der Modelle ist Rauschen
```
finding:   Wiederholte Kreuzvalidierung zeigt eine Streuung, die grösser ist als die
           Abstände zwischen den besten Kandidaten. Validierung und Kreuzvalidierung
           küren unterschiedliche Sieger.
number:    ± 3 s Streuung bei unter 3 s Abstand in den Top 6
source:    notebooks/04_evaluating.ipynb — Model Stability
```

### F6 — Vierzehn konstruierte Features reichen
```
finding:   Das kompakte Feature-Set erreicht dasselbe wie der volle Satz. Zusätzliche
           Spalten wie Anbieter-Kennungen verdrängen Features, die tragen, statt etwas
           beizusteuern.
number:    14 Features 141,06 s gegen 21 Features 140,25 s; mit Anbieter-Kennungen 147,40 s
source:    notebooks/04_evaluating.ipynb — Feature Group Impact
```

---

## Model Results

```
algorithm:      GradientBoostingRegressor in TransformedTargetRegressor (log1p/expm1)
target:         wait_sec
metric:         MAE (Mean Absolute Error)
split_strategy: train_test_split(test_size=0.1, random_state=42) — laut Aufgabenstellung
train_rows:     14.091
test_rows:      1.566
aim_rows:       1.635
```

### Baseline Benchmark

| Modell | Logik | MAE | R² |
|---|---|---|---|
| Median | immer 222 s vorhersagen | 188,79 s | −0,085 |
| **Referenz der Aufgabe** | **lineare Regression mit Ausreisser-Entfernung** | **164,09 s** | **0,080 ← Ziel** |

### Model Progression

| Stand | Features | MAE Zieldatenset | R² | vs. Referenz |
|---|---|---|---|---|
| Median-Baseline | — | 188,79 s | −0,085 | +24,70 s |
| Referenz der Aufgabe | wenige | 164,09 s | 0,080 | — |
| Erstversuch (März 2026) | 14 | 152,61 s | 0,212 | −11,48 s |
| **Gebaute Pipeline (August 2026)** | **21** | **138,94 s** | **0,322** | **−25,15 s** |

```
best_model:     GradientBoosting, 300 Bäume, log1p-Ziel, 21 Features
best_metric:    138,94 s MAE auf dem Zieldatenset · 135,70 s auf dem vorgeschriebenen Testset
key_insight:    trip_estimated trägt 46,8 % der Feature Importance. Die vorhandene
                Fahrzeitschätzung ist das stärkste Signal — die konstruierten Features
                sind mit ihr grösstenteils redundant.
mbe:            Median-Residuum +8,90 s. Das mittlere Residuum von +59,69 s ist die
                Schiefe der Zielverteilung, nicht eine Drift des Modells.
```

---

## Figures

```yaml
result:
  - ../img/benchmark-scoreboard.png     # Zielmarke, Erstversuch, neue Pipeline
  - ../img/convergence-plateau.png      # 280 Läufe sortiert, Boden bei 140 s

exploration:
  - ../img/target-distribution.png      # Rechtsschiefe des Ziels, roh und nach log1p
  - ../img/wait-vs-distance.png         # Grundbeziehung Distanz zu Wartezeit

model:
  - ../img/feature-set-progression.png  # Bestes MAE je Feature-Set
  - ../img/log-target-effect.png        # Wirkung der Ziel-Transformation je Algorithmus
  - ../img/model-feature-matrix.png     # Modelle × Feature-Sets, Konvergenz
  - ../img/champion-feature-importance.png
  - ../img/signal-ablation.png          # woher das Signal kommt

method:
  - ../img/cv-uncertainty.png           # Streuung schluckt die Rangfolge
  - ../img/split-comparison.png         # zufälliger gegen temporalen Split
  - ../img/residual-diagnosis.png       # Schiefe gegen echte Drift
  - ../img/error-by-distance.png        # Fehler je Distanz-Quartil
  - ../img/quantile-tradeoff.png        # MAE gegen Quantil-Modell
```

---

## Recommendations

```
r1:
  title:  Als Spanne anzeigen, nicht als Sekundenwert
  detail: Bei 139 s mittlerem Fehler auf 228 s Median trägt eine Sekundenangabe eine
          Genauigkeit vor, die sie nicht hat. Ein Intervall, das mit der Fahrtdistanz
          breiter wird, bildet die Unsicherheit ab — der Fehler auf dem längsten Quartil
          ist mehr als doppelt so gross wie auf dem kürzesten.

r2:
  title:  Auf das 80. Perzentil optimieren statt auf den Mittelwert
  detail: Eine Zusage, die in der Hälfte der Fälle zu niedrig ausfällt, taugt nicht als
          Versprechen. Ein Quantil-Modell hält sie in vier von fünf Fahrten, bei
          schlechterer Kennzahl. Welche Zahl zählt, entscheidet der Anwendungsfall.

r3:
  title:  Fehlende Signale beim Data-Engineering-Team anfragen
  detail: Die Aufgabe stellt diese Frage ausdrücklich. Es fehlen die gefahrene Route, die
          Verkehrslage zum Fahrtzeitpunkt und die Strassenkategorie. Ohne sie ist das
          Plateau bei 140 s nicht zu unterschreiten, mit welchem Modell auch immer.

r4:
  title:  Mehrjährige Daten für eine belastbare Saison-Aussage
  detail: Vierzehn Monate reichen nicht, um Periode und Jahreszeit zu trennen. Ein
          temporaler Testabschnitt fällt zwangsläufig in eine Jahreszeit — in diesem Fall
          in eine ohne einen einzigen Regenzeit-Tag.
```

---

## Research Opportunities
<!-- VIEWS: storyview, techview -->

- **Getrennter Validierungssplit war nachträglich nötig.** Der erste Durchgang wählte das
  beste von 280 Modellen auf demselben Testset aus, auf dem er es berichtete. Nachgemessen
  kostete das 0,62 s beim zufälligen und 0,00 s beim temporalen Split — das Vorgehen war
  falsch, der Schaden gering, weil die Kandidaten stark korreliert sind.
- **Flughafenfahrten sind nicht auswertbar.** Nur 25 von 15.657 Fahrten berühren den
  Flughafen, obwohl die Aufgabenstellung ihn hervorhebt.
- **Das Tempolimit aus der Aufgabe blieb ungenutzt.** Die Bereinigung filtert bei 120 km/h
  und entfernt damit 2 Zeilen; das genannte Stadtlimit von 50 km/h beträfe 488.
- **Smearing-Korrektur nach der Rücktransformation** wurde nicht angewandt und wäre der
  saubere Weg, wenn statt des Medians der Erwartungswert gebraucht wird.

---

## Status

```
generated_by:    /project-case story
generated_at:    2026-08-29
summary_version: 2
portfolio_check: ✅ passed
report_html:     ❌ pending
slides_html:     ❌ pending
dashboard:       ❌ not deployed
```
