Spaces:
Sleeping
Sleeping
File size: 8,833 Bytes
985e206 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# 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.") |