From 2539a5fd59e085eaa741293529e8a290dc9c0066 Mon Sep 17 00:00:00 2001 From: AlexandreBourrieau <66630728+AlexandreBourrieau@users.noreply.github.com> Date: Thu, 3 Jun 2021 16:54:31 +0200 Subject: [PATCH] =?UTF-8?q?Cr=C3=A9=C3=A9=20avec=20Colaboratory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Reseau_GRU_Avec_Auto_Attention.ipynb | 790 ++++++++++++++++++ 1 file changed, 790 insertions(+) create mode 100644 Introduction Attention/Reseau_GRU_Avec_Auto_Attention.ipynb diff --git a/Introduction Attention/Reseau_GRU_Avec_Auto_Attention.ipynb b/Introduction Attention/Reseau_GRU_Avec_Auto_Attention.ipynb new file mode 100644 index 0000000..1f8f994 --- /dev/null +++ b/Introduction Attention/Reseau_GRU_Avec_Auto_Attention.ipynb @@ -0,0 +1,790 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "Reseau_GRU_Avec_Auto_Attention.ipynb", + "provenance": [], + "include_colab_link": true + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + } + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "view-in-github", + "colab_type": "text" + }, + "source": [ + "\"Open" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ubCeIvtF6R4W" + }, + "source": [ + "Dans ce carnet nous allons mettre en place un modèle à réseau de neurones récurrent de type GRU associé à une **couche d'auto attention** comprenant une **matrice de contexte** pour réaliser des prédictions sur notre série temporelle. \n", + "Ce modèle est tiré du papier de recherche : [A Structured Self-attentive Sentence Embedding](https://arxiv.org/pdf/1703.03130)" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "RRhtHsNn5fc3" + }, + "source": [ + "import tensorflow as tf\n", + "from tensorflow import keras\n", + "\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "XFeah3y_6kif" + }, + "source": [ + "# Création de la série temporelle et du dataset pour l'entrainement" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "vJfSLtub6sdc" + }, + "source": [ + "# Fonction permettant d'afficher une série temporelle\n", + "def affiche_serie(temps, serie, format=\"-\", debut=0, fin=None, label=None):\n", + " plt.plot(temps[debut:fin], serie[debut:fin], format, label=label)\n", + " plt.xlabel(\"Temps\")\n", + " plt.ylabel(\"Valeur\")\n", + " if label:\n", + " plt.legend(fontsize=14)\n", + " plt.grid(True)\n", + "\n", + "# Fonction permettant de créer une tendance\n", + "def tendance(temps, pente=0):\n", + " return pente * temps\n", + "\n", + "# Fonction permettant de créer un motif\n", + "def motif_periodique(instants):\n", + " return (np.where(instants < 0.4, # Si les instants sont < 0.4\n", + " np.cos(instants * 2 * np.pi), # Alors on retourne la fonction cos(2*pi*t)\n", + " 1 / np.exp(3 * instants))) # Sinon, on retourne la fonction exp(-3t)\n", + "\n", + "# Fonction permettant de créer une saisonnalité avec un motif\n", + "def saisonnalite(temps, periode, amplitude=1, phase=0):\n", + " \"\"\"Répétition du motif sur la même période\"\"\"\n", + " instants = ((temps + phase) % periode) / periode # Mapping du temps =[0 1 2 ... 1460] => instants = [0.0 ... 1.0]\n", + " return amplitude * motif_periodique(instants)\n", + "\n", + "# Fonction permettant de générer du bruit gaussien N(0,1)\n", + "def bruit_blanc(temps, niveau_bruit=1, graine=None):\n", + " rnd = np.random.RandomState(graine)\n", + " return rnd.randn(len(temps)) * niveau_bruit\n", + "\n", + "# Fonction permettant de créer un dataset à partir des données de la série temporelle\n", + "# au format X(X1,X2,...Xn) / Y(Y1,Y2,...,Yn)\n", + "# X sont les données d'entrées du réseau\n", + "# Y sont les labels\n", + "\n", + "def prepare_dataset_XY(serie, taille_fenetre, batch_size, buffer_melange):\n", + " dataset = tf.data.Dataset.from_tensor_slices(serie)\n", + " dataset = dataset.window(taille_fenetre+1, shift=1, drop_remainder=True)\n", + " dataset = dataset.flat_map(lambda x: x.batch(taille_fenetre + 1))\n", + " dataset = dataset.map(lambda x: (x[:-1], x[-1:]))\n", + " dataset = dataset.batch(batch_size,drop_remainder=True).prefetch(1)\n", + " return dataset\n", + "\n", + "\n", + "# Création de la série temporelle\n", + "temps = np.arange(4 * 365) # temps = [0 1 2 .... 4*365] = [0 1 2 .... 1460]\n", + "amplitude = 40 # Amplitude de la la saisonnalité\n", + "niveau_bruit = 5 # Niveau du bruit\n", + "offset = 10 # Offset de la série\n", + "\n", + "serie = offset + tendance(temps, 0.1) + saisonnalite(temps, periode=365, amplitude=amplitude) + bruit_blanc(temps,niveau_bruit,graine=40)\n", + "\n", + "temps_separation = 1000\n", + "\n", + "# Extraction des temps et des données d'entrainement\n", + "temps_entrainement = temps[:temps_separation]\n", + "x_entrainement = serie[:temps_separation]\n", + "\n", + "# Exctraction des temps et des données de valiadation\n", + "temps_validation = temps[temps_separation:]\n", + "x_validation = serie[temps_separation:]\n", + "\n", + "# Définition des caractéristiques du dataset que l'on souhaite créer\n", + "taille_fenetre = 20\n", + "batch_size = 32\n", + "buffer_melange = 1000\n", + "\n", + "# Création du dataset X,Y\n", + "dataset = prepare_dataset_XY(x_entrainement,taille_fenetre,batch_size,buffer_melange)\n", + "\n", + "# Création du dataset X,Y de validation\n", + "dataset_Val = prepare_dataset_XY(x_validation,taille_fenetre,batch_size,buffer_melange)" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "-6WVzU_X3JxG" + }, + "source": [ + "# Calcul de la moyenne et de l'écart type de la série\n", + "mean = tf.math.reduce_mean(serie)\n", + "std = tf.math.reduce_std(serie)\n", + "\n", + "# Normalise les données\n", + "Serie_Normalisee = (serie-mean)/std\n", + "min = tf.math.reduce_min(serie)\n", + "max = tf.math.reduce_max(serie)" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "CYtsc0Yk3LhT" + }, + "source": [ + "# Création des données pour l'entrainement et le test\n", + "x_entrainement_norm = Serie_Normalisee[:temps_separation]\n", + "x_validation_norm = Serie_Normalisee[temps_separation:]\n", + "\n", + "# Création du dataset X,Y\n", + "dataset_norm = prepare_dataset_XY(x_entrainement_norm,taille_fenetre,batch_size,buffer_melange)\n", + "\n", + "# Création du dataset X,Y de validation\n", + "dataset_Val_norm = prepare_dataset_XY(x_validation_norm,taille_fenetre,batch_size,buffer_melange)" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "2Yt-EgZ3sgPY" + }, + "source": [ + "# Création du modèle GRU avec couche d'attention possédant un vecteur de contexte" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "dyrcfKcgCsZ7" + }, + "source": [ + "**1. Création du réseau et adaptation des formats d'entrée et de sortie**" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "zeJyix8HK7Kt" + }, + "source": [ + "Sous forme de shéma, notre réseau est donc le suivant :\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "1OZkfsmnBNHY" + }, + "source": [ + " " + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "4kgTrJOQ5DUo" + }, + "source": [ + "# Remise à zéro de tous les états générés par Keras\n", + "tf.keras.backend.clear_session()" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "hLNIAGDlBizT" + }, + "source": [ + "On créé une classe dérivée de la classe [Layer](https://keras.io/api/layers/base_layer/#layer-class) de Keras. Les méthodes utilisées sont les suivantes : \n", + " - [build](https://www.tensorflow.org/api_docs/python/tf/keras/layers/Layer#build) : Permet de créer les variables utilisées par la couche (commes les poids et les offsets)\n", + " - [call](https://www.tensorflow.org/api_docs/python/tf/keras/layers/Layer#call) : Permet d'implanter la logique de la couche" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "cZK9V72Va9vg" + }, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "zyoh5UpQXCqm" + }, + "source": [ + "Parmi les nouvelles fonctions de Tensorflow et de Keras utilisées, on trouve :\n", + "- [transpose](https://www.tensorflow.org/api_docs/python/tf/transpose) : Permet de transposer un tenseur et éventuellement de reconstituer l'ordre des axes avec l'argument `perm`\n", + "- [add_weight](https://www.tensorflow.org/api_docs/python/tf/keras/layers/Layer#add_weight) : Méthode de la classe Layers de Keras, qui permet d'ajouter un paramètre (poids et offset ou autre) qui sera une variable mémoire pour la couche construite. \n" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Hhk0kmPSgqva" + }, + "source": [ + "# Classe d'auto-attention\n", + "# Applique les poids de la matrice d'attention sur les vecteurs de la couche récurrente\n", + "\n", + "# Importe le Backend de Keras\n", + "from keras import backend as K\n", + "\n", + "# Définit une nouvelle classe Couche_Attention\n", + "# Héritée de la classe Layer de Keras\n", + "\n", + "class Couche_Auto_Attention(tf.keras.layers.Layer):\n", + " # Fonction d'initialisation de la classe d'attention\n", + " def __init__(self,dim_att,nbr_hop):\n", + " self.dim_att = dim_att # Dimension du vecteur d'attention\n", + " self.nbr_hop = nbr_hop\n", + " super().__init__() # Appel du __init__() de la classe Layer\n", + " \n", + " def build(self,input_shape):\n", + " self.W = self.add_weight(shape=(self.dim_att,input_shape[2]),initializer='glorot_uniform',name=\"W\")\n", + " self.U = self.add_weight(shape=(self.nbr_hop,self.dim_att),initializer='glorot_uniform',name=\"U\")\n", + " super().build(input_shape) # Appel de la méthode build()\n", + "\n", + " # Définit la logique de la couche d'attention\n", + " # Arguments : x : Tenseur d'entrée de dimension (None, nbr_v,dim)\n", + " def call(self,x):\n", + " # Calcul de la matrice XH contenant les\n", + " # représentations cachées des vecteurs\n", + " # issus de la couche GRU\n", + " xt = tf.transpose(x,perm=[0,2,1]) # (None,20,40) => (None,40,20)\n", + " Xh = tf.matmul(self.W,xt) # (#Att,40)x(None,40,20) = (None,#Att,20)\n", + " Xh = K.tanh(Xh) # Xh = (None,#Att,20)\n", + "\n", + " # Calcul de la matrice des poids d'attention normalisés\n", + " A = tf.matmul(self.U,Xh) # (#hop,#Att)x(None,#Att,20) = (None,#Att,20)\n", + " A = tf.keras.activations.softmax(A,axis=2) # (None,#Att,20)\n", + "\n", + " # Calcul de la matrice des vecteur d'attentions\n", + " sortie = tf.matmul(A,x) # (None,#Att,20)x(None,20,40) = (None,#Att,40)\n", + " return tf.keras.layers.Flatten()(sortie)" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "gxdhzNuymXTx" + }, + "source": [ + "dim_GRU = 40\n", + "nbr_hop = 5\n", + "\n", + "# Fonction de la couche lambda d'entrée\n", + "def Traitement_Entrees(x):\n", + " return tf.expand_dims(x,axis=-1)\n", + "\n", + "# Définition de l'entrée du modèle\n", + "entrees = tf.keras.layers.Input(shape=(taille_fenetre))\n", + "\n", + "# Encodeur\n", + "e_adapt = tf.keras.layers.Lambda(Traitement_Entrees)(entrees)\n", + "s_encodeur = tf.keras.layers.GRU(dim_GRU,return_sequences=True,recurrent_regularizer=tf.keras.regularizers.l2(1e-5))(e_adapt)\n", + "s_attention = Couche_Auto_Attention(dim_att=dim_GRU,nbr_hop=nbr_hop)(s_encodeur)\n", + "\n", + "# Décodeur\n", + "s_decodeur = tf.keras.layers.Dense(dim_GRU*nbr_hop,activation=\"tanh\")(s_attention)\n", + "s_decodeur = tf.keras.layers.Concatenate()([s_decodeur,s_attention])\n", + "\n", + "# Générateur\n", + "sortie = tf.keras.layers.Dense(1)(s_decodeur)\n", + "\n", + "# Construction du modèle\n", + "model = tf.keras.Model(entrees,sortie)\n", + "\n", + "model.save_weights(\"model_initial.hdf5\")\n", + "model.summary()" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "MUM0-SSXGLIQ" + }, + "source": [ + "**2. Optimisation du taux d'apprentissage**" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "jejCBhXVuNQ4" + }, + "source": [ + "# Définition de la fonction de régulation du taux d'apprentissage\n", + "def RegulationTauxApprentissage(periode, taux):\n", + " return 1e-8*10**(periode/10)\n", + "\n", + "# Définition de l'optimiseur à utiliser\n", + "optimiseur=tf.keras.optimizers.Adam()\n", + "\n", + "# Utilisation de la méthode ModelCheckPoint\n", + "CheckPoint = tf.keras.callbacks.ModelCheckpoint(\"poids.hdf5\", monitor='loss', verbose=1, save_best_only=True, save_weights_only = True, mode='auto', save_freq='epoch')\n", + "\n", + "# Compile le modèle\n", + "model.compile(loss=tf.keras.losses.Huber(), optimizer=optimiseur, metrics=\"mae\")\n", + "\n", + "# Entraine le modèle en utilisant notre fonction personnelle de régulation du taux d'apprentissage\n", + "historique = model.fit(dataset_norm,epochs=100,verbose=1, callbacks=[tf.keras.callbacks.LearningRateScheduler(RegulationTauxApprentissage), CheckPoint])" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "q1_WMNlzu2B4" + }, + "source": [ + "# Construit un vecteur avec les valeurs du taux d'apprentissage à chaque période \n", + "taux = 1e-8*(10**(np.arange(100)/10))\n", + "\n", + "# Affiche l'erreur en fonction du taux d'apprentissage\n", + "plt.figure(figsize=(10, 6))\n", + "plt.semilogx(taux,historique.history[\"loss\"])\n", + "plt.axis([ taux[0], taux[99], 0, 1])\n", + "plt.title(\"Evolution de l'erreur en fonction du taux d'apprentissage\")" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "6XdXh_b0GP_F" + }, + "source": [ + "**3. Entrainement du modèle**" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "80pEtJ10wIfY" + }, + "source": [ + "# Charge les meilleurs poids\n", + "model.load_weights(\"poids.hdf5\")" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "16ujUiELwR33" + }, + "source": [ + "from timeit import default_timer as timer\n", + "\n", + "class TimingCallback(keras.callbacks.Callback):\n", + " def __init__(self, logs={}):\n", + " self.logs=[]\n", + " def on_epoch_begin(self, epoch, logs={}):\n", + " self.starttime = timer()\n", + " def on_epoch_end(self, epoch, logs={}):\n", + " self.logs.append(timer()-self.starttime)\n", + "\n", + "# Définition des paramètres liés à l'évolution du taux d'apprentissage\n", + "lr_schedule = tf.keras.optimizers.schedules.InverseTimeDecay(\n", + " initial_learning_rate=0.01,\n", + " decay_steps=10,\n", + " decay_rate=0.01\n", + " )\n", + "\n", + "cb = TimingCallback()\n", + "\n", + "# Définition de l'optimiseur à utiliser\n", + "optimiseur=tf.keras.optimizers.SGD(learning_rate=lr_schedule,momentum=0.9)\n", + "\n", + "\n", + "# Utilisation de la méthode ModelCheckPoint\n", + "CheckPoint = tf.keras.callbacks.ModelCheckpoint(\"poids_train.hdf5\", monitor='loss', verbose=1, save_best_only=True, save_weights_only = True, mode='auto', save_freq='epoch')\n", + "\n", + "# Compile le modèle\n", + "model.compile(loss=tf.keras.losses.Huber(), optimizer=optimiseur,metrics=\"mae\")\n", + "\n", + "# Entraine le modèle\n", + "historique = model.fit(dataset_norm,validation_data=dataset_Val_norm, epochs=500,verbose=1, callbacks=[CheckPoint,cb])\n", + "\n", + "print(cb.logs)\n", + "print(sum(cb.logs))" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "COP9u4yitvmw" + }, + "source": [ + "erreur_entrainement = historique.history[\"loss\"]\n", + "erreur_validation = historique.history[\"val_loss\"]\n", + "\n", + "# Affiche l'erreur en fonction de la période\n", + "plt.figure(figsize=(10, 6))\n", + "plt.plot(np.arange(0,len(erreur_entrainement)),erreur_entrainement, label=\"Erreurs sur les entrainements\")\n", + "plt.plot(np.arange(0,len(erreur_entrainement)),erreur_validation, label =\"Erreurs sur les validations\")\n", + "plt.legend()\n", + "\n", + "plt.title(\"Evolution de l'erreur en fonction de la période\")" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "_o2zh6N9t1b7" + }, + "source": [ + "erreur_entrainement = historique.history[\"loss\"]\n", + "erreur_validation = historique.history[\"val_loss\"]\n", + "\n", + "# Affiche l'erreur en fonction de la période\n", + "plt.figure(figsize=(10, 6))\n", + "plt.plot(np.arange(0,len(erreur_entrainement[400:500])),erreur_entrainement[400:500], label=\"Erreurs sur les entrainements\")\n", + "plt.plot(np.arange(0,len(erreur_entrainement[400:500])),erreur_validation[400:500], label =\"Erreurs sur les validations\")\n", + "plt.legend()\n", + "\n", + "plt.title(\"Evolution de l'erreur en fonction de la période\")" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "T6Gq2CkeGR_1" + }, + "source": [ + "**4. Prédictions**" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "HRxXtHRXGXfF" + }, + "source": [ + "taille_fenetre = 20\n", + "\n", + "# Création d'une liste vide pour recevoir les prédictions\n", + "predictions = []\n", + "\n", + "# Calcul des prédiction pour chaque groupe de 20 valeurs consécutives de la série\n", + "# dans l'intervalle de validation\n", + "for t in temps[temps_separation:-taille_fenetre]:\n", + " X = np.reshape(Serie_Normalisee[t:t+taille_fenetre],(1,taille_fenetre))\n", + " predictions.append(model.predict(X))" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "Wd2nfDcgG8EO" + }, + "source": [ + "# Affiche la série et les prédictions\n", + "plt.figure(figsize=(10, 6))\n", + "affiche_serie(temps,serie,label=\"Série temporelle\")\n", + "affiche_serie(temps[temps_separation+taille_fenetre:],np.asarray(predictions*std+mean)[:,0,0],label=\"Prédictions\")\n", + "plt.title('Prédictions avec le modèle GRU avec Auto-Attention')\n", + "plt.show()\n", + "\n", + "# Zoom sur l'intervalle de validation\n", + "plt.figure(figsize=(10, 6))\n", + "affiche_serie(temps[temps_separation:],serie[temps_separation:],label=\"Série temporelle\")\n", + "affiche_serie(temps[temps_separation+taille_fenetre:],np.asarray(predictions*std+mean)[:,0,0],label=\"Prédictions\")\n", + "plt.title(\"Prédictions avec le modèle GRU avec Auto-Attention (zoom sur l'intervalle de validation)\")\n", + "plt.show()" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "PDS7BJvZG_e1" + }, + "source": [ + "# Calcule de l'erreur quadratique moyenne et de l'erreur absolue moyenne \n", + "\n", + "mae = tf.keras.metrics.mean_absolute_error(serie[temps_separation+taille_fenetre:],np.asarray(predictions*std+mean)[:,0,0]).numpy()\n", + "mse = tf.keras.metrics.mean_squared_error(serie[temps_separation+taille_fenetre:],np.asarray(predictions*std+mean)[:,0,0]).numpy()\n", + "\n", + "print(mae)\n", + "print(mse)" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "taPvyn8-tecN" + }, + "source": [ + "**5. Entrainement du modèle avec l'optimiseur Adam**" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "1Yzp0HzatoHM" + }, + "source": [ + "# Charge les meilleurs poids\n", + "model.load_weights(\"model_initial.hdf5\")" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "RX4zPE1mvLqH" + }, + "source": [ + "# Définition de la fonction de régulation du taux d'apprentissage\n", + "def RegulationTauxApprentissage(periode, taux):\n", + " return 1e-8*10**(periode/10)\n", + "\n", + "# Définition de l'optimiseur à utiliser\n", + "optimiseur=tf.keras.optimizers.Adam()\n", + "\n", + "# Utilisation de la méthode ModelCheckPoint\n", + "CheckPoint = tf.keras.callbacks.ModelCheckpoint(\"poids.hdf5\", monitor='loss', verbose=1, save_best_only=True, save_weights_only = True, mode='auto', save_freq='epoch')\n", + "\n", + "# Compile le modèle\n", + "model.compile(loss=tf.keras.losses.Huber(), optimizer=optimiseur, metrics=\"mae\")\n", + "\n", + "# Entraine le modèle en utilisant notre fonction personnelle de régulation du taux d'apprentissage\n", + "historique = model.fit(dataset_norm,epochs=100,verbose=1, callbacks=[tf.keras.callbacks.LearningRateScheduler(RegulationTauxApprentissage), CheckPoint])" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "XLsKmUWOvQ5l" + }, + "source": [ + "# Construit un vecteur avec les valeurs du taux d'apprentissage à chaque période \n", + "taux = 1e-8*(10**(np.arange(100)/10))\n", + "\n", + "# Affiche l'erreur en fonction du taux d'apprentissage\n", + "plt.figure(figsize=(10, 6))\n", + "plt.semilogx(taux,historique.history[\"loss\"])\n", + "plt.axis([ taux[0], taux[99], 0, 1])\n", + "plt.title(\"Evolution de l'erreur en fonction du taux d'apprentissage\")" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "bSdlJjQLvjjk" + }, + "source": [ + "# Charge les meilleurs poids\n", + "model.load_weights(\"poids.hdf5\")" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "a3-u6kmXtre0" + }, + "source": [ + "from timeit import default_timer as timer\n", + "\n", + "class TimingCallback(keras.callbacks.Callback):\n", + " def __init__(self, logs={}):\n", + " self.logs=[]\n", + " def on_epoch_begin(self, epoch, logs={}):\n", + " self.starttime = timer()\n", + " def on_epoch_end(self, epoch, logs={}):\n", + " self.logs.append(timer()-self.starttime)\n", + "\n", + "# Définition des paramètres liés à l'évolution du taux d'apprentissage\n", + "lr_schedule = tf.keras.optimizers.schedules.InverseTimeDecay(\n", + " initial_learning_rate=0.008,\n", + " decay_steps=10,\n", + " decay_rate=0.1\n", + " )\n", + "\n", + "cb = TimingCallback()\n", + "\n", + "# Définition de l'optimiseur à utiliser\n", + "optimiseur=tf.keras.optimizers.Adam(learning_rate=lr_schedule)\n", + "\n", + "\n", + "# Utilisation de la méthode ModelCheckPoint\n", + "CheckPoint = tf.keras.callbacks.ModelCheckpoint(\"poids_train.hdf5\", monitor='loss', verbose=1, save_best_only=True, save_weights_only = True, mode='auto', save_freq='epoch')\n", + "\n", + "# Compile le modèle\n", + "model.compile(loss=tf.keras.losses.Huber(), optimizer=optimiseur,metrics=\"mae\")\n", + "\n", + "# Entraine le modèle\n", + "historique = model.fit(dataset_norm,validation_data=dataset_Val_norm, epochs=500,verbose=1, callbacks=[CheckPoint,cb])\n", + "\n", + "print(cb.logs)\n", + "print(sum(cb.logs))" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "WdFxSahqtyFl" + }, + "source": [ + "erreur_entrainement = historique.history[\"loss\"]\n", + "erreur_validation = historique.history[\"val_loss\"]\n", + "\n", + "# Affiche l'erreur en fonction de la période\n", + "plt.figure(figsize=(10, 6))\n", + "plt.plot(np.arange(0,len(erreur_entrainement)),erreur_entrainement, label=\"Erreurs sur les entrainements\")\n", + "plt.plot(np.arange(0,len(erreur_entrainement)),erreur_validation, label =\"Erreurs sur les validations\")\n", + "plt.legend()\n", + "\n", + "plt.title(\"Evolution de l'erreur en fonction de la période\")" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "KvxXr8ajt0PT" + }, + "source": [ + "erreur_entrainement = historique.history[\"loss\"]\n", + "erreur_validation = historique.history[\"val_loss\"]\n", + "\n", + "# Affiche l'erreur en fonction de la période\n", + "plt.figure(figsize=(10, 6))\n", + "plt.plot(np.arange(0,len(erreur_entrainement[400:500])),erreur_entrainement[400:500], label=\"Erreurs sur les entrainements\")\n", + "plt.plot(np.arange(0,len(erreur_entrainement[400:500])),erreur_validation[400:500], label =\"Erreurs sur les validations\")\n", + "plt.legend()\n", + "\n", + "plt.title(\"Evolution de l'erreur en fonction de la période\")" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "ylZ7I5l3t20D" + }, + "source": [ + "taille_fenetre = 20\n", + "\n", + "# Création d'une liste vide pour recevoir les prédictions\n", + "predictions = []\n", + "\n", + "# Calcul des prédiction pour chaque groupe de 20 valeurs consécutives de la série\n", + "# dans l'intervalle de validation\n", + "for t in temps[temps_separation:-taille_fenetre]:\n", + " X = np.reshape(Serie_Normalisee[t:t+taille_fenetre],(1,taille_fenetre))\n", + " predictions.append(model.predict(X))" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "AIb_7LJft4wG" + }, + "source": [ + "# Affiche la série et les prédictions\n", + "plt.figure(figsize=(10, 6))\n", + "affiche_serie(temps,serie,label=\"Série temporelle\")\n", + "affiche_serie(temps[temps_separation+taille_fenetre:],np.asarray(predictions*std+mean)[:,0,0],label=\"Prédictions\")\n", + "plt.title('Prédictions avec le modèle GRU avec Auto-Attention')\n", + "plt.show()\n", + "\n", + "# Zoom sur l'intervalle de validation\n", + "plt.figure(figsize=(10, 6))\n", + "affiche_serie(temps[temps_separation:],serie[temps_separation:],label=\"Série temporelle\")\n", + "affiche_serie(temps[temps_separation+taille_fenetre:],np.asarray(predictions*std+mean)[:,0,0],label=\"Prédictions\")\n", + "plt.title(\"Prédictions avec le modèle GRU avec Auto-Attention (zoom sur l'intervalle de validation)\")\n", + "plt.show()" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "UwIpcX-jt6Ms" + }, + "source": [ + "# Calcule de l'erreur quadratique moyenne et de l'erreur absolue moyenne \n", + "\n", + "mae = tf.keras.metrics.mean_absolute_error(serie[temps_separation+taille_fenetre:],np.asarray(predictions*std+mean)[:,0,0]).numpy()\n", + "mse = tf.keras.metrics.mean_squared_error(serie[temps_separation+taille_fenetre:],np.asarray(predictions*std+mean)[:,0,0]).numpy()\n", + "\n", + "print(mae)\n", + "print(mse)" + ], + "execution_count": null, + "outputs": [] + } + ] +} \ No newline at end of file