Skip to content

Repository files navigation

Wind Power Forecasting System

Dieses Projekt prognostiziert die Stromerzeugung einer Windkraftanlage mithilfe von Wetterdaten und Machine-Learning-Verfahren. Ziel war es, ein vollständiges End-to-End-System zu entwickeln – von der Datenbeschaffung über das Modelltraining bis hin zur produktionsreifen Bereitstellung in der Cloud.

Projektbeschreibung

Im Mittelpunkt des Projekts steht die Windkraftanlage AN Windenergie SWT-0.6-44 MK4 mit einer Nennleistung von 600 kW. Die Anlage befindet sich in einem Windpark an der A27 bei Bremen (Nabenhöhe 58 m, Rotordurchmesser 44 m, Baujahr 1997). Für die Vorhersage der Energieerzeugung werden historische ERA5-Reanalyse-Daten verwendet, die über die Open-Meteo-API bezogen werden.

Das Projekt bildet den gesamten Machine-Learning-Lebenszyklus ab und orientiert sich an modernen MLOps- und Software-Engineering-Standards.


Was wurde gebaut – Schritt für Schritt

Phase 0 – Projekt-Fundament

  • Git-Repository initialisiert, saubere Ordnerstruktur angelegt (data/, src/, notebooks/, tests/, models/)
  • Conda-Umgebung (wind, Python 3.11) mit versioniertem requirements.txt
  • config.yaml als zentrale Konfigurationsdatei: Turbinenparameter, Koordinaten, Zeitraum – kein Hardcoding von Werten im Code
  • Koordinaten der Anlage über Google Maps und OpenStreetMap kreuzvalidiert (53.1165290, 8.8298645)

Phase 1 – Datenbeschaffung (Ingestion)

  • src/ingest.py: Ruft historische Wetterdaten (2020–2025, stündlich, 52.608 Werte) von der Open-Meteo-API ab
  • Windgeschwindigkeit explizit in m/s angefordert (Standard der API ist km/h – ein klassischer Stolperstein, der durch einen Sanity-Check mit Plausibilitätsprüfung der Werte aufgedeckt wurde)
  • Rohdaten werden unverändert als zeitgestempelte JSON-Dateien in data/raw/ gespeichert – nie überschrieben, jederzeit reproduzierbar

Phase 2 – Transformation & Windphysik

  • src/transform.py: Umrechnung der Windgeschwindigkeit von Messhöhe (10 m/100 m) auf Nabenhöhe (58 m) mittels Power Law (Hellmann-Exponent), dynamisch pro Stunde berechnet aus den zwei verfügbaren Messhöhen
  • Randfälle (Windstille, führt zu unendlichem Exponenten) werden durch Median-Imputation robust behandelt – dokumentiert im Code, keine stille Datenkorruption
  • Bias-Korrektur: ERA5 unterschätzt die lokale Windgeschwindigkeit systematisch (Gitterauflösung ~9 km glättet lokale Effekte). Korrektur auf das Referenzmittel des Global Wind Atlas (6,2 m/s) mittels konstantem Faktor – Limitation transparent dokumentiert
  • Leistungskurve: Physikalisch hergeleitet aus der Windleistungsformel (P ∝ v³, Betz-Theorie), da keine Herstellerkurve verfügbar war. Cut-in-, Rated- und Cut-out-Bereiche berücksichtigt
  • Ergebnis: data/processed/dataset.parquet – ein sauberer, dokumentierter Datensatz mit Windgeschwindigkeit und Leistung

Phase 3 – Explorative Datenanalyse & Feature Engineering

  • Windverteilung folgt einer Weibull-Verteilung (rechtsschief, Mittelwert > Median)
  • Klare Saisonalität: Winterhalbjahr deutlich windreicher als Sommer (atlantische Tiefdruckgebiete vs. Azorenhoch)
  • src/features.py: Erzeugung von Lag-Features (t-1 bis t-48), Rolling-Statistiken (gleitender Mittelwert/Standardabweichung) und zyklisch kodierten Zeitmerkmalen (Sin/Cos für Stunde und Monat – verhindert, dass z. B. Dezember und Januar als maximal unähnlich behandelt werden)
  • Zielvariable: Leistung 24 Stunden in der Zukunft (target_24h)

Phase 4 – Modellierung (vier Ansätze im direkten Vergleich)

Chronologischer Train/Test-Split (2020–2024 Training, 2025 Test) – kein zufälliger Split, da dieser bei Zeitreihen zu Data Leakage führen würde.

Modell nMAE Bewertungsmethode
Persistence (naive Baseline) 17,74 % Statisch
Seasonal Naive 19,64 % Statisch
XGBoost (Gradient Boosting) 15,82 % Statisch
LSTM (Deep Learning, PyTorch) 15,65 % Statisch
SARIMA (klassische Zeitreihenstatistik) 13,69 % Walk-Forward (tägliches Update)

Wichtige Erkenntnis: SARIMA erzielte das beste Ergebnis, profitiert dabei aber vom Walk-Forward-Verfahren (tägliche Aktualisierung mit echten Beobachtungen). XGBoost und LSTM wurden statisch bewertet. Ein vollständig fairer Vergleich würde ein äquivalentes Update-Verfahren für alle Modelle erfordern – diese Einschränkung wird bewusst offengelegt statt verschwiegen.

Für alle Modelle wurde konsequent auf Data Leakage geachtet: zeitreihenkorrekte Kreuzvalidierung (TimeSeriesSplit), kein Blick in die Zukunft bei Rolling-Fenstern, getrennte Feature-Berechnung für Train und Test.

Phase 5 – Serving (produktionsreife Bereitstellung)

  • src/api.py: FastAPI-Service mit /predict- und /health-Endpunkt
  • Bewusste Modellwahl für das Serving: XGBoost statt SARIMA – trotz leicht schlechterem nMAE, da XGBoost zustandslos (stateless) ist und sich damit für eine einfache, skalierbare API eignet, während SARIMA ein tägliches Update-Verfahren benötigen würde
  • Kein Training-Serving-Skew: Die Feature-Berechnung im API-Endpunkt nutzt exakt dieselben Funktionen wie das Training (src/features.py) – Client muss nur Rohdaten (Windgeschwindigkeit, Leistung der letzten 48h) senden, keine internen Features
  • Automatisierte Tests (pytest) prüfen Health-Check, Plausibilität der Vorhersage und korrekte Fehlerbehandlung bei unvollständigen Eingaben
  • Containerisierung mit Docker: Eigene, minimale requirements-api.txt (ohne Jupyter/TensorFlow/W&B) für schlanke, schnelle Images

Deployment & Infrastruktur

  • AWS EC2 (Frankfurt, t2.micro, Free Tier): Docker-Container erfolgreich deployt und öffentlich erreichbar gemacht
  • CI/CD mit GitHub Actions: Bei jedem Push werden automatisch alle Tests in einer isolierten Ubuntu-Umgebung ausgeführt – Codequalität wird kontinuierlich abgesichert
  • Streamlit-Dashboard (src/dashboard.py): Interaktive Oberfläche, die live gegen die deployte API kommuniziert und die letzten 48 Stunden sowie die 24h-Prognose visualisiert
  • Nach erfolgreichem End-to-End-Test wurde die EC2-Instanz gestoppt, um Kosten zu vermeiden (Wiederinbetriebnahme jederzeit möglich)

Technischer Stack

Bereich Werkzeuge
Datenquelle Open-Meteo API (ERA5-Reanalyse)
Datenverarbeitung pandas, NumPy, PyArrow (Parquet)
Modellierung XGBoost, statsmodels (SARIMA), PyTorch (LSTM), scikit-learn
Experiment-Tracking TensorBoard
Serving FastAPI, Uvicorn, Pydantic
Containerisierung Docker
Cloud AWS EC2 (Free Tier)
CI/CD GitHub Actions, pytest
Dashboard Streamlit
Versionierung Git / GitHub

Projektstruktur

wind_power_forecast/
├── config.yaml              # Zentrale Konfiguration (Turbine, Zeitraum, Bias-Korrektur)
├── data/
│   ├── raw/                  # Unveränderte Rohdaten (zeitgestempelt)
│   └── processed/            # Verarbeitete Datensätze (Parquet)
├── src/
│   ├── config.py              # Lädt config.yaml
│   ├── ingest.py               # Datenabruf von Open-Meteo
│   ├── transform.py            # Windphysik, Bias-Korrektur, Leistungskurve
│   ├── features.py             # Feature Engineering (Lags, Rolling, zyklische Zeit)
│   ├── baseline.py             # Naive Baselines, Zeitsplit, nMAE-Metrik
│   ├── train_xgboost.py         # XGBoost-Training mit TimeSeriesSplit
│   ├── sarima.py                # SARIMA mit Walk-Forward-Evaluierung
│   ├── train_lstm.py            # LSTM-Training (PyTorch)
│   ├── api.py                   # FastAPI-Service
│   └── dashboard.py             # Streamlit-Dashboard
├── tests/                    # Automatisierte Tests (pytest)
├── notebooks/                # Explorative Datenanalyse
├── models/                   # Trainierte Modelle, Grafiken
├── Dockerfile                 # Container-Definition für die API
└── .github/workflows/         # CI-Pipeline

Wichtigste methodische Prinzipien

  • Reproduzierbarkeit: Rohdaten werden nie verändert, jeder Verarbeitungsschritt ist eine reine Funktion, die aus den Rohdaten neu ausgeführt werden kann
  • Kein Data Leakage: Chronologischer Split, zeitreihenkorrekte Kreuzvalidierung, Feature-Fenster ohne Blick in die Zukunft
  • Ehrliche Modellbewertung: Jede Limitation (Bias-Korrektur, Walk-Forward-Vorteil von SARIMA, idealisierter Kapazitätsfaktor) wird offen dokumentiert statt verschwiegen
  • Trennung von Exploration und Produktion: Notebooks für Exploration, src/-Module für wiederverwendbaren, testbaren, produktionsreifen Code
  • Kein Training-Serving-Skew: Identische Funktionen für Feature-Berechnung in Training und API

Limitationen

  • Der berechnete Kapazitätsfaktor (~22 %) ist eine idealisierte Obergrenze ohne Verfügbarkeitsverluste, Wake-Effekte oder reale, windabhängige Cp-Kurve
  • Die Bias-Korrektur nutzt einen konstanten Faktor, der nur das Mittel, nicht die Form der Windverteilung korrigiert
  • Der Modellvergleich in Phase 4 ist nicht vollständig fair, da SARIMA von Walk-Forward-Updates profitiert, während XGBoost und LSTM statisch bewertet wurden

Status

Alle Phasen (0–5) sowie Deployment, Dashboard und CI/CD sind abgeschlossen. Das System wurde erfolgreich End-to-End getestet: von der Datenbeschaffung bis zur öffentlich erreichbaren, containerisierten API in der Cloud.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages