| import sys |
| import os |
| import pandas as pd |
| import numpy as np |
| from pathlib import Path |
| from sklearn.ensemble import RandomForestRegressor |
| import pickle |
|
|
| |
| sys.path.append(str(Path(__file__).resolve().parent.parent)) |
|
|
|
|
| def train_model( |
| data_file: str = "training_data.csv", |
| model_out: str = "models/forecaster.pkl", |
| ): |
| data_path = Path(data_file) |
| if not data_path.exists(): |
| print(f"Data file {data_file} not found.") |
| return |
|
|
| print("Loading training data...") |
| df = pd.read_csv(data_path) |
|
|
| print("Engineering features...") |
| df = df.sort_values(["node_id", "tick"]) |
|
|
| |
| df["scenario_cat"] = df["scenario"].astype("category").cat.codes |
| df["weather_cat"] = df["weather"].astype("category").cat.codes |
|
|
| |
| for i in range(1, 6): |
| df[f"occ_lag_{i}"] = df.groupby("node_id")["fused_occupancy"].shift(i) |
|
|
| |
| df["target_15min"] = df.groupby("node_id")["fused_occupancy"].shift(-30) |
| df["target_30min"] = df.groupby("node_id")["fused_occupancy"].shift(-60) |
|
|
| df = df.dropna() |
|
|
| features = ( |
| ["fused_occupancy"] |
| + [f"occ_lag_{i}" for i in range(1, 6)] |
| + ["scenario_cat", "weather_cat"] |
| ) |
| targets = ["target_15min", "target_30min"] |
|
|
| X = df[features] |
| Y = df[targets] |
|
|
| print(f"Training Multi-output Random Forest on {len(df)} samples...") |
| model = RandomForestRegressor( |
| n_estimators=30, max_depth=10, n_jobs=-1, random_state=42 |
| ) |
| model.fit(X, Y) |
|
|
| print("Saving model and label encoders...") |
| scenario_mapping = { |
| val: i |
| for i, val in enumerate( |
| df["scenario"].astype("category").cat.categories |
| ) |
| } |
| weather_mapping = { |
| val: i |
| for i, val in enumerate( |
| df["weather"].astype("category").cat.categories |
| ) |
| } |
|
|
| out_path = Path(model_out) |
| out_path.parent.mkdir(parents=True, exist_ok=True) |
|
|
| with open(out_path, "wb") as f: |
| pickle.dump( |
| { |
| "model": model, |
| "scenario_mapping": scenario_mapping, |
| "weather_mapping": weather_mapping, |
| "features": features, |
| }, |
| f, |
| ) |
|
|
| print(f"Model saved to {model_out}") |
|
|
|
|
| if __name__ == "__main__": |
| train_model() |
|
|