Chat
Ask me anything
Ithy Logo

Comment prédire la consommation d'énergie future avec Python et la Régression Linéaire Multiple ?

Un guide détaillé pour transformer vos données de puissance en prévisions hebdomadaires précises, même avec une seule colonne de données.

prediction-puissance-mlr-python-guide-42sqiqc5

Vous cherchez à anticiper les valeurs de puissance pour la semaine à venir en utilisant la Régression Linéaire Multiple (MLR) ? Ce guide vous fournira une méthodologie complète et le code Python nécessaire, en tenant compte de la nature de vos données (normalisées, une seule colonne de 437 796 mesures se terminant le 31 octobre 2023) et de votre objectif de prédiction jusqu'au 7 novembre 2023.

Points Clés à Retenir

  • Ingénierie des Caractéristiques Cruciale : La MLR nécessite plusieurs variables prédictives. Pour une série temporelle avec une seule colonne, la création de caractéristiques temporelles (heure, jour, etc.) et retardées (valeurs passées) est essentielle.
  • Prédiction Itérative pour le Futur : Prédire plusieurs étapes dans le futur avec des caractéristiques retardées exige une approche itérative, où chaque nouvelle prédiction utilise les prédictions précédentes pour calculer les lags requis.
  • MLR et Séries Temporelles : Bien que possible, la MLR n'est pas nativement conçue pour les dépendances séquentielles complexes des séries temporelles. Sa performance dépendra fortement de la qualité des caractéristiques créées. Des modèles plus avancés (ARIMA, LSTM) sont souvent plus performants pour cet usage.

Comprendre la Régression Linéaire Multiple (MLR) pour les Séries Temporelles

La Régression Linéaire Multiple (MLR) est une technique statistique qui vise à modéliser la relation entre une variable dépendante (la cible, ici votre puissance) et plusieurs variables indépendantes (les prédicteurs ou caractéristiques). La formule générale est :

\[ Y = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \dots + \beta_n X_n + \epsilon \]

Où :

  • \(Y\) est la variable dépendante (puissance).
  • \(X_1, X_2, \dots, X_n\) sont les variables indépendantes (caractéristiques).
  • \(\beta_0\) est l'ordonnée à l'origine (intercept).
  • \(\beta_1, \beta_2, \dots, \beta_n\) sont les coefficients de régression, indiquant le changement moyen de \(Y\) pour une unité de changement dans la caractéristique correspondante, en maintenant les autres constantes.
  • \(\epsilon\) est le terme d'erreur (résidu).
Visualisation du concept de Régression Linéaire Multiple
Illustration du principe de la régression linéaire multiple.

Le Défi : Une Seule Colonne de Données

Votre jeu de données contient 437 796 lignes mais une seule colonne de valeurs de puissance normalisées. La MLR exige plusieurs prédicteurs. Comment faire ? La solution réside dans l'ingénierie des caractéristiques (feature engineering) : nous allons créer de nouvelles colonnes (caractéristiques) à partir des informations disponibles :

  1. L'index temporel : En supposant que vos données ont un index temporel (timestamp), nous pouvons en extraire des informations précieuses.
  2. La colonne de puissance elle-même : Les valeurs passées de la puissance peuvent aider à prédire les valeurs futures.

Hypothèse sur la Fréquence des Données

Avec 437 796 points de données se terminant le '2023-10-31 23:59:31', cela couvre environ 304 jours (437796 / (60*24) ≈ 304). Cela suggère fortement que vos données ont une fréquence d'une minute. Nous baserons notre code sur cette hypothèse. Si votre fréquence est différente (par exemple, horaire), vous devrez ajuster les calculs de lags en conséquence.


Guide Détaillé et Code Python

Étape 1 : Préparation de l'Environnement et Chargement des Données

Assurez-vous d'avoir les bibliothèques nécessaires installées :

pip install pandas numpy scikit-learn matplotlib

Chargeons ensuite vos données. Nous supposons qu'elles sont dans un fichier CSV nommé puissance_data.csv avec une colonne 'timestamp' et une colonne 'power'. Adaptez le code si votre structure est différente.


import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
from datetime import timedelta

# --- Configuration ---
DATA_FILE = 'puissance_data.csv' # Mettez ici le chemin vers votre fichier
TIMESTAMP_COL = 'timestamp'      # Nom de la colonne timestamp
POWER_COL = 'power'            # Nom de la colonne puissance (normalisée)
FREQ = 'min'                   # Fréquence supposée des données ('T' ou 'min')

LAST_TIMESTAMP_TRAIN = pd.to_datetime('2023-10-31 23:59:31')
PREDICTION_START = pd.to_datetime('2023-11-01 00:00:00')
PREDICTION_END = pd.to_datetime('2023-11-07 23:59:00')

# --- Chargement et Vérification Initiale ---
print("Chargement des données...")
try:
    # Essayez de charger avec la colonne timestamp comme index
    df = pd.read_csv(DATA_FILE, parse_dates=[TIMESTAMP_COL], index_col=TIMESTAMP_COL)
    print(f"Données chargées avec succès depuis {DATA_FILE}.")
except FileNotFoundError:
    print(f"ERREUR : Le fichier '{DATA_FILE}' n'a pas été trouvé.")
    # Quitter ou gérer l'erreur comme nécessaire
    exit()
except KeyError:
    # Si la colonne timestamp n'existe pas, ou si elle n'est pas l'index
    try:
        df = pd.read_csv(DATA_FILE, parse_dates=[TIMESTAMP_COL])
        df = df.set_index(TIMESTAMP_COL)
        print(f"Données chargées et colonne '{TIMESTAMP_COL}' définie comme index.")
    except Exception as e:
        print(f"ERREUR : Impossible de charger ou de traiter le fichier CSV : {e}")
        exit()
except Exception as e:
    print(f"ERREUR inattendue lors du chargement des données : {e}")
    exit()

# Assurer le bon nom de colonne pour la puissance
if POWER_COL not in df.columns:
    # Si une seule colonne, la renommer
    if len(df.columns) == 1:
        print(f"Avertissement : Une seule colonne trouvée, renommée en '{POWER_COL}'.")
        df.columns = [POWER_COL]
    else:
        print(f"ERREUR : Colonne '{POWER_COL}' non trouvée dans les données.")
        exit()

# Vérifier la forme
print(f"Forme initiale des données : {df.shape}")
if df.shape[0] != 437796:
    print(f"Avertissement : Le nombre de lignes ({df.shape[0]}) ne correspond pas aux 437796 attendus.")

# Trier par index (temps) et supprimer les doublons éventuels
df = df.sort_index()
df = df[~df.index.duplicated(keep='first')]
print(f"Données triées et doublons d'index supprimés. Nouvelle forme : {df.shape}")

# Vérifier la dernière date
if not df.empty:
    actual_last_date = df.index.max()
    print(f"Dernier timestamp dans les données chargées : {actual_last_date}")
    # Comparaison prudente à cause des fuseaux horaires potentiels
    if abs((actual_last_date - LAST_TIMESTAMP_TRAIN).total_seconds()) > 60: # Tolérance de 1 minute
        print(f"Avertissement : Le dernier timestamp ({actual_last_date}) ne correspond pas exactement à {LAST_TIMESTAMP_TRAIN}.")
else:
    print("ERREUR : Le DataFrame est vide après chargement.")
    exit()

# Vérifier les valeurs manquantes
if df[POWER_COL].isnull().any():
    print("Valeurs manquantes détectées. Suppression des lignes concernées...")
    initial_rows = len(df)
    df.dropna(subset=[POWER_COL], inplace=True)
    print(f"{initial_rows - len(df)} lignes avec NaN supprimées.")

print(f"Vérification de la normalisation (min/max de '{POWER_COL}') : {df[POWER_COL].min()} / {df[POWER_COL].max()}")
print("\nExploration des premières et dernières lignes :")
print(df.head())
print(df.tail())
  

Étape 2 : Ingénierie des Caractéristiques (Feature Engineering)

Créons les caractéristiques temporelles et retardées (lags).


print("\nCréation des caractéristiques (Features)...")

# --- Caractéristiques Temporelles ---
df['hour'] = df.index.hour
df['minute'] = df.index.minute # Peut être utile à la fréquence minute
df['dayofweek'] = df.index.dayofweek # Lundi=0, Dimanche=6
df['dayofyear'] = df.index.dayofyear
df['month'] = df.index.month
df['weekofyear'] = df.index.isocalendar().week.astype(int)

# Utiliser sin/cos pour les caractéristiques cycliques (améliore la performance de MLR)
df['hour_sin'] = np.sin(2 * np.pi * df['hour'] / 24)
df['hour_cos'] = np.cos(2 * np.pi * df['hour'] / 24)
df['dayofweek_sin'] = np.sin(2 * np.pi * df['dayofweek'] / 7)
df['dayofweek_cos'] = np.cos(2 * np.pi * df['dayofweek'] / 7)
df['month_sin'] = np.sin(2 * np.pi * df['month'] / 12)
df['month_cos'] = np.cos(2 * np.pi * df['month'] / 12)

# --- Caractéristiques Retardées (Lags) ---
# Important : Les périodes de lag doivent correspondre à la fréquence (en minutes ici)
lag_periods_minutes = {
    'lag_1h': 60,
    'lag_2h': 120,
    'lag_24h': 24 * 60,
    'lag_48h': 48 * 60,
    'lag_1w': 7 * 24 * 60
}

print("Ajout des caractéristiques retardées (cela peut prendre du temps)...")
for name, lag_min in lag_periods_minutes.items():
    df[name] = df[POWER_COL].shift(lag_min)
    print(f"  - {name} (décalage de {lag_min} minutes) ajouté.")

# --- Nettoyage après création des caractéristiques ---
print("Suppression des lignes avec NaN créés par les lags...")
initial_rows = len(df)
df.dropna(inplace=True)
print(f"{initial_rows - len(df)} lignes supprimées. Forme finale pour l'entraînement : {df.shape}")

if df.empty:
    print("ERREUR : Plus de données après suppression des NaN des lags. Vérifiez les périodes de lag ou la quantité de données.")
    exit()

# --- Définition des Features et de la Cible ---
# Exclure les caractéristiques temporelles brutes si on utilise sin/cos
features_cols = [
    'minute', 'dayofyear', 'weekofyear', # Garder des indicateurs non cycliques ou moins bien capturés par sin/cos
    'hour_sin', 'hour_cos',
    'dayofweek_sin', 'dayofweek_cos',
    'month_sin', 'month_cos'
] + list(lag_periods_minutes.keys()) # Ajouter tous les lags

target_col = POWER_COL

X_train = df[features_cols]
y_train = df[target_col]

print(f"\nCaractéristiques sélectionnées pour l'entraînement ({len(features_cols)}):")
print(features_cols)
print(f"Forme de X_train : {X_train.shape}, Forme de y_train : {y_train.shape}")
  

Étape 3 : Entraînement du Modèle MLR

Entraînons le modèle LinearRegression de scikit-learn.


print("\nEntraînement du modèle de Régression Linéaire Multiple...")
model = LinearRegression()
model.fit(X_train, y_train)
print("Modèle entraîné avec succès.")

# Afficher les coefficients (optionnel)
# print("\nCoefficients du modèle:")
# coeff_df = pd.DataFrame(model.coef_, index=features_cols, columns=['Coefficient'])
# print(coeff_df)
# print(f"Ordonnée à l'origine (Intercept) : {model.intercept_}")
  

Étape 4 : Préparation pour la Prédiction Future (Approche Itérative)

C'est l'étape la plus délicate. Pour prédire la semaine du 1er au 7 novembre, nous devons générer les caractéristiques pour chaque minute future. Les caractéristiques temporelles sont faciles à calculer, mais les caractéristiques retardées (lags) dépendent des valeurs de puissance futures... que nous essayons justement de prédire !

La solution est une prédiction itérative :

  1. On prédit la première minute future (01/11/2023 00:00:00). Pour calculer ses lags, on utilise les vraies valeurs historiques de fin octobre.
  2. On prédit la deuxième minute future (01/11/2023 00:01:00). Pour ses lags, on utilise les vraies valeurs historiques si le lag remonte à octobre, OU la valeur prédite à l'étape 1 si le lag remonte à 00:00:00.
  3. On continue ainsi pour toute la semaine, en utilisant les prédictions précédentes pour calculer les lags nécessaires au fur et à mesure.

Attention : Cette approche peut entraîner une accumulation des erreurs (error propagation), surtout sur un horizon long comme une semaine. Les prédictions peuvent devenir moins fiables au fil du temps.


print("\nPréparation de la prédiction future (itérative)...")

# Créer l'index temporel pour la période de prédiction
future_index = pd.date_range(start=PREDICTION_START, end=PREDICTION_END, freq=FREQ)
print(f"Index temporel futur créé : {len(future_index)} points de {future_index.min()} à {future_index.max()}")

# Créer un DataFrame pour stocker les caractéristiques futures et les prédictions
df_future = pd.DataFrame(index=future_index)

# Combiner les données historiques récentes et le DataFrame futur pour faciliter le calcul des lags
# Nous avons besoin des données historiques remontant au moins au lag le plus long (1 semaine)
max_lag_minutes = max(lag_periods_minutes.values())
required_history_start = PREDICTION_START - timedelta(minutes=max_lag_minutes)

# Sélectionner l'historique pertinent (DataFrame 'df' original avant dropna)
# Recharger si nécessaire ou utiliser une copie si 'df' a été modifié par dropna
try:
    df_hist_for_lags = pd.read_csv(DATA_FILE, parse_dates=[TIMESTAMP_COL], index_col=TIMESTAMP_COL)
    df_hist_for_lags = df_hist_for_lags.sort_index()
    df_hist_for_lags = df_hist_for_lags[~df_hist_for_lags.index.duplicated(keep='first')]
    df_hist_for_lags = df_hist_for_lags[[POWER_COL]] # Garder seulement la puissance
except Exception as e:
     print(f"ERREUR lors du rechargement des données pour les lags : {e}. Utilisation de df avant dropna.")
     # Attention, si df a été modifié, il faut le recharger
     # Solution simple: utiliser df_train et y_train pour reconstruire une partie
     df_hist_for_lags = pd.DataFrame({POWER_COL: y_train}, index=X_train.index)


df_combined = pd.concat([df_hist_for_lags[df_hist_for_lags.index >= required_history_start],
                         pd.DataFrame(index=future_index)]) # Concaténer avec l'index futur vide

print(f"DataFrame combiné (historique récent + futur) créé. Forme : {df_combined.shape}")

# Initialiser la colonne de puissance prédite (sera remplie itérativement)
df_combined['predicted_power'] = np.nan
# Remplir la partie historique avec les vraies valeurs
df_combined['predicted_power'].fillna(df_combined[POWER_COL], inplace=True)


print("Génération des caractéristiques et prédiction itérative (cela peut prendre du temps)...")

# Boucle sur chaque timestamp futur à prédire
for t in future_index:
    if t not in df_combined.index:
        print(f"Timestamp {t} non trouvé dans df_combined, arrêt.")
        break

    current_features = {}

    # 1. Calculer les caractéristiques temporelles pour le temps 't'
    current_features['hour'] = t.hour
    current_features['minute'] = t.minute
    current_features['dayofweek'] = t.dayofweek
    current_features['dayofyear'] = t.dayofyear
    current_features['month'] = t.month
    current_features['weekofyear'] = t.isocalendar().week

    current_features['hour_sin'] = np.sin(2 * np.pi * current_features['hour'] / 24)
    current_features['hour_cos'] = np.cos(2 * np.pi * current_features['hour'] / 24)
    current_features['dayofweek_sin'] = np.sin(2 * np.pi * current_features['dayofweek'] / 7)
    current_features['dayofweek_cos'] = np.cos(2 * np.pi * current_features['dayofweek'] / 7)
    current_features['month_sin'] = np.sin(2 * np.pi * current_features['month'] / 12)
    current_features['month_cos'] = np.cos(2 * np.pi * current_features['month'] / 12)

    # 2. Calculer les caractéristiques retardées (lags) pour le temps 't'
    valid_lags = True
    for name, lag_min in lag_periods_minutes.items():
        lag_timestamp = t - timedelta(minutes=lag_min)
        if lag_timestamp in df_combined.index:
            # Utiliser la valeur prédite si elle existe (pour les lags qui tombent dans la période de prédiction),
            # sinon la valeur historique réelle.
            lag_value = df_combined.loc[lag_timestamp, 'predicted_power']
            if pd.isna(lag_value):
                 # Essayer de récupérer la valeur historique si 'predicted_power' est NaN (devrait pas arriver avec fillna)
                 lag_value = df_combined.loc[lag_timestamp, POWER_COL]

            if pd.isna(lag_value):
                print(f"AVERTISSEMENT : Valeur de lag manquante pour {name} au temps {t} (timestamp lag: {lag_timestamp}). Utilisation de 0.")
                current_features[name] = 0 # Ou une autre stratégie (ex: moyenne, ffill)
                valid_lags = False # Marquer comme potentiellement problématique
            else:
                current_features[name] = lag_value
        else:
            print(f"AVERTISSEMENT : Timestamp de lag {lag_timestamp} hors des limites pour {name} au temps {t}. Utilisation de 0.")
            current_features[name] = 0 # Pas assez d'historique
            valid_lags = False

    # 3. Préparer les caractéristiques pour le modèle (DataFrame d'une ligne)
    # Assurer le bon ordre des colonnes, correspondant à X_train.columns
    current_X = pd.DataFrame([current_features], index=[t])[features_cols]

    # 4. Faire la prédiction
    prediction = model.predict(current_X)[0]

    # 5. Stocker la prédiction dans df_combined pour qu'elle soit utilisée pour les futurs lags
    df_combined.loc[t, 'predicted_power'] = prediction

    # Afficher la progression (optionnel)
    if t.minute == 0 and t.second == 0: # Toutes les heures
         print(f"  Prédiction pour {t} : {prediction:.4f}")


# Extraire les prédictions finales
predictions_final = df_combined.loc[future_index, ['predicted_power']]

print("\nPrédictions générées pour la semaine future.")
print("Premières prédictions :")
print(predictions_final.head())
print("\nDernières prédictions :")
print(predictions_final.tail())

# Sauvegarder les prédictions (optionnel)
# predictions_final.to_csv('predictions_puissance_semaine_future.csv')
# print("Prédictions sauvegardées dans 'predictions_puissance_semaine_future.csv'")

  

Étape 5 : Visualisation des Résultats

Visualiser les données historiques récentes et les prédictions aide à évaluer qualitativement le modèle.


print("\nVisualisation des résultats...")

plt.figure(figsize=(15, 7))

# Afficher les dernières semaines de données réelles
plt.plot(df.index[-7*24*60*2:], df[POWER_COL].tail(7*24*60*2), label='Données Historiques Réelles (2 dernières semaines)', color='blue', alpha=0.7)

# Afficher les prédictions
plt.plot(predictions_final.index, predictions_final['predicted_power'], label='Prédictions MLR (Semaine Future)', color='red', linestyle='--')

plt.title('Prédiction de Puissance (Normalisée) avec MLR')
plt.xlabel('Temps')
plt.ylabel('Puissance Normalisée')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

# Zoom sur la transition
plt.figure(figsize=(15, 7))
zoom_start = LAST_TIMESTAMP_TRAIN - timedelta(days=2)
zoom_end = PREDICTION_START + timedelta(days=2)

# Historique zoomé
plt.plot(df.loc[zoom_start:LAST_TIMESTAMP_TRAIN].index, df.loc[zoom_start:LAST_TIMESTAMP_TRAIN, POWER_COL], label='Données Historiques (Zoom)', color='blue')

# Prédictions zoomées
plt.plot(predictions_final.loc[PREDICTION_START:zoom_end].index, predictions_final.loc[PREDICTION_START:zoom_end, 'predicted_power'], label='Prédictions MLR (Zoom)', color='red', linestyle='--')

plt.title('Zoom sur la Transition Historique / Prédiction')
plt.xlabel('Temps')
plt.ylabel('Puissance Normalisée')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
  

Analyse de l'Importance des Caractéristiques

Pour comprendre quels facteurs influencent le plus les prédictions de notre modèle MLR, nous pouvons visualiser l'importance relative des différentes catégories de caractéristiques que nous avons créées. Le graphique radar ci-dessous donne une estimation qualitative de l'impact potentiel de chaque groupe de caractéristiques sur la prédiction de la puissance. Notez que l'importance réelle peut varier et une analyse plus approfondie (comme l'analyse des coefficients ou les tests de permutation) serait nécessaire pour une quantification précise.

Ce graphique suggère que les caractéristiques retardées (capturant l'autocorrélation et les cycles journaliers/hebdomadaires) ainsi que les caractéristiques temporelles cycliques (heure, jour de la semaine) ont potentiellement le plus grand impact sur la capacité du modèle MLR à prédire la puissance. Les lags plus longs (hebdomadaires) et les caractéristiques annuelles (mois) peuvent être légèrement moins influents mais restent importants pour capturer les tendances saisonnières.


Synthèse du Processus

Le diagramme ci-dessous résume les étapes clés que nous avons suivies pour passer de vos données brutes aux prédictions de puissance pour la semaine à venir en utilisant la régression linéaire multiple.

mindmap root["Prédiction de Puissance avec MLR"] id1["1. Préparation"] id1a["Chargement Données (CSV)"] id1b["Vérification (Shape, Dates, NaN)"] id1c["Identification Fréquence (min)"] id2["2. Ingénierie Caractéristiques"] id2a["Temporelles
(Heure, Jour, Mois...)"] id2b["Cycliques (Sin/Cos)"] id2c["Retardées (Lags)
(1h, 24h, 1w...)"] id2d["Nettoyage (Drop NaN)"] id3["3. Entraînement Modèle"] id3a["Sélection Features (X) et Cible (y)"] id3b["Instanciation LinearRegression"] id3c["model.fit(X_train, y_train)"] id4["4. Prédiction Future"] id4a["Création Index Futur
(1 semaine)"] id4b["Approche Itérative"] id4b1["Boucle sur Temps Futur"] id4b2["Calcul Features Temporelles"] id4b3["Calcul Lags (Hist. + Préd. Préc.)"] id4b4["model.predict()"] id4b5["Stockage Prédiction"] id5["5. Analyse & Visualisation"] id5a["Affichage Prédictions"] id5b["Graphiques (Historique vs Préd.)"] id5c["Évaluation (Visuelle)"] id5d["(Optionnel) Sauvegarde CSV"]

Ce processus structuré permet de s'assurer que toutes les étapes nécessaires sont couvertes, de la préparation initiale des données à la génération et à l'évaluation des prédictions finales, en passant par l'étape cruciale de création des caractéristiques adaptées à un modèle MLR pour une série temporelle.


Tableau Récapitulatif des Caractéristiques Créées

Pour mieux comprendre les différentes variables que nous avons ajoutées pour alimenter le modèle MLR, voici un tableau résumant leur type, leur objectif et un exemple.

Nom de la Caractéristique Type Objectif Exemple de Calcul / Valeur
hour, minute, dayofweek, dayofyear, month, weekofyear Temporel (Brut) Capturer les moments spécifiques dans le temps. df.index.hour -> 14
hour_sin, hour_cos Temporel (Cyclique) Représenter la nature cyclique de l'heure dans une journée (0h est proche de 23h). np.sin(2*np.pi*df['hour']/24)
dayofweek_sin, dayofweek_cos Temporel (Cyclique) Représenter la nature cyclique des jours de la semaine (Dimanche est proche de Lundi). np.cos(2*np.pi*df['dayofweek']/7)
month_sin, month_cos Temporel (Cyclique) Représenter la nature cyclique des mois de l'année (Décembre est proche de Janvier). np.sin(2*np.pi*df['month']/12)
lag_1h Retardé (Lag) Utiliser la valeur de puissance d'il y a 1 heure pour prédire la valeur actuelle. Capture l'autocorrélation à court terme. df['power'].shift(60)
lag_24h Retardé (Lag) Utiliser la valeur de puissance d'il y a 24 heures. Capture les schémas journaliers. df['power'].shift(1440)
lag_1w Retardé (Lag) Utiliser la valeur de puissance d'il y a 1 semaine. Capture les schémas hebdomadaires. df['power'].shift(10080)

Cette combinaison de caractéristiques temporelles (brutes et cycliques) et retardées (lags à différentes échelles) fournit au modèle MLR une vue plus riche du contexte de chaque point de données, améliorant ainsi sa capacité à effectuer des prédictions informées.


Apprendre Visuellement : La Régression Linéaire Multiple avec Python

Pour compléter ce guide écrit, la vidéo ci-dessous offre une excellente introduction visuelle et pratique à l'implémentation de la Régression Linéaire Multiple en utilisant la bibliothèque scikit-learn en Python. Bien qu'elle ne traite pas spécifiquement de la prédiction de séries temporelles avec l'approche itérative que nous avons détaillée, elle couvre les concepts fondamentaux de la MLR, la préparation des données (sélection des features X et de la cible y), l'entraînement du modèle (fit) et la réalisation de prédictions (predict), qui sont toutes des étapes clés de notre processus.

Regarder cette vidéo peut vous aider à solidifier votre compréhension des mécanismes de base de la MLR et de son implémentation avec sklearn, rendant le code fourni dans ce guide plus facile à appréhender.


Limitations et Considérations

  • Performance de MLR pour Séries Temporelles : La MLR suppose une relation linéaire et l'indépendance des erreurs, ce qui n'est souvent pas parfaitement vrai pour les séries temporelles complexes comme la consommation/production de puissance. Les performances peuvent être limitées, surtout si les relations sous-jacentes sont non-linéaires ou si des événements externes non modélisés (météo, pannes, etc.) influencent fortement la puissance.
  • Propagation d'Erreur : L'approche itérative pour la prédiction multi-étapes est susceptible à la propagation d'erreur. Une petite erreur dans la première prédiction peut s'amplifier dans les suivantes car elle est utilisée pour calculer les lags futurs. La précision peut diminuer significativement vers la fin de l'horizon de prédiction d'une semaine.
  • Importance des Caractéristiques : Le succès de cette approche dépend énormément de la pertinence des caractéristiques créées. L'ajout de caractéristiques externes (par exemple, prévisions météorologiques si disponibles) pourrait améliorer considérablement les résultats.
  • Normalisation : Vos données sont déjà normalisées, et les prédictions le seront aussi. Si vous avez besoin des prédictions dans l'échelle originale, vous devrez appliquer la transformation inverse de la normalisation utilisée initialement.
  • Fréquence des Données : Nous avons supposé une fréquence d'une minute. Si elle est différente, adaptez les calculs de lag (en nombre de pas) et la fréquence (freq) dans pd.date_range.
  • Alternatives : Pour des prédictions de séries temporelles potentiellement plus précises, envisagez des modèles spécifiquement conçus pour cela, tels que ARIMA, SARIMA, Prophet, ou des modèles basés sur les réseaux de neurones comme les LSTMs ou les GRUs.

Questions Fréquemment Posées (FAQ)

La MLR est-elle le meilleur modèle pour ce type de prédiction ?

Pas nécessairement. La MLR est un modèle relativement simple qui peut bien fonctionner si les relations sont principalement linéaires et si les caractéristiques temporelles et retardées capturent bien la dynamique. Cependant, pour les séries temporelles complexes avec des non-linéarités, des saisonnalités multiples ou des dépendances à long terme, des modèles plus sophistiqués comme SARIMA, Prophet, ou des réseaux de neurones (LSTM, GRU, Transformers) peuvent offrir une meilleure précision. La MLR est un bon point de départ en raison de sa simplicité et de son interprétabilité.

Comment puis-je améliorer la précision des prédictions ?

Plusieurs pistes peuvent être explorées :

  • Plus de caractéristiques : Ajoutez d'autres lags (ex: lags partiels comme 12h, 6h), des caractéristiques d'interaction (ex: heure * jour_semaine), ou des statistiques roulantes (moyenne mobile, écart-type mobile sur différentes fenêtres).
  • Caractéristiques externes : Si possible, intégrez des données externes pertinentes, comme les prévisions météorologiques (température, ensoleillement, vent - crucial pour le PV), les jours fériés, ou des indicateurs d'événements spéciaux.
  • Sélection de caractéristiques : Utilisez des techniques pour sélectionner les caractéristiques les plus pertinentes et éliminer celles qui ajoutent du bruit (ex: analyse de corrélation, Recursive Feature Elimination).
  • Modèles plus complexes : Essayez des modèles non linéaires (ex: Random Forest Regressor, Gradient Boosting Machines) ou des modèles spécifiques aux séries temporelles (voir question précédente).
  • Réglage des hyperparamètres : Bien que MLR ait peu d'hyperparamètres, d'autres modèles en ont qui peuvent être optimisés.
  • Gestion de la propagation d'erreur : Des stratégies plus avancées existent pour la prédiction multi-étapes, comme l'approche "Direct Multi-step Forecast" où l'on entraîne un modèle distinct pour chaque étape future.
Que faire si ma fréquence de données n'est pas d'une minute ?

Vous devez ajuster deux parties principales du code :

  1. Calcul des Lags : Les valeurs dans `lag_periods_minutes` représentent le décalage en nombre de pas correspondant à la période souhaitée. Si votre fréquence est horaire (1 pas = 1 heure), alors `lag_1h` serait `shift(1)`, `lag_24h` serait `shift(24)`, `lag_1w` serait `shift(24*7)`. Adaptez les valeurs de décalage en fonction de votre fréquence réelle.
  2. Génération de l'Index Futur : Modifiez le paramètre `freq` dans `pd.date_range(start=PREDICTION_START, end=PREDICTION_END, freq=...)`. Utilisez 'H' pour horaire, '15min' pour 15 minutes, etc. Consultez la documentation pandas pour les alias de fréquence (Pandas Offset Aliases).
Comment évaluer quantitativement la performance du modèle ?

La visualisation est utile, mais une évaluation quantitative est nécessaire. Vous devriez idéalement mettre de côté une partie de vos données historiques comme "ensemble de test" (par exemple, la dernière semaine ou les dernières semaines avant le '2023-10-31'). Entraînez le modèle sur les données précédant cet ensemble de test, puis faites des prédictions sur la période de test et comparez-les aux valeurs réelles en utilisant des métriques comme :

  • MAE (Mean Absolute Error) : Erreur absolue moyenne. \( \frac{1}{N} \sum_{i=1}^{N} |y_i - \hat{y}_i| \)
  • RMSE (Root Mean Squared Error) : Erreur quadratique moyenne racine. \( \sqrt{\frac{1}{N} \sum_{i=1}^{N} (y_i - \hat{y}_i)^2} \)
  • MAPE (Mean Absolute Percentage Error) : Pourcentage d'erreur absolu moyen (attention si les valeurs réelles sont proches de zéro). \( \frac{100\%}{N} \sum_{i=1}^{N} \left| \frac{y_i - \hat{y}_i}{y_i} \right| \)

Où \(y_i\) est la valeur réelle et \(\hat{y}_i\) est la valeur prédite. Calculez ces métriques sur votre ensemble de test pour avoir une idée de la performance attendue sur les données futures.


Références

Recommandations pour Approfondir


Last updated April 24, 2025
Ask Ithy AI
Download Article
Delete Article