CoolFace
Apppublic

MAALOUFimad02/Machine_Learning_Training

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
TP4_LSTM_TimeSeries.ipynb372 linesDownload Raw Back to notebooks
1{2 "cells": [3  {4   "cell_type": "markdown",5   "metadata": {},6   "source": [7    "# ⏱️ TP-4 : Prédiction de Séries Temporelles avec LSTM\n",8    "\n",9    "**Objectif** : Prédire la consommation électrique avec des réseaux LSTM.\n",10    "\n",11    "**Compétences** :\n",12    "- Préparation de données temporelles\n",13    "- Fenêtres glissantes (windowing)\n",14    "- Architecture LSTM avec Keras\n",15    "- Early stopping et régularisation"16   ]17  },18  {19   "cell_type": "code",20   "execution_count": null,21   "metadata": {},22   "outputs": [],23   "source": [24    "import numpy as np\n",25    "import pandas as pd\n",26    "import matplotlib.pyplot as plt\n",27    "from sklearn.preprocessing import MinMaxScaler\n",28    "from sklearn.metrics import mean_squared_error, mean_absolute_error\n",29    "\n",30    "import tensorflow as tf\n",31    "from tensorflow.keras.models import Sequential\n",32    "from tensorflow.keras.layers import LSTM, Dense, Dropout\n",33    "from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau\n",34    "\n",35    "# Reproductibilité\n",36    "np.random.seed(42)\n",37    "tf.random.set_seed(42)\n",38    "\n",39    "print(f\"✅ TensorFlow version : {tf.__version__}\")"40   ]41  },42  {43   "cell_type": "code",44   "execution_count": null,45   "metadata": {},46   "outputs": [],47   "source": [48    "# Génération de données synthétiques (consommation électrique)\n",49    "# En pratique, remplacez par vos données réelles\n",50    "\n",51    "def generate_energy_data(n_days=365*2):\n",52    "    \"\"\"Génère des données de consommation électrique simulées\"\"\"\n",53    "    hours = np.arange(n_days * 24)\n",54    "    \n",55    "    # Tendance\n",56    "    trend = 0.001 * hours\n",57    "    \n",58    "    # Saisonnalité journalière\n",59    "    daily = 10 * np.sin(2 * np.pi * hours / 24)\n",60    "    \n",61    "    # Saisonnalité hebdomadaire\n",62    "    weekly = 5 * np.sin(2 * np.pi * hours / (24 * 7))\n",63    "    \n",64    "    # Saisonnalité annuelle\n",65    "    yearly = 15 * np.sin(2 * np.pi * hours / (24 * 365))\n",66    "    \n",67    "    # Bruit\n",68    "    noise = np.random.normal(0, 3, len(hours))\n",69    "    \n",70    "    # Consommation totale\n",71    "    consumption = 50 + trend + daily + weekly + yearly + noise\n",72    "    consumption = np.maximum(consumption, 0)  # Pas de valeurs négatives\n",73    "    \n",74    "    return consumption\n",75    "\n",76    "# Génération des données\n",77    "data = generate_energy_data(n_days=730)  # 2 ans de données\n",78    "\n",79    "# Création du DataFrame\n",80    "dates = pd.date_range(start='2022-01-01', periods=len(data), freq='H')\n",81    "df = pd.DataFrame({'consumption': data}, index=dates)\n",82    "\n",83    "print(f\"📊 Période : {df.index[0]} à {df.index[-1]}\")\n",84    "print(f\"📊 Total : {len(df)} heures de données\")\n",85    "df.head()"86   ]87  },88  {89   "cell_type": "code",90   "execution_count": null,91   "metadata": {},92   "outputs": [],93   "source": [94    "# Visualisation des données\n",95    "fig, axes = plt.subplots(3, 1, figsize=(15, 10))\n",96    "\n",97    "# Vue complète\n",98    "axes[0].plot(df.index, df['consumption'], alpha=0.7)\n",99    "axes[0].set_title('Consommation électrique - Vue complète (2 ans)')\n",100    "axes[0].set_ylabel('kWh')\n",101    "\n",102    "# Vue d'une semaine\n",103    "one_week = df.iloc[:24*7]\n",104    "axes[1].plot(one_week.index, one_week['consumption'], marker='o')\n",105    "axes[1].set_title('Consommation - Vue hebdomadaire')\n",106    "axes[1].set_ylabel('kWh')\n",107    "\n",108    "# Vue d'une journée\n",109    "one_day = df.iloc[:24]\n",110    "axes[2].plot(one_day.index.hour, one_day['consumption'], marker='o')\n",111    "axes[2].set_title('Consommation - Vue journalière')\n",112    "axes[2].set_xlabel('Heure')\n",113    "axes[2].set_ylabel('kWh')\n",114    "\n",115    "plt.tight_layout()\n",116    "plt.show()"117   ]118  },119  {120   "cell_type": "code",121   "execution_count": null,122   "metadata": {},123   "outputs": [],124   "source": [125    "# Feature Engineering temporel\n",126    "df['hour'] = df.index.hour\n",127    "df['day_of_week'] = df.index.dayofweek\n",128    "df['month'] = df.index.month\n",129    "df['is_weekend'] = (df['day_of_week'] >= 5).astype(int)\n",130    "\n",131    "# Lags (valeurs précédentes)\n",132    "for lag in [1, 2, 3, 24, 48]:\n",133    "    df[f'lag_{lag}'] = df['consumption'].shift(lag)\n",134    "\n",135    "# Rolling statistics\n",136    "df['rolling_mean_24'] = df['consumption'].rolling(window=24).mean()\n",137    "df['rolling_std_24'] = df['consumption'].rolling(window=24).std()\n",138    "\n",139    "# Suppression des NaN\n",140    "df = df.dropna()\n",141    "\n",142    "print(f\"✅ Features créées : {df.shape[1]} colonnes\")\n",143    "df.head()"144   ]145  },146  {147   "cell_type": "code",148   "execution_count": null,149   "metadata": {},150   "outputs": [],151   "source": [152    "# Préparation des séquences pour LSTM\n",153    "def create_sequences(data, target_col, sequence_length=24):\n",154    "    \"\"\"\n",155    "    Crée des séquences pour LSTM\n",156    "    data : DataFrame avec features\n",157    "    target_col : nom de la colonne cible\n",158    "    sequence_length : longueur de la séquence (ex: 24 heures)\n",159    "    \"\"\"\n",160    "    X, y = [], []\n",161    "    values = data.values\n",162    "    target_idx = data.columns.get_loc(target_col)\n",163    "    \n",164    "    for i in range(sequence_length, len(values)):\n",165    "        X.append(values[i-sequence_length:i])\n",166    "        y.append(values[i, target_idx])\n",167    "    \n",168    "    return np.array(X), np.array(y)\n",169    "\n",170    "# Séparation train/test\n",171    "train_size = int(len(df) * 0.8)\n",172    "train_df = df.iloc[:train_size]\n",173    "test_df = df.iloc[train_size:]\n",174    "\n",175    "# Normalisation\n",176    "scaler = MinMaxScaler()\n",177    "train_scaled = scaler.fit_transform(train_df)\n",178    "test_scaled = scaler.transform(test_df)\n",179    "\n",180    "# Conversion en DataFrame pour garder les noms de colonnes\n",181    "train_scaled = pd.DataFrame(train_scaled, columns=df.columns, index=train_df.index)\n",182    "test_scaled = pd.DataFrame(test_scaled, columns=df.columns, index=test_df.index)\n",183    "\n",184    "# Création des séquences\n",185    "SEQUENCE_LENGTH = 24  # 24 heures d'historique\n",186    "\n",187    "X_train, y_train = create_sequences(train_scaled, 'consumption', SEQUENCE_LENGTH)\n",188    "X_test, y_test = create_sequences(test_scaled, 'consumption', SEQUENCE_LENGTH)\n",189    "\n",190    "print(f\"📊 X_train shape : {X_train.shape}\")\n",191    "print(f\"📊 y_train shape : {y_train.shape}\")\n",192    "print(f\"📊 X_test shape : {X_test.shape}\")\n",193    "print(f\"📊 y_test shape : {y_test.shape}\")"194   ]195  },196  {197   "cell_type": "code",198   "execution_count": null,199   "metadata": {},200   "outputs": [],201   "source": [202    "# Construction du modèle LSTM\n",203    "model = Sequential([\n",204    "    LSTM(64, return_sequences=True, input_shape=(SEQUENCE_LENGTH, X_train.shape[2])),\n",205    "    Dropout(0.2),\n",206    "    LSTM(32, return_sequences=False),\n",207    "    Dropout(0.2),\n",208    "    Dense(16, activation='relu'),\n",209    "    Dense(1)\n",210    "])\n",211    "\n",212    "model.compile(\n",213    "    optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),\n",214    "    loss='mse',\n",215    "    metrics=['mae']\n",216    ")\n",217    "\n",218    "model.summary()"219   ]220  },221  {222   "cell_type": "code",223   "execution_count": null,224   "metadata": {},225   "outputs": [],226   "source": [227    "# Callbacks\n",228    "callbacks = [\n",229    "    EarlyStopping(\n",230    "        monitor='val_loss',\n",231    "        patience=10,\n",232    "        restore_best_weights=True\n",233    "    ),\n",234    "    ReduceLROnPlateau(\n",235    "        monitor='val_loss',\n",236    "        factor=0.5,\n",237    "        patience=5,\n",238    "        min_lr=1e-6\n",239    "    )\n",240    "]\n",241    "\n",242    "# Entraînement\n",243    "history = model.fit(\n",244    "    X_train, y_train,\n",245    "    epochs=100,\n",246    "    batch_size=32,\n",247    "    validation_split=0.2,\n",248    "    callbacks=callbacks,\n",249    "    verbose=1\n",250    ")"251   ]252  },253  {254   "cell_type": "code",255   "execution_count": null,256   "metadata": {},257   "outputs": [],258   "source": [259    "# Visualisation de l'entraînement\n",260    "fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n",261    "\n",262    "# Loss\n",263    "axes[0].plot(history.history['loss'], label='Train')\n",264    "axes[0].plot(history.history['val_loss'], label='Validation')\n",265    "axes[0].set_title('Loss (MSE)')\n",266    "axes[0].set_xlabel('Epoch')\n",267    "axes[0].set_ylabel('Loss')\n",268    "axes[0].legend()\n",269    "\n",270    "# MAE\n",271    "axes[1].plot(history.history['mae'], label='Train')\n",272    "axes[1].plot(history.history['val_mae'], label='Validation')\n",273    "axes[1].set_title('MAE')\n",274    "axes[1].set_xlabel('Epoch')\n",275    "axes[1].set_ylabel('MAE')\n",276    "axes[1].legend()\n",277    "\n",278    "plt.tight_layout()\n",279    "plt.show()"280   ]281  },282  {283   "cell_type": "code",284   "execution_count": null,285   "metadata": {},286   "outputs": [],287   "source": [288    "# Prédictions\n",289    "y_pred = model.predict(X_test)\n",290    "\n",291    "# Métriques (sur données normalisées)\n",292    "mse = mean_squared_error(y_test, y_pred)\n",293    "mae = mean_absolute_error(y_test, y_pred)\n",294    "rmse = np.sqrt(mse)\n",295    "\n",296    "print(f\"📊 MSE  : {mse:.6f}\")\n",297    "print(f\"📊 MAE  : {mae:.6f}\")\n",298    "print(f\"📊 RMSE : {rmse:.6f}\")"299   ]300  },301  {302   "cell_type": "code",303   "execution_count": null,304   "metadata": {},305   "outputs": [],306   "source": [307    "# Visualisation des prédictions\n",308    "plt.figure(figsize=(15, 6))\n",309    "\n",310    "# Plot des 500 premières prédictions\n",311    "n_plot = 500\n",312    "plt.plot(y_test[:n_plot], label='Réel', alpha=0.8)\n",313    "plt.plot(y_pred[:n_plot], label='Prédit', alpha=0.8)\n",314    "plt.title(f'Prédictions LSTM - {n_plot} premiers points de test')\n",315    "plt.xlabel('Temps')\n",316    "plt.ylabel('Consommation (normalisée)')\n",317    "plt.legend()\n",318    "plt.show()"319   ]320  },321  {322   "cell_type": "code",323   "execution_count": null,324   "metadata": {},325   "outputs": [],326   "source": [327    "# Scatter plot : Réel vs Prédit\n",328    "plt.figure(figsize=(8, 8))\n",329    "plt.scatter(y_test, y_pred, alpha=0.5)\n",330    "plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', lw=2)\n",331    "plt.xlabel('Valeurs réelles')\n",332    "plt.ylabel('Valeurs prédites')\n",333    "plt.title('Réel vs Prédit')\n",334    "plt.show()"335   ]336  },337  {338   "cell_type": "markdown",339   "metadata": {},340   "source": [341    "## 🎓 Conclusion\n",342    "\n",343    "Dans ce TP, nous avons :\n",344    "\n",345    "1. ✅ **Généré** des données de consommation électrique avec patterns temporels\n",346    "2. ✅ **Créé** des features temporelles (heure, jour, mois, lags, rolling stats)\n",347    "3. ✅ **Préparé** les séquences pour LSTM avec windowing\n",348    "4. ✅ **Construit** un modèle LSTM avec Dropout et Early Stopping\n",349    "5. ✅ **Évalué** les performances sur l'ensemble de test\n",350    "\n",351    "**Améliorations possibles** :\n",352    "- Utiliser des données météo comme features externes\n",353    "- Tester des architectures plus complexes (Bidirectional LSTM, GRU)\n",354    "- Faire du multi-step forecasting (prédire plusieurs heures en avance)"355   ]356  }357 ],358 "metadata": {359  "kernelspec": {360   "display_name": "Python 3",361   "language": "python",362   "name": "python3"363  },364  "language_info": {365   "name": "python",366   "version": "3.8.0"367  }368 },369 "nbformat": 4,370 "nbformat_minor": 4371}372