diff --git a/train_model_linux.py b/train_model_linux.py index 26ab402..de5764d 100644 --- a/train_model_linux.py +++ b/train_model_linux.py @@ -4,7 +4,7 @@ import holidays import xgboost as xgb from sklearn.metrics import mean_absolute_error -print("Start training Model 1.5...") +print("Start training Model 1.5 for Linux...") # --- 1. DATA LADEN --- # We gebruiken de CSV die we al hadden @@ -83,7 +83,7 @@ xgb_model_v1_5 = xgb.XGBRegressor( early_stopping_rounds=50 ) -print("\nModel v1.5 aan het trainen...") +print("\nModel v1.5 for Linux aan het trainen...") xgb_model_v1_5.fit( X_train, y_train, eval_set=[(X_test, y_test)], @@ -97,6 +97,6 @@ mae_v1_5 = mean_absolute_error(y_test, voorspellingen_v1_5) print(f"\nNieuwe Model (v1.5) MAE: {mae_v1_5:.4f}") # --- 7. MODEL OPSLAAN --- -MODEL_FILE = 'price_forecast_model_v1_5.json' +MODEL_FILE = 'price_forecast_model_1.5.linux.json' xgb_model_v1_5.save_model(MODEL_FILE) print(f"\nModel 1.5 opgeslagen als: {MODEL_FILE}") \ No newline at end of file diff --git a/voorspel_advanced_linux.py b/voorspel_advanced_linux.py new file mode 100644 index 0000000..4df5638 --- /dev/null +++ b/voorspel_advanced_linux.py @@ -0,0 +1,180 @@ +import pandas as pd +import numpy as np +import xgboost as xgb +import mysql.connector +from mysql.connector import Error +from datetime import datetime, timedelta +import holidays # NIEUW: importeer holidays + +# --- CONFIGURATIE --- +# BELANGRIJK: Verwijs naar je NIEUWE model +MODEL_FILE = 'price_forecast_model_1.5.linux.json' +TARGET = 'gemiddelde_prijs' +AANTAL_UUR_VOORSPELLEN = 72 # Hoeveel uur vooruit wil je kijken? + +DB_CONFIG = { + 'host': '192.168.178.201', + 'user': 'energy_prices_user', + 'password': 'kS9R*xp17ZwCD@CV&E^N', + 'database': 'energy_prices', + 'port': 3307 +} + +# NIEUW: Haal de lijst van features uit je model +# We hoeven de lijst niet meer handmatig te typen! +try: + print(f"Laden van model: {MODEL_FILE}...") + model = xgb.XGBRegressor() + model.load_model(MODEL_FILE) + FEATURES = model.feature_names_in_ # Pakt automatisch alle feature-namen + print(f"āœ… Model succesvol geladen (verwacht {len(FEATURES)} features).") +except FileNotFoundError: + print(f"āŒ Fout: Model bestand '{MODEL_FILE}' niet gevonden.") + print("Heb je het 'v1_5 (linux)' model al getraind en opgeslagen?") + exit() +except Exception as e: + print(f"āŒ Fout bij laden model: {e}") + exit() + +# Maak de feestdagen-checker klaar +nl_holidays = holidays.Netherlands(years=[datetime.now().year, datetime.now().year + 1]) + + +def haal_data_uit_database(conn): + # ... (Deze functie is 100% IDENTIEK aan je vorige script) + # ... (Kopieer de 'haal_data_uit_database' functie hier) + print("šŸ’¾ Data ophalen uit MySQL...") + + query_hist = """ + SELECT + w.datum_tijd, w.temperatuur, w.gevoelstemperatuur, w.neerslag, + w.wind_richting, w.wind_snelheid, w.bewolking, w.luchtdruk, w.luchtvochtigheid, + p_avg.gemiddelde_prijs + FROM + amersfoort_weer_uurlijks AS w + LEFT JOIN -- <--- DE OPLOSSING + (SELECT datetime, AVG(price) AS gemiddelde_prijs + FROM dynamic_price_data GROUP BY datetime) AS p_avg + ON w.datum_tijd = p_avg.datetime + WHERE + w.datum_tijd BETWEEN (UTC_TIMESTAMP() - INTERVAL 30 HOUR) AND UTC_TIMESTAMP() + ORDER BY + w.datum_tijd; + """ + + query_toekomst = f""" + SELECT + datum_tijd, temperatuur, gevoelstemperatuur, neerslag, + wind_richting, wind_snelheid, bewolking, luchtdruk, luchtvochtigheid, + NULL AS gemiddelde_prijs + FROM + amersfoort_weer_uurlijks + WHERE + datum_tijd BETWEEN UTC_TIMESTAMP() AND (UTC_TIMESTAMP() + INTERVAL {AANTAL_UUR_VOORSPELLEN} HOUR) + ORDER BY + datum_tijd; + """ + + try: + hist_df = pd.read_sql(query_hist, conn, index_col='datum_tijd', parse_dates=['datum_tijd']) + toekomst_df = pd.read_sql(query_toekomst, conn, index_col='datum_tijd', parse_dates=['datum_tijd']) + + print(f"āœ… {len(hist_df)} uur historie geladen.") + print(f"āœ… {len(toekomst_df)} uur toekomstig weer geladen.") + + # --- OPLOSSING HIER --- + # Vul 'gaten' in de historische prijsdata ALLEEN op hist_df + hist_df['gemiddelde_prijs'] = hist_df['gemiddelde_prijs'].ffill() + hist_df['gemiddelde_prijs'] = hist_df['gemiddelde_prijs'].bfill() + # --- EINDE OPLOSSING --- + + # Combineer nu de gevulde historie met de lege toekomst + combined_df = pd.concat([hist_df, toekomst_df]) + + return combined_df.sort_index() + + except Exception as e: + print(f"āŒ Fout bij ophalen data: {e}") + return None + + +def maak_features_voor_uur(df, timestamp): + """ + MAAK FEATURES v1.5 - Deze functie is compleet VERNIEUWD + """ + features = {} + + # Haal data op van het specifieke uur + data_nu = df.loc[timestamp] + + # 1. Tijd-features (simpel) + features['maand'] = timestamp.month + features['dag_van_het_jaar'] = timestamp.dayofyear + + # 2. Feestdag feature + features['is_feestdag'] = 1 if timestamp in nl_holidays else 0 + + # 3. Weer-features + weer_cols = ['temperatuur', 'gevoelstemperatuur', 'neerslag', 'wind_richting', + 'wind_snelheid', 'bewolking', 'luchtdruk', 'luchtvochtigheid'] + for col in weer_cols: + features[col] = data_nu[col] + + # 4. Lag-features + features['prijs_1u_geleden'] = df.loc[timestamp - timedelta(hours=1)]['gemiddelde_prijs'] + features['prijs_24u_geleden'] = df.loc[timestamp - timedelta(hours=24)]['gemiddelde_prijs'] + + # 5. Rolling-features + features['temp_avg_3u'] = df.loc[timestamp - timedelta(hours=2) : timestamp]['temperatuur'].mean() + features['prijs_avg_6u'] = df.loc[timestamp - timedelta(hours=5) : timestamp]['gemiddelde_prijs'].mean() + + # 6. ONE-HOT ENCODING (Handmatig) + # Voeg alle 7 'dag_' kolommen toe, en zet de juiste op 1 + for dag in range(7): + features[f'dag_{dag}'] = 1 if timestamp.dayofweek == dag else 0 + + # Voeg alle 24 'uur_' kolommen toe, en zet de juiste op 1 + for uur in range(24): + features[f'uur_{uur}'] = 1 if timestamp.hour == uur else 0 + + # Converteer naar een DataFrame en gebruik de volgorde van het model + return pd.DataFrame([features], columns=FEATURES) + + +# --- START VAN HET SCRIPT --- +# (Dit deel is weer 100% identiek aan je vorige script) +try: + conn = mysql.connector.connect(**DB_CONFIG) + werk_df = haal_data_uit_database(conn) + + if werk_df is not None: + te_voorspellen_tijden = werk_df[werk_df['gemiddelde_prijs'].isnull()].index + + print(f"\n🧠 Start iteratieve voorspelling voor {len(te_voorspellen_tijden)} uur...") + voorspellingen = [] + + for timestamp in te_voorspellen_tijden: + features_nu = maak_features_voor_uur(werk_df, timestamp) + voorspelde_prijs = model.predict(features_nu)[0] + werk_df.loc[timestamp, 'gemiddelde_prijs'] = voorspelde_prijs + voorspellingen.append(voorspelde_prijs) + + print("\n" + "="*70) + pd.set_option('display.max_rows', None) # Zorg dat we alles printen + print(f"--- VOORSPELDE PRIJZEN (komende {len(te_voorspellen_tijden)} uur) ---") + + resultaat_df = pd.DataFrame({ + 'Voorspelde_Prijs': voorspellingen + }, index=te_voorspellen_tijden) + + print(resultaat_df) + print("="*70) + +except Error as e: + print(f"āŒ Fout met MySQL verbinding: {e}") +except Exception as e: + print(f"āŒ Een onverwachte fout is opgetreden: {e}") +finally: + if 'conn' in locals() and conn.is_connected(): + conn.close() + print("\nVerbinding met MySQL gesloten.") \ No newline at end of file