Skip to content

feat: hyperparameter tuning voor XGBoost en SARIMA modellen #111

@Muhammet369

Description

@Muhammet369

Probleem

Beide ML-modellen draaien op hardcoded defaults zonder enige vorm van tuning:

XGBoost Classifier (src/models/xgboost_classifier.py:33):

model = XGBClassifier(objective="binary:logistic", eval_metric="auc")

Alle hyperparameters (max_depth, n_estimators, learning_rate, subsample, etc.) staan op XGBoost defaults. Er is geen early stopping of evaluatie op een validatieset.

XGBoost Regressor (src/models/xgboost_regressor.py:56):

model = XGBRegressor(learning_rate=0.25)

Alleen learning_rate is handmatig ingesteld (0.25 is agressief), rest is default.

SARIMA (src/models/sarima.py:178-180):

if programme.startswith("B") and predict_week in [17,18,19,20,21]:
    model = SARIMAForecaster(order=(1,0,1), seasonal_order=(1,1,1,52))
else:
    model = SARIMAForecaster(order=(1,0,1), seasonal_order=(1,1,0,52))

SARIMA-ordes zijn hardcoded en gekozen op basis van of de opleiding met "B" begint. Geen AIC/BIC-selectie, geen diagnostiek.

Impact

  • Model presteert waarschijnlijk suboptimaal (huidige gemiddelde MAPE ~14-15%)
  • Risico op overfitting zonder early stopping
  • Eén SARIMA-configuratie past niet op alle 54 combinaties (18 opleidingen × 3 herkomsten)

Voorstel

Fase 1: Quick wins (zonder grid search)

  1. Early stopping toevoegen aan beide XGBoost modellen:

    model.fit(X_train, y_train,
              eval_set=[(X_val, y_val)],
              early_stopping_rounds=10,
              verbose=False)
  2. Handmatige baseline-hyperparameters instellen op basis van domeinkennis:

    XGBClassifier(
        objective="binary:logistic",
        eval_metric="auc",
        n_estimators=300,
        max_depth=6,
        learning_rate=0.1,
        subsample=0.8,
        colsample_bytree=0.8,
        min_child_weight=5,
    )
  3. SARIMA: pmdarima.auto_arima gebruiken als fallback, of AIC-vergelijking van een beperkte set ordes per opleiding.

  4. Hyperparameters configureerbaar maken via configuration.json:

    "model_config": {
        "xgboost_classifier": {
            "max_depth": 6,
            "learning_rate": 0.1,
            "n_estimators": 300
        },
        "xgboost_regressor": {
            "max_depth": 5,
            "learning_rate": 0.1
        }
    }

Fase 2: Geautomatiseerde tuning (optioneel, met grid search)

  1. TimeSeriesSplit cross-validation (niet random k-fold — respecteert tijdsvolgorde):

    from sklearn.model_selection import TimeSeriesSplit
    tscv = TimeSeriesSplit(n_splits=3)
  2. RandomizedSearchCV (efficiënter dan grid search bij veel parameters):

    param_dist = {
        "max_depth": [3, 5, 7, 9],
        "learning_rate": [0.01, 0.05, 0.1, 0.2],
        "n_estimators": [100, 200, 500],
        "subsample": [0.7, 0.8, 0.9],
        "colsample_bytree": [0.7, 0.8, 1.0],
    }
  3. Resultaten loggen — beste parameters per run opslaan zodat ze vergelijkbaar zijn over tijd.

Acceptatiecriteria

  • XGBoost classifier en regressor gebruiken early stopping
  • Hyperparameters zijn configureerbaar via configuration.json
  • SARIMA-orde selectie is onderbouwd (AIC of auto_arima)
  • Modelprestatie (MAPE) verbetert of blijft gelijk t.o.v. huidige baseline
  • Tuning-resultaten worden gelogd naar dashboard of console-output

Referenties

  • Huidige MAPE: ~14% (ratio), ~15.5% (SARIMA cumulative) bij week 12
  • Bestanden: src/models/xgboost_classifier.py, src/models/xgboost_regressor.py, src/models/sarima.py

Metadata

Metadata

Assignees

Labels

Type

No fields configured for Task.

Projects

Status

In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions