Multi-Target Demo II: Die MultiTask-Pipeline mit demo10-Daten

Diese Seite ist die aktualisierte Fassung des Multi-Task-Target-Demos. Sie steuert die komplette Pipeline direkt über die Klasse MultiTask aus spotforecast2.multitask.multi (Version >= 3.9.0 erforderlich, installiert über PyPI oder GitHub). Eine MultiTask-Instanz wird mit einer ConfigMulti und den Laufzeit-Parametern konstruiert; anschließend durchläuft sie die Pipeline-Schritte — Datenaufbereitung, Ausreißerbehandlung, Imputation, exogene Merkmale, Training, Prognose, Aggregation — und die Methode MultiTask.run() gibt das aggregierte Prediction-Package zurück, aus dem sich die Prognose als DataFrame entnehmen lässt.

Vorbereitung

Bereitstellen des DataFrames df aus dem mitgelieferten Demo-Datensatz demo10.csv (11 Zielreihen, stündlich, ca. zwei Jahre):

import warnings

from spotforecast2_safe.data.fetch_data import fetch_data, get_package_data_home

warnings.filterwarnings("ignore")

df = fetch_data(filename=str(get_package_data_home() / "demo10.csv"))
df.tail(3)
A B C D E F G H I J K
DateTime
2021-12-24 19:00:00+00:00 6779.905942 1914.575282 -188.785332 40.414701 -151.954372 1.890299 32.396494 10270.621206 24.670940 -159.680687 138.444384
2021-12-24 20:00:00+00:00 5214.307366 2594.522237 738.566203 290.816747 575.507812 -28.564654 44.652500 10715.139172 -108.974569 367.366066 180.618827
2021-12-24 21:00:00+00:00 5420.030788 3271.458407 147.249660 -32.572713 576.854449 -9.907991 46.299119 15585.949262 15.319324 -158.527425 -66.810962
Private Daten nicht in versionierten Seiten ausführen

Diese Seite wird versioniert, in CI gerendert und veröffentlicht — auch die _freeze/-Ausführungsergebnisse liegen im Repository. Eine Zelle, die gegen private Daten läuft, bettet deren Werte in die veröffentlichte Dokumentation ein. Für lokale Läufe mit privaten Daten (z. B. /Users/bartz/spotforecast2_data/demo10.csv) das folgende Muster ausschließlich in einem nicht versionierten Dokument (z. B. unter local/) verwenden; auf GitHub greift dann automatisch der mitgelieferte Demo-Datensatz:

from spotforecast2_safe.data.fetch_data import fetch_data, get_package_data_home

try:
    df = fetch_data(filename="/Users/bartz/spotforecast2_data/demo10.csv")
except FileNotFoundError:
    # Fallback auf den mitgelieferten Demo-Datensatz (z. B. für Tests auf GitHub)
    df = fetch_data(filename=str(get_package_data_home() / "demo10.csv"))

Konfiguration

Konfiguration der Parameter und des Cache-Verzeichnisses. Seit Version 3.9.0 werden Trainings- und Validierungsfenster als pd.Timedelta über die ConfigMulti-Felder train_size und delta_val gesetzt; die früheren Parameter train_days / val_days existieren nicht mehr. Alle weiteren Schlüsselwortargumente des MultiTask-Konstruktors werden als **overrides an config.set_params() weitergereicht — unbekannte Parameter führen zu einem expliziten ValueError statt zu stillem Ignorieren. Da diese **overrides die übergebene ConfigMulti direkt mutieren, legt jeder Task-Abschnitt unten eine eigene frische ConfigMulti an, damit sich Einstellungen nicht zwischen den Abschnitten vermischen.

import tempfile

import pandas as pd

CACHE_HOME = tempfile.mkdtemp()      # Demo: temporäres Cache-Verzeichnis
PROJECT_NAME = "demo10_run"
TRAIN_SIZE = pd.Timedelta(days=90)   # Produktion: pd.Timedelta(days=10 * 365)
DELTA_VAL = pd.Timedelta(days=31)
N_TRIALS_OPTUNA = 2                  # Produktion: 25
Note

Die Werte sind für eine schnell und offline rendernde Demo-Seite verkleinert. In Produktion: persistentes Cache-Verzeichnis (z. B. ~/.spotforecast2_cache/cache), train_size von zehn Jahren, 25 Optuna-Trials, und die hier deaktivierten Optionen use_exogenous_features / use_outlier_detection typischerweise eingeschaltet (Wetter-Features benötigen Netzzugriff).

Importieren der Pipeline-Klasse und ihrer Konfiguration:

from spotforecast2.multitask.multi import MultiTask
from spotforecast2_safe.configurator.config_multi import ConfigMulti

Production

Optuna

Tunen der Hyperparameter (wöchentlich):

cfg_optuna = ConfigMulti()
cfg_optuna.data_frame_name = PROJECT_NAME   # Projektname = Cache-/Modell-Namespace

mt_optuna = MultiTask(
    cfg_optuna,
    task="optuna",
    dataframe=df,
    cache_home=CACHE_HOME,
    log_level=40,
    # ab hier: **overrides, werden via config.set_params() gesetzt
    train_size=TRAIN_SIZE,
    delta_val=DELTA_VAL,
    n_trials_optuna=N_TRIALS_OPTUNA,
    use_exogenous_features=False,
    use_outlier_detection=False,
)

# Pipeline-Schritte in fester Reihenfolge:
mt_optuna.prepare_data()
mt_optuna.detect_outliers()
mt_optuna.impute()
mt_optuna.build_exogenous_features()
result_optuna = mt_optuna.run(show=False)

# MultiTask.run() liefert das aggregierte Prediction-Package;
# die Prognose liegt unter result_optuna["future_pred"]:
forecast_optuna = result_optuna["future_pred"].to_frame("forecast")
forecast_optuna.head()
forecast
2021-12-24 22:00:00+00:00 1998.730889
2021-12-24 23:00:00+00:00 1806.574009
2021-12-25 00:00:00+00:00 1735.236008
2021-12-25 01:00:00+00:00 1707.990166
2021-12-25 02:00:00+00:00 1698.098677

Lazy

Model-Fit und Prediction mit den besten Hyperparametern aus Optuna, ohne erneutes Tuning (täglich oder stündlich). Wurde die Optuna-Phase noch nicht ausgeführt, startet lazy automatisch mit den Standardparametern. Mit run(show=True) ließen sich zusätzlich interaktive Grafiken pro Ziel und für die Aggregation anzeigen; hier bleibt das mit run(show=False) ausgeschaltet, um die Seite schlank zu halten. Eine eigene frische ConfigMulti stellt sicher, dass keine Einstellungen aus dem Optuna-Abschnitt hereinlecken.

cfg_lazy = ConfigMulti()
cfg_lazy.data_frame_name = PROJECT_NAME

mt_lazy = MultiTask(
    cfg_lazy,
    task="lazy",
    dataframe=df,
    cache_home=CACHE_HOME,
    log_level=40,
    train_size=TRAIN_SIZE,
    delta_val=DELTA_VAL,
    use_exogenous_features=False,
    use_outlier_detection=False,
)

mt_lazy.prepare_data()
mt_lazy.detect_outliers()
mt_lazy.impute()
mt_lazy.build_exogenous_features()
result_lazy = mt_lazy.run(show=False)

forecast_lazy = result_lazy["future_pred"].to_frame("forecast")
forecast_lazy.head()
forecast
2021-12-24 22:00:00+00:00 1998.730889
2021-12-24 23:00:00+00:00 1806.574009
2021-12-25 00:00:00+00:00 1735.236008
2021-12-25 01:00:00+00:00 1707.990166
2021-12-25 02:00:00+00:00 1698.098677

Zusätzliche Tasks

Predict

Nur Vorhersage, ohne Tuning oder Fit. Die Schritte optuna oder lazy müssen bereits einmal gelaufen sein, damit die Modelle im Cache vorliegen (auto_save_models=True ist der Standard).

cfg_predict = ConfigMulti()
cfg_predict.data_frame_name = PROJECT_NAME

mt_predict = MultiTask(
    cfg_predict,
    task="predict",
    dataframe=df,
    cache_home=CACHE_HOME,
    log_level=40,
    # train_size / delta_val entfallen: predict fittet nicht neu
    use_exogenous_features=False,
    use_outlier_detection=False,
)

mt_predict.prepare_data()
mt_predict.detect_outliers()
mt_predict.impute()
mt_predict.build_exogenous_features()
result_predict = mt_predict.run(show=False)

forecast_predict = result_predict["future_pred"].to_frame("forecast")
forecast_predict.head()
forecast
2021-12-24 22:00:00+00:00 1998.730889
2021-12-24 23:00:00+00:00 1806.574009
2021-12-25 00:00:00+00:00 1735.236008
2021-12-25 01:00:00+00:00 1707.990166
2021-12-25 02:00:00+00:00 1698.098677

Clean

Löschen der Cache-Daten für das Projekt. Mit dry_run=True wird nur angezeigt, welche Dateien gelöscht würden, ohne sie tatsächlich zu entfernen.

cfg_clean = ConfigMulti()
cfg_clean.data_frame_name = PROJECT_NAME

mt_clean_dry = MultiTask(
    cfg_clean,
    task="clean",
    cache_home=CACHE_HOME,
    dry_run=True,
    log_level=40,
)
mt_clean_dry.run()   # dry_run=True: zeigt nur an, was gelöscht würde
[clean] Dry run — would delete: /tmp/tmp3poge5iz
  Would remove: logging
  Would remove: models
  Would remove: tuning_results
{'status': 'dry_run',
 'cache_dir': PosixPath('/tmp/tmp3poge5iz'),
 'deleted_items': ['logging', 'models', 'tuning_results']}
cfg_clean_real = ConfigMulti()
cfg_clean_real.data_frame_name = PROJECT_NAME

mt_clean = MultiTask(
    cfg_clean_real,
    task="clean",
    cache_home=CACHE_HOME,
    dry_run=False,
    log_level=40,
)
mt_clean.run()
[clean] Cache removed successfully: /tmp/tmp3poge5iz
{'status': 'success',
 'cache_dir': PosixPath('/tmp/tmp3poge5iz'),
 'deleted_items': ['logging', 'models', 'tuning_results']}

Dokumentation der Klasse MultiTask

Die vollständige API-Referenz mit allen Parametern, Pipeline-Methoden und weiteren Beispielen: multitask.MultiTask.