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": [
+ ""
+ ]
+ },
+ {
+ "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