# Importation des bibliothèques nécessaires import pandas as pd import numpy as np import glob import matplotlib.pyplot as plt import matplotlib as mpl from sklearn.preprocessing import LabelEncoder, StandardScaler from sklearn.metrics import mean_absolute_error, mean_squared_error from sklearn.model_selection import TimeSeriesSplit from xgboost import XGBRegressor import joblib import os # Ajustement du paramètre agg.path.chunksize pour éviter l'OverflowError mpl.rcParams['agg.path.chunksize'] = 10000 # Vous pouvez ajuster la valeur si nécessaire # 1. Chargement des données print("Chargement des données...") parquet_files = glob.glob('FuelInFranceData/*.parquet') if not parquet_files: raise FileNotFoundError("Aucun fichier Parquet trouvé dans le répertoire spécifié.") df_list = [] for f in parquet_files: print(f"Chargement du fichier {f}") df_list.append(pd.read_parquet(f)) df = pd.concat(df_list, ignore_index=True) del df_list # Libération de la mémoire print(f"Nombre total d'enregistrements: {len(df)}") # 2. Prétraitement des données print("Prétraitement des données...") df['rate_date'] = pd.to_datetime(df['rate_date']) df['brent_date'] = pd.to_datetime(df['brent_date']) df = df.sort_values('rate_date') df = df.dropna() # Exclure les carburants E85 et GPLc df = df[~df['fuel_name'].isin(['E85', 'GPLc'])] # Sélection des colonnes pertinentes (inclure 'brent_date') cols_to_use = ['station_id', 'commune', 'marque', 'departement', 'regioncode', 'coordlatitude', 'coordlongitude', 'fuel_name', 'price', 'rate_date', 'brent_rate_eur', 'brent_date'] df = df[cols_to_use] # Encodage des variables catégorielles print("Encodage des variables catégorielles...") label_encoders = {} categorical_cols = ['station_id', 'commune', 'marque', 'departement', 'regioncode', 'fuel_name'] for col in categorical_cols: le = LabelEncoder() df[col] = le.fit_transform(df[col].astype(str)) label_encoders[col] = le # 3. Nettoyage des valeurs aberrantes (outliers) print("Nettoyage des valeurs aberrantes...") # Suppression des outliers en utilisant l'IQR (Interquartile Range) def remove_outliers_iqr(data, column): Q1 = data[column].quantile(0.25) Q3 = data[column].quantile(0.75) IQR = Q3 - Q1 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQR data_clean = data[(data[column] >= lower_bound) & (data[column] <= upper_bound)] return data_clean df = remove_outliers_iqr(df, 'price') # 4. Entraînement de modèles séparés pour chaque type de carburant avec validation croisée temporelle print("Entraînement de modèles séparés pour chaque type de carburant avec validation croisée temporelle...") fuel_types = df['fuel_name'].unique() models = {} scalers = {} results = {} for fuel in fuel_types: fuel_name_decoded = label_encoders['fuel_name'].inverse_transform([fuel])[0] print(f"\nTraitement du carburant: {fuel_name_decoded}") df_fuel = df[df['fuel_name'] == fuel].copy() # Ingénierie des caractéristiques df_fuel['day_of_week'] = df_fuel['rate_date'].dt.dayofweek df_fuel['month'] = df_fuel['rate_date'].dt.month df_fuel['year'] = df_fuel['rate_date'].dt.year # Création des variables de décalage (lags) pour le prix du Brent for lag in [1, 3, 7, 15, 30]: df_fuel[f'brent_rate_eur_lag_{lag}'] = df_fuel['brent_rate_eur'].shift(lag) df_fuel = df_fuel.dropna() # Variables features et target X = df_fuel.drop(['price', 'rate_date', 'brent_date'], axis=1) y = df_fuel['price'] dates = df_fuel['rate_date'] # Normalisation des données scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # Validation croisée temporelle tscv = TimeSeriesSplit(n_splits=5) y_tests = [] y_preds = [] dates_list = [] for fold, (train_index, test_index) in enumerate(tscv.split(X_scaled)): print(f" Fold {fold+1}/{tscv.get_n_splits()}") X_train, X_test = X_scaled[train_index], X_scaled[test_index] y_train, y_test = y.iloc[train_index], y.iloc[test_index] dates_test = dates.iloc[test_index] # Entraînement du modèle model = XGBRegressor(objective='reg:squarederror', n_estimators=100, learning_rate=0.1) model.fit(X_train, y_train) # Prédiction sur l'ensemble de test y_pred = model.predict(X_test) # Stockage des résultats y_tests.append(y_test) y_preds.append(y_pred) dates_list.append(dates_test) # Concaténation des résultats y_test_total = pd.concat(y_tests) y_pred_total = np.concatenate(y_preds) dates_total = pd.concat(dates_list) # Évaluation du modèle mae = mean_absolute_error(y_test_total, y_pred_total) rmse = mean_squared_error(y_test_total, y_pred_total, squared=False) print(f"Erreur Absolue Moyenne (MAE): {mae:.4f}") print(f"Racine de l'Erreur Quadratique Moyenne (RMSE): {rmse:.4f}") # Entraînement final sur l'ensemble des données pour la prévision future model_final = XGBRegressor(objective='reg:squarederror', n_estimators=100, learning_rate=0.1) model_final.fit(X_scaled, y) # Sauvegarde du modèle final et du scaler models[fuel] = model_final scalers[fuel] = scaler # Stockage des résultats pour l'analyse results[fuel] = { 'y_test': y_test_total, 'y_pred': y_pred_total, 'dates': dates_total } # Sous-échantillonnage des données pour le tracé downsample_rate = max(1, len(dates_total) // 1000) # Limiter à 1000 points dates_sampled = dates_total.iloc[::downsample_rate] y_test_sampled = y_test_total.iloc[::downsample_rate] y_pred_sampled = y_pred_total[::downsample_rate] # Tri des données pour le tracé sorted_indices = np.argsort(dates_sampled) dates_sampled = dates_sampled.iloc[sorted_indices] y_test_sampled = y_test_sampled.iloc[sorted_indices] y_pred_sampled = y_pred_sampled[sorted_indices] # Graphique de validation (Prix prédit vs Prix réel) plt.figure(figsize=(12, 6)) plt.plot(dates_sampled, y_test_sampled, label='Prix Réel', marker='o', linestyle='None', markersize=4) plt.plot(dates_sampled, y_pred_sampled, label='Prix Prédit', marker='x', linestyle='None', markersize=4) plt.xlabel('Date') plt.ylabel('Prix (€)') plt.title(f"Comparaison du Prix Réel et Prédit pour le Carburant {fuel_name_decoded}") plt.legend() plt.tight_layout() # Enregistrer le graphique plt.savefig(f'validation_{fuel_name_decoded}.png') plt.close() # 5. Prévision pour les 3, 7, 15 et 30 prochains jours pour chaque carburant print("\nPrévision pour les prochains jours pour chaque carburant...") for fuel in fuel_types: fuel_name_decoded = label_encoders['fuel_name'].inverse_transform([fuel])[0] print(f"\nPrévisions pour le carburant: {fuel_name_decoded}") df_fuel = df[df['fuel_name'] == fuel] last_known_data = df_fuel.iloc[-1] model = models[fuel] scaler = scalers[fuel] def forecast_prices(model, last_known_data, scaler, horizons=[3, 7, 15, 30]): forecasts = {} for horizon in horizons: future_date = last_known_data['rate_date'] + pd.Timedelta(days=horizon) input_data = last_known_data.to_frame().T.copy() input_data['rate_date'] = future_date input_data['day_of_week'] = future_date.dayofweek input_data['month'] = future_date.month input_data['year'] = future_date.year # Mise à jour des variables de décalage du Brent for lag in [1, 3, 7, 15, 30]: input_data[f'brent_rate_eur_lag_{lag}'] = last_known_data['brent_rate_eur'] input_data = input_data.dropna(axis=1, how='all') # Préparation des données pour la prédiction input_features = input_data.drop(['price', 'rate_date', 'brent_date'], axis=1) input_features_scaled = scaler.transform(input_features) predicted_price = model.predict(input_features_scaled) forecasts[horizon] = predicted_price[0] return forecasts # Prévision des prix forecasts = forecast_prices(model, last_known_data, scaler) for horizon, price in forecasts.items(): print(f"Dans {horizon} jours: {price:.4f} €") # 6. Sauvegarde des modèles et des scalers pour une utilisation future print("\nSauvegarde des modèles et des scalers...") for fuel in fuel_types: fuel_name_decoded = label_encoders['fuel_name'].inverse_transform([fuel])[0] joblib.dump(models[fuel], f'fuel_price_model_{fuel_name_decoded}.pkl') joblib.dump(scalers[fuel], f'scaler_{fuel_name_decoded}.pkl') print("Script terminé avec succès.")