{"cells":[{"cell_type":"markdown","metadata":{"id":"ojWck8JFNwMp"},"source":["## Partie 3 : 🧠 Approches avancée (embeddings pré-entraînés et deep learning)\n","\n","Dans ce notebook, nous développons des **modèles avancés d'analyse de sentiment** pour détecter les bad buzz potentiels sur Twitter. Nous implémentons deux architectures de deep learning basées sur des réseaux **LSTM bidirectionnels**, utilisant respectivement les embeddings **Word2Vec** et **GloVe 300d** comme représentations vectorielles des mots. Ces modèles exploitent les techniques modernes d'apprentissage profond pour prédire le sentiment de tweets.\n","\n","Concernant l'entrainement, le choix a été fait d'entrainer par optimisation de la variable de perte de validation `val_loss` avec en particulier un critère d'`EarlyStopping` au bout d'un certain nombre d'époques lancées (5, en l'ocurrence) afin de garantir une bonne généralisation ainsi qu'une limitation de l'overfitting.\n","\n","Cependant, le critère qui sera retenu comme le plus important en raison de notre problématique métier est la `precision` car nous souhaitons plus que tout éviter les faux positifs (tweet prédit comme positif, alors qu'il sera mal reçu)."]},{"cell_type":"markdown","metadata":{"id":"hQ2lFBinNwMq"},"source":["## Importation des bibliothèques"]},{"cell_type":"code","source":["from google.colab import drive\n","drive.mount('/content/drive')\n","import os\n","drive_folder= \"/content/drive/MyDrive/Colab_Notebooks/Project_7/notebooks\"\n","os.chdir(drive_folder)\n","os.listdir()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"khhtDEa-Phih","executionInfo":{"status":"ok","timestamp":1751829649428,"user_tz":-120,"elapsed":962,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}},"outputId":"ce7f19f8-a0ca-4fcf-fa46-ce54b3c96da7"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount(\"/content/drive\", force_remount=True).\n"]},{"output_type":"execute_result","data":{"text/plain":["['content',\n"," 'requirements_analyse_exploratoire.txt',\n"," 'p07_01-notebook-analyse-exploratoire.ipynb',\n"," 'requirements_bert.txt',\n"," 'requirements_modele_avance.txt',\n"," 'p07_03-notebook-modele-avance.ipynb',\n"," 'requirements_modele_simple.txt',\n"," 'p07_02-notebook-modele-simple.ipynb',\n"," 'p07_04-notebook-modele-bert.ipynb',\n"," 'notebook-connexion-mlflow.ipynb']"]},"metadata":{},"execution_count":1}]},{"cell_type":"code","source":["!pip install mlflow boto3 dotenv gensim --quiet"],"metadata":{"id":"vN2rVNmf86bI"},"execution_count":null,"outputs":[]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Ae66AtL4NwMq","executionInfo":{"status":"ok","timestamp":1751829672248,"user_tz":-120,"elapsed":11453,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}},"colab":{"base_uri":"https://localhost:8080/"},"outputId":"b8b32a26-9249-40fa-f306-7bcaf14d3061"},"outputs":[{"output_type":"stream","name":"stderr","text":["[nltk_data] Downloading package punkt to /root/nltk_data...\n","[nltk_data] Unzipping tokenizers/punkt.zip.\n","[nltk_data] Downloading package punkt_tab to /root/nltk_data...\n","[nltk_data] Unzipping tokenizers/punkt_tab.zip.\n","[nltk_data] Downloading package stopwords to /root/nltk_data...\n","[nltk_data] Unzipping corpora/stopwords.zip.\n","[nltk_data] Downloading package wordnet to /root/nltk_data...\n","[nltk_data] Downloading package omw-1.4 to /root/nltk_data...\n"]}],"source":["# Importations nécessaires\n","import os\n","import sys\n","import pandas as pd\n","import numpy as np\n","import matplotlib.pyplot as plt\n","import seaborn as sns\n","import time\n","import warnings\n","from collections import Counter\n","import pickle\n","from tqdm import tqdm\n","\n","# Importations scikit-learn\n","from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer\n","from sklearn.model_selection import train_test_split, GridSearchCV\n","from sklearn.linear_model import LogisticRegression\n","from sklearn.svm import LinearSVC\n","from sklearn.ensemble import RandomForestClassifier\n","from sklearn.naive_bayes import MultinomialNB\n","from sklearn.metrics import (accuracy_score, precision_score, recall_score, f1_score,\n"," make_scorer, matthews_corrcoef, balanced_accuracy_score,\n"," classification_report, confusion_matrix, roc_auc_score, roc_curve)\n","\n","\n","import numpy as np\n","import tensorflow as tf\n","from tensorflow import keras\n","from tensorflow.keras.preprocessing.text import Tokenizer\n","from tensorflow.keras.preprocessing.sequence import pad_sequences\n","\n","# Ajoute le dossier parent au path\n","sys.path.append(os.path.abspath(\"..\"))\n","\n","# Maintenant tu peux importer ton module\n","from functions import convert_sentiment_label, downsample_data, preprocess_tweet, process_in_parallel, apply_preprocessing\n","\n","\n","# Configuration des visualisations\n","plt.style.use('ggplot')\n","plt.rcParams['figure.figsize'] = (12, 8)\n","plt.rcParams['font.family'] = 'DejaVu Sans'\n","warnings.filterwarnings('ignore')"]},{"cell_type":"markdown","metadata":{"id":"E1TqvSBHNwMr"},"source":["## 💾 Jeu de données : Sentiment140\n","\n","Le jeu de données [Sentiment140 dataset with 1.6 million tweets](https://www.kaggle.com/datasets/kazanova/sentiment140) est une ressource majeure pour l'analyse de sentiment sur Twitter, comprenant **1,6 million de tweets** extraits via l'API Twitter. Ces tweets ont été automatiquement annotés selon leur polarité sentimentale, offrant une base solide pour développer des modèles de classification de sentiment.\n","\n","Le jeu de données est organisé en 6 colonnes distinctes :\n","\n","1. **target** : La polarité du sentiment exprimé dans le tweet.\n"," - 0 = sentiment négatif\n"," - 2 = sentiment neutre\n"," - 4 = sentiment positif\n","2. **ids** : L'identifiant unique du tweet (exemple : *2087*)\n","3. **date** : La date et l'heure de publication du tweet.\n","4. **flag** : La requête utilisée pour obtenir le tweet.\n"," - Exemple : *lyx*\n"," - Si aucune requête n'a été utilisée : *NO_QUERY*\n","5. **user** : Le nom d'utilisateur de l'auteur du tweet.\n","6. **text** : Le contenu textuel du tweet."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"jDsgh8mGNwMr","outputId":"e0836993-b471-4040-e453-ce648a7ebefd","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1751829672256,"user_tz":-120,"elapsed":9,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}}},"outputs":[{"output_type":"stream","name":"stdout","text":["CPU times: user 58 µs, sys: 0 ns, total: 58 µs\n","Wall time: 460 µs\n"]}],"source":["%%time\n","\n","# Define the URL and the local file path\n","url = \"https://s3-eu-west-1.amazonaws.com/static.oc-static.com/prod/courses/files/AI+Engineer/Project+7%C2%A0-+D%C3%A9tectez+les+Bad+Buzz+gr%C3%A2ce+au+Deep+Learning/sentiment140.zip\"\n","local_zip_path = \"./content/data/sentiment140.zip\"\n","extract_path = \"./content/data\"\n","\n","if not os.path.exists(extract_path):\n","\n"," # Create the directory if it doesn't exist\n"," os.makedirs(extract_path, exist_ok=True)\n","\n"," # Download the zip file\n"," response = requests.get(url)\n"," with open(local_zip_path, 'wb') as file:\n"," file.write(response.content)\n","\n"," # Extract the contents of the zip file\n"," with zipfile.ZipFile(local_zip_path, 'r') as zip_ref:\n"," zip_ref.extractall(extract_path)\n","\n"," # Delete the zip file\n"," os.remove(local_zip_path)"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"c-6C8QR_NwMr"},"outputs":[],"source":["pd.set_option('display.max_columns', None)\n","pd.set_option('display.expand_frame_repr', True)"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"MtMJv7S-NwMr","outputId":"4b66b3a9-3182-4541-8683-22eaed885d24","colab":{"base_uri":"https://localhost:8080/","height":206},"executionInfo":{"status":"ok","timestamp":1751829684281,"user_tz":-120,"elapsed":12010,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}}},"outputs":[{"output_type":"execute_result","data":{"text/plain":[" target ids date flag \\\n","0 0 1467810369 Mon Apr 06 22:19:45 PDT 2009 NO_QUERY \n","1 0 1467810672 Mon Apr 06 22:19:49 PDT 2009 NO_QUERY \n","2 0 1467810917 Mon Apr 06 22:19:53 PDT 2009 NO_QUERY \n","3 0 1467811184 Mon Apr 06 22:19:57 PDT 2009 NO_QUERY \n","4 0 1467811193 Mon Apr 06 22:19:57 PDT 2009 NO_QUERY \n","\n"," user text \n","0 _TheSpecialOne_ @switchfoot http://twitpic.com/2y1zl - Awww, t... \n","1 scotthamilton is upset that he can't update his Facebook by ... \n","2 mattycus @Kenichan I dived many times for the ball. Man... \n","3 ElleCTF my whole body feels itchy and like its on fire \n","4 Karoli @nationwideclass no, it's not behaving at all.... "],"text/html":["\n","
\n","
\n","\n","
\n"," \n","
\n","
\n","
target
\n","
ids
\n","
date
\n","
flag
\n","
user
\n","
text
\n","
\n"," \n"," \n","
\n","
0
\n","
0
\n","
1467810369
\n","
Mon Apr 06 22:19:45 PDT 2009
\n","
NO_QUERY
\n","
_TheSpecialOne_
\n","
@switchfoot http://twitpic.com/2y1zl - Awww, t...
\n","
\n","
\n","
1
\n","
0
\n","
1467810672
\n","
Mon Apr 06 22:19:49 PDT 2009
\n","
NO_QUERY
\n","
scotthamilton
\n","
is upset that he can't update his Facebook by ...
\n","
\n","
\n","
2
\n","
0
\n","
1467810917
\n","
Mon Apr 06 22:19:53 PDT 2009
\n","
NO_QUERY
\n","
mattycus
\n","
@Kenichan I dived many times for the ball. Man...
\n","
\n","
\n","
3
\n","
0
\n","
1467811184
\n","
Mon Apr 06 22:19:57 PDT 2009
\n","
NO_QUERY
\n","
ElleCTF
\n","
my whole body feels itchy and like its on fire
\n","
\n","
\n","
4
\n","
0
\n","
1467811193
\n","
Mon Apr 06 22:19:57 PDT 2009
\n","
NO_QUERY
\n","
Karoli
\n","
@nationwideclass no, it's not behaving at all....
\n","
\n"," \n","
\n","
\n","
\n","\n","
\n"," \n","\n"," \n","\n"," \n","
\n","\n","\n","
\n"," \n","\n","\n","\n"," \n","
\n","\n","
\n","
\n"],"application/vnd.google.colaboratory.intrinsic+json":{"type":"dataframe","variable_name":"raw_data"}},"metadata":{},"execution_count":6}],"source":["# Define the path to the CSV file\n","csv_file_path = os.path.join(extract_path, 'training.1600000.processed.noemoticon.csv')\n","\n","# Define the column names\n","column_names = ['target', 'ids', 'date', 'flag', 'user', 'text']\n","\n","# Load the dataset into a pandas DataFrame\n","raw_data = pd.read_csv(csv_file_path, encoding='latin-1', names=column_names)\n","\n","# Display the first few rows of the DataFrame\n","raw_data.head()"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"bIeawbN6NwMs","outputId":"a847e733-a6cc-4635-cd01-0bc887dc7bfd","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1751829684282,"user_tz":-120,"elapsed":5,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}}},"outputs":[{"output_type":"stream","name":"stdout","text":["Ce dataframe contient 1600000 lignes et 6 colonnes.\n"]}],"source":["print(f\"Ce dataframe contient {raw_data.shape[0]} lignes et {raw_data.shape[1]} colonnes.\")"]},{"cell_type":"markdown","source":["## ⏩🧠 Approches avancées de Deep Learning\n","Notre démarche pour la classification de sentiment avec des approches avancées comprend:\n","\n","1. **Prétraitement des tweets**\n"," - Nettoyage\n"," - Tokenisation et lemmatisation\n"," - Remplacement des URLs et mentions par des tokens spéciaux\n","\n","3. **Modèles testés**\n"," - **Modèle LSTM bidirectionnel avec Word2Vec:** Ce modèle utilisera une architecture de réseau de neurones récurrents (LSTM) bidirectionnel et les embeddings pré-entraînés **Word2Vec** pour représenter les mots.\n"," - **Modèle LSTM bidirectionnel avec GloVe 300d:** Ce modèle similaire utilisera également une architecture LSTM bidirectionnel, mais avec les embeddings pré-entraînés **GloVe de dimension 300**.\n","\n","\n","3. **Évaluation et suivi**\n"," - Métriques: précision, accuracy, recall, F1-score, ROC-AUC\n"," - Tracking avec MLflow pour la reproductibilité et la comparaison\n","\n","\n","Il est important de noter que l'entraînement est fait sur un sous-échantillon et non sur l'intégralité du dataset."],"metadata":{"id":"Lq2h1qmW2PqP"}},{"cell_type":"markdown","metadata":{"id":"UXHYqYWiNwMs"},"source":["## Prétraitement\n","\n","Notre démarche pour la classification de sentiment avec des approches classiques comprend:\n","\n","1. **Prétraitement des tweets**\n"," - Nettoyage\n"," - Tokenisation et lemmatisation\n"," - Remplacement des URLs et mentions par des tokens spéciaux\n","\n"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"XC0M0gPXNwMs"},"outputs":[],"source":["converted_target_data = convert_sentiment_label(raw_data)"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"gMSXKh2RNwMs","outputId":"d9635826-13f5-464f-f230-0bd4a0d6c743","colab":{"base_uri":"https://localhost:8080/","height":178},"executionInfo":{"status":"ok","timestamp":1751829686127,"user_tz":-120,"elapsed":2,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}}},"outputs":[{"output_type":"execute_result","data":{"text/plain":["target\n","0 800000\n","1 800000\n","Name: count, dtype: int64"],"text/html":["
"]},"metadata":{},"execution_count":10}],"source":["sample_size = 100000\n","downsampled_data = downsample_data(converted_target_data, n_samples=sample_size)\n","downsampled_data['target'].value_counts()"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"f2CkXR7XNwMt","outputId":"62b2f9e7-3dcb-49fe-e366-aff4eb32c5c1","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1751829778185,"user_tz":-120,"elapsed":90859,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}}},"outputs":[{"output_type":"stream","name":"stdout","text":["Prétraitement des tweets en cours...\n","Prétraitement terminé !\n"]}],"source":["# Appliquer le prétraitement à tous les tweets\n","print(\"Prétraitement des tweets en cours...\")\n","preprocessed_data = process_in_parallel(downsampled_data, apply_preprocessing, n_jobs=8)\n","print(\"Prétraitement terminé !\")"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"LN5ul0JBNwMt","outputId":"cb4d7277-bbce-4bc8-b424-9b406f9ab93a","colab":{"base_uri":"https://localhost:8080/","height":206},"executionInfo":{"status":"ok","timestamp":1751829778186,"user_tz":-120,"elapsed":4,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}}},"outputs":[{"output_type":"execute_result","data":{"text/plain":[" target ids date flag \\\n","212188 0 1974671194 Sat May 30 13:36:31 PDT 2009 NO_QUERY \n","299036 0 1997882236 Mon Jun 01 17:37:11 PDT 2009 NO_QUERY \n","475978 0 2177756662 Mon Jun 15 06:39:05 PDT 2009 NO_QUERY \n","588988 0 2216838047 Wed Jun 17 20:02:12 PDT 2009 NO_QUERY \n","138859 0 1880666283 Fri May 22 02:03:31 PDT 2009 NO_QUERY \n","\n"," user text \\\n","212188 simba98 @xnausikaax oh no! where did u order from? tha... \n","299036 Seve76 A great hard training weekend is over. a coup... \n","475978 x__claireyy__x Right, off to work Only 5 hours to go until I... \n","588988 Balasi I am craving for japanese food \n","138859 djrickdawson Jean Michel Jarre concert tomorrow gotta work... \n","\n"," processed_text \n","212188 < MENTION > oh no ! u order ? thats horrible \n","299036 great hard training weekend couple day rest le... \n","475978 right work 5 hour go im free xd \n","588988 craving japanese food \n","138859 jean michel jarre concert tomorrow got ta work... "],"text/html":["\n","
\n","
\n","\n","
\n"," \n","
\n","
\n","
target
\n","
ids
\n","
date
\n","
flag
\n","
user
\n","
text
\n","
processed_text
\n","
\n"," \n"," \n","
\n","
212188
\n","
0
\n","
1974671194
\n","
Sat May 30 13:36:31 PDT 2009
\n","
NO_QUERY
\n","
simba98
\n","
@xnausikaax oh no! where did u order from? tha...
\n","
< MENTION > oh no ! u order ? thats horrible
\n","
\n","
\n","
299036
\n","
0
\n","
1997882236
\n","
Mon Jun 01 17:37:11 PDT 2009
\n","
NO_QUERY
\n","
Seve76
\n","
A great hard training weekend is over. a coup...
\n","
great hard training weekend couple day rest le...
\n","
\n","
\n","
475978
\n","
0
\n","
2177756662
\n","
Mon Jun 15 06:39:05 PDT 2009
\n","
NO_QUERY
\n","
x__claireyy__x
\n","
Right, off to work Only 5 hours to go until I...
\n","
right work 5 hour go im free xd
\n","
\n","
\n","
588988
\n","
0
\n","
2216838047
\n","
Wed Jun 17 20:02:12 PDT 2009
\n","
NO_QUERY
\n","
Balasi
\n","
I am craving for japanese food
\n","
craving japanese food
\n","
\n","
\n","
138859
\n","
0
\n","
1880666283
\n","
Fri May 22 02:03:31 PDT 2009
\n","
NO_QUERY
\n","
djrickdawson
\n","
Jean Michel Jarre concert tomorrow gotta work...
\n","
jean michel jarre concert tomorrow got ta work...
\n","
\n"," \n","
\n","
\n","
\n","\n","
\n"," \n","\n"," \n","\n"," \n","
\n","\n","\n","
\n"," \n","\n","\n","\n"," \n","
\n","\n","
\n","
\n"],"application/vnd.google.colaboratory.intrinsic+json":{"type":"dataframe","variable_name":"preprocessed_data"}},"metadata":{},"execution_count":12}],"source":["preprocessed_data.head()"]},{"cell_type":"markdown","metadata":{"id":"zyb9Fj38NwMt"},"source":["## Division des données en ensembles d'entraînement et de test"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Z_y6Ja0INwMt","outputId":"900bbf3f-2716-478d-b03b-8f04f23a819f","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1751829778219,"user_tz":-120,"elapsed":35,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}}},"outputs":[{"output_type":"stream","name":"stdout","text":["Taille de l'ensemble d'entraînement: 160000 exemples\n","Taille de l'ensemble de test: 40000 exemples\n"]}],"source":["# Diviser les données en ensembles d'entraînement et de test\n","from sklearn.model_selection import train_test_split\n","\n","X = preprocessed_data['processed_text']\n","y = preprocessed_data['target']\n","\n","# Division train/test\n","X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)\n","\n","print(f\"Taille de l'ensemble d'entraînement: {X_train.shape[0]} exemples\")\n","print(f\"Taille de l'ensemble de test: {X_test.shape[0]} exemples\")"]},{"cell_type":"markdown","metadata":{"id":"wPE9r-G4NwMt"},"source":["## Entraînement des modèles et tracking avec MLflow"]},{"cell_type":"markdown","metadata":{"id":"zpsZDWuANwMt"},"source":["### Configuration de MLFlow"]},{"cell_type":"code","source":["import mlflow\n","import mlflow.keras\n","from mlflow.models import infer_signature\n","from mlflow import MlflowClient\n","from dotenv import load_dotenv\n","\n","# Charger les variables d'environnement depuis le fichier .env\n","load_dotenv(dotenv_path='../.env')\n","\n","# Configuration de MLflow avec les variables d'environnement\n","mlflow_tracking_uri = os.getenv(\"MLFLOW_TRACKING_URI\")\n","mlflow_s3_endpoint_url = os.getenv(\"MLFLOW_S3_ENDPOINT_URL\")\n","aws_access_key_id = os.getenv(\"AWS_ACCESS_KEY_ID\")\n","aws_secret_access_key = os.getenv(\"AWS_SECRET_ACCESS_KEY\")\n","\n","# Configuration explicite de MLflow\n","mlflow.set_tracking_uri(mlflow_tracking_uri)\n","print(f\"MLflow Tracking URI: {mlflow_tracking_uri}\")\n","\n","# Configuration explicite des identifiants AWS\n","os.environ[\"MLFLOW_S3_ENDPOINT_URL\"] = mlflow_s3_endpoint_url\n","os.environ[\"AWS_ACCESS_KEY_ID\"] = aws_access_key_id\n","os.environ[\"AWS_SECRET_ACCESS_KEY\"] = aws_secret_access_key\n","print(\"Identifiants AWS configurés\")"],"metadata":{"id":"qoQ4njujN758","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1751829780115,"user_tz":-120,"elapsed":1895,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}},"outputId":"c3bd3672-bdfe-41cf-e3ea-4f05c5dc85e9"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["MLflow Tracking URI: https://mlflow.greg-madman-nas.duckdns.org/\n","Identifiants AWS configurés\n"]}]},{"cell_type":"code","execution_count":null,"metadata":{"id":"CZ7unEtvNwMt","outputId":"9d070ad6-ba13-4f7d-d0bc-59415062d3b7","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1751829782348,"user_tz":-120,"elapsed":2232,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}}},"outputs":[{"output_type":"execute_result","data":{"text/plain":[""]},"metadata":{},"execution_count":15}],"source":["# Créer l'expérience MLflow\n","mlflow.set_experiment(\"OC Projet 7\")"]},{"cell_type":"markdown","metadata":{"id":"33JkcVxcNwMt"},"source":["## Préparation des données pour les modèles de deep learning\n","\n","D'abord, nous devons tokeniser nos textes et les préparer pour l'entraînement des modèles de deep learning."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"WKfNMY_JNwMt","outputId":"db116bc5-51d4-4ca0-d4ec-3bcbf92e763f","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1751829788323,"user_tz":-120,"elapsed":5944,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}}},"outputs":[{"output_type":"stream","name":"stdout","text":["Taille du vocabulaire: 83731\n","Forme des données d'entraînement: (160000, 50)\n","Forme des données de test: (40000, 50)\n"]}],"source":["# Définir la longueur maximale des séquences (nombre de mots par tweet)\n","MAX_SEQUENCE_LENGTH = 50\n","\n","# Définir la taille du vocabulaire (nombre de mots uniques à considérer)\n","MAX_VOCAB_SIZE = 20000\n","\n","# Tokenisation des textes\n","tokenizer = Tokenizer(num_words=MAX_VOCAB_SIZE, oov_token='')\n","tokenizer.fit_on_texts(X_train)\n","\n","# Convertir les textes en séquences d'indices\n","X_train_seq = tokenizer.texts_to_sequences(X_train)\n","X_test_seq = tokenizer.texts_to_sequences(X_test)\n","\n","# Padding des séquences pour qu'elles aient toutes la même longueur\n","X_train_pad = pad_sequences(X_train_seq, maxlen=MAX_SEQUENCE_LENGTH, padding='post', truncating='post')\n","X_test_pad = pad_sequences(X_test_seq, maxlen=MAX_SEQUENCE_LENGTH, padding='post', truncating='post')\n","\n","# Créer le dossier pour sauvegarder les modèles\n","os.makedirs(\"content/advanced-model\", exist_ok=True)\n","# os.makedirs(\"content/advanced-model/best\", exist_ok=True)\n","\n","# Sauvegarder le tokenizer pour une utilisation ultérieure\n","import pickle\n","with open('content/advanced-model/tokenizer.pickle', 'wb') as handle:\n"," pickle.dump(tokenizer, handle, protocol=pickle.HIGHEST_PROTOCOL)\n","\n","print(f\"Taille du vocabulaire: {len(tokenizer.word_index) + 1}\")\n","print(f\"Forme des données d'entraînement: {X_train_pad.shape}\")\n","print(f\"Forme des données de test: {X_test_pad.shape}\")"]},{"cell_type":"markdown","metadata":{"id":"876rS4__NwMt"},"source":["## Fonctions d'évaluation"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"OrUjzG-6NwMt"},"outputs":[],"source":["def evaluate_model(model, X_test, y_test, class_names=['Négatif', 'Positif']):\n"," \"\"\"\n"," Évalue le modèle sur l'ensemble de test et retourne les métriques de performance.\n"," \"\"\"\n"," # Prédictions du modèle\n"," y_pred_proba = model.predict(X_test)\n"," y_pred = (y_pred_proba > 0.5).astype(int)\n","\n"," # Convertir les prédictions de format numpy à format list pour éviter les erreurs de sérialisation\n"," if isinstance(y_pred, np.ndarray):\n"," y_pred = y_pred.flatten().tolist()\n"," if isinstance(y_pred_proba, np.ndarray):\n"," y_pred_proba = y_pred_proba.flatten().tolist()\n","\n"," # Calculer les métriques\n"," accuracy = accuracy_score(y_test, y_pred)\n"," precision = precision_score(y_test, y_pred)\n"," recall = recall_score(y_test, y_pred)\n"," f1 = f1_score(y_test, y_pred)\n"," roc_auc = roc_auc_score(y_test, y_pred_proba)\n","\n"," # Matrice de confusion\n"," cm = confusion_matrix(y_test, y_pred)\n","\n"," # Rapport de classification\n"," report = classification_report(y_test, y_pred, target_names=class_names)\n","\n"," metrics = {\n"," 'accuracy': accuracy,\n"," 'precision': precision,\n"," 'recall': recall,\n"," 'f1': f1,\n"," 'roc_auc': roc_auc\n"," }\n","\n"," return metrics, cm, report, y_pred, y_pred_proba\n","\n","def plot_confusion_matrix(cm, class_names, title='Matrice de confusion'):\n"," \"\"\"\n"," Crée une figure de matrice de confusion.\n"," \"\"\"\n"," fig, ax = plt.subplots(figsize=(8, 6))\n"," im = ax.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)\n"," ax.figure.colorbar(im, ax=ax)\n"," ax.set(xticks=np.arange(cm.shape[1]),\n"," yticks=np.arange(cm.shape[0]),\n"," xticklabels=class_names,\n"," yticklabels=class_names,\n"," title=title,\n"," ylabel='Vraie étiquette',\n"," xlabel='Étiquette prédite')\n","\n"," # Pivoter les labels de l'axe des x\n"," plt.setp(ax.get_xticklabels(), rotation=45, ha=\"right\", rotation_mode=\"anchor\")\n","\n"," # Annoter la matrice de confusion\n"," thresh = cm.max() / 2.\n"," for i in range(cm.shape[0]):\n"," for j in range(cm.shape[1]):\n"," ax.text(j, i, format(cm[i, j], 'd'),\n"," ha=\"center\", va=\"center\",\n"," color=\"white\" if cm[i, j] > thresh else \"black\")\n","\n"," plt.tight_layout()\n"," return fig\n"]},{"cell_type":"markdown","metadata":{"id":"3_YfW-7yNwMt"},"source":["## Fonction de logging pour MLflow"]},{"cell_type":"code","source":["def log_model_to_mlflow(model, model_name, vectorizer_name, metrics, cm, report, X_test, y_test, history=None, params=None):\n"," \"\"\"\n"," Enregistre le modèle et ses performances dans MLflow.\n"," \"\"\"\n"," class_names = ['Négatif', 'Positif']\n","\n"," with mlflow.start_run(run_name=f\"Modele_Avance_{model_name}_{vectorizer_name}\"):\n"," # Enregistrer les paramètres du modèle\n"," if params:\n"," for key, value in params.items():\n"," mlflow.log_param(key, value)\n","\n"," # Enregistrer les métriques de validation issues de l'entraînement\n"," if history is not None:\n"," hist = history.history\n"," if 'val_precision' in hist:\n"," best_epoch = int(np.argmax(hist['val_precision']))\n"," mlflow.log_metric(\"val_precision\", float(hist['val_precision'][best_epoch]))\n"," if 'val_loss' in hist:\n"," mlflow.log_metric(\"val_loss\", float(hist['val_loss'][best_epoch]))\n"," if 'val_recall' in hist:\n"," mlflow.log_metric(\"val_recall\", float(hist['val_recall'][best_epoch]))\n","\n"," # Enregistrer les métriques de performance\n"," for key, value in metrics.items():\n"," mlflow.log_metric('test_' + key, value)\n","\n"," # Tracer et enregistrer la matrice de confusion\n"," fig = plot_confusion_matrix(cm, class_names)\n"," mlflow.log_figure(fig, f\"confusion_matrix_{model_name}_{vectorizer_name}.png\")\n"," plt.close(fig)\n","\n"," # Enregistrer le rapport de classification\n"," report_path = f\"content/advanced-model/{model_name}_{vectorizer_name}/classification_report.txt\"\n"," os.makedirs(os.path.dirname(report_path), exist_ok=True)\n"," with open(report_path, \"w\") as f:\n"," f.write(report)\n"," mlflow.log_artifact(report_path)\n","\n"," # Enregistrer le modèle dans MLflow\n"," signature = infer_signature(X_test, y_test)\n"," mlflow.keras.log_model(\n"," model,\n"," f\"model_{model_name}_{vectorizer_name}\",\n"," signature=signature\n"," )\n","\n"," # Log du dossier local qui contient déjà tous les artefacts\n"," artifact_dir = f\"content/advanced-model/{model_name}_{vectorizer_name}\"\n"," if os.path.exists(artifact_dir):\n"," mlflow.log_artifacts(artifact_dir, \"local_artifacts\")\n","\n"," return mlflow.active_run().info.run_id\n","\n","\n","def plot_training_history(history, model_name, vectorizer_name, run_id=None):\n"," \"\"\"\n"," Trace l'historique d'entraînement du modèle et l'enregistre dans la même exécution MLflow.\n","\n"," Args:\n"," history: Historique d'entraînement du modèle\n"," model_name: Nom du modèle\n"," vectorizer_name: Nom du vectoriseur\n"," run_id: ID de l'exécution MLflow existante\n","\n"," Returns:\n"," fig: Figure matplotlib créée\n"," \"\"\"\n"," fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))\n","\n"," # Tracer precision (train & val)\n"," ax1.plot(history.history['precision'], label='train')\n"," ax1.plot(history.history['val_precision'], label='validation')\n"," ax1.set_title(f'Précision - {model_name} avec {vectorizer_name}')\n"," ax1.set_xlabel('Epoch')\n"," ax1.set_ylabel('Précision')\n"," ax1.legend()\n","\n"," # Tracer loss (train & val)\n"," ax2.plot(history.history['loss'], label='train')\n"," ax2.plot(history.history['val_loss'], label='validation')\n"," ax2.set_title(f'Loss - {model_name} avec {vectorizer_name}')\n"," ax2.set_xlabel('Epoch')\n"," ax2.set_ylabel('Loss')\n"," ax2.legend()\n","\n","\n"," plt.tight_layout()\n","\n"," # Sauvegarder la figure localement\n"," filename = f'content/advanced-model/training_history_{model_name}_{vectorizer_name}.png'\n"," plt.savefig(filename)\n","\n"," # Enregistrer dans MLflow en utilisant l'exécution existante\n"," if run_id:\n"," with mlflow.start_run(run_id=run_id):\n"," mlflow.log_figure(fig, f\"training_history_{model_name}_{vectorizer_name}.png\")\n"," else:\n"," # Fallback si aucun run_id n'est fourni\n"," with mlflow.start_run(run_name=f\"ModeleAvance_{model_name}_{vectorizer_name}\"):\n"," mlflow.log_figure(fig, f\"training_history_{model_name}_{vectorizer_name}.png\")"],"metadata":{"id":"etdkfzD9x8t3"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"1UorrWtSNwMu"},"source":["## Chargement et préparation des embeddings pré-entraînés"]},{"cell_type":"markdown","metadata":{"id":"yzl1y9HSNwMu"},"source":["### Word2vec"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"K0hDRRZmNwMu","outputId":"f27eb320-f434-478d-defd-62e9b14d7e05","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1751829788865,"user_tz":-120,"elapsed":511,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}}},"outputs":[{"output_type":"stream","name":"stdout","text":["Word2Vec model already exists at content/pretrained-embeddings/word2vec/GoogleNews-vectors-negative300.bin\n","Word2Vec model is available at: content/pretrained-embeddings/word2vec/GoogleNews-vectors-negative300.bin\n"]}],"source":["def download_word2vec():\n"," \"\"\"\n"," Downloads the pre-trained Word2Vec embeddings.\n"," Creates the necessary directories, downloads the file, extracts it, and cleans up unneeded files.\n","\n"," Returns:\n"," str: Path to the extracted Word2Vec model file\n"," \"\"\"\n"," import os\n"," import gzip\n"," import shutil\n"," from urllib.request import urlretrieve\n"," import time\n"," import zipfile\n","\n"," # Create necessary directories\n"," content_dir = 'content/pretrained-embeddings'\n"," word2vec_dir = os.path.join(content_dir, 'word2vec')\n","\n"," os.makedirs(word2vec_dir, exist_ok=True)\n","\n"," # Define file paths\n"," model_file = os.path.join(word2vec_dir, 'GoogleNews-vectors-negative300.bin')\n"," zip_file = os.path.join(word2vec_dir, 'GoogleNews-vectors-negative300.bin.zip')\n","\n"," # Skip download if file already exists\n"," if os.path.exists(model_file):\n"," print(f\"Word2Vec model already exists at {model_file}\")\n"," return model_file\n","\n"," # URL for the pre-trained Word2Vec embeddings\n"," # Using huggingface repository as a reliable source\n"," url = 'https://huggingface.co/fse/word2vec-google-news-300/resolve/main/GoogleNews-vectors-negative300.bin.gz'\n","\n"," try:\n"," # Download the file with progress reporting\n"," print(f\"Downloading Word2Vec embeddings from {url}...\")\n"," print(\"This may take a while as the file is ~1.5GB\")\n","\n"," start_time = time.time()\n","\n"," def progress_callback(count, block_size, total_size):\n"," elapsed_time = time.time() - start_time\n"," downloaded = count * block_size / (1024 * 1024) # MB\n"," total = total_size / (1024 * 1024) if total_size > 0 else 0 # MB\n"," percent = min(100, count * block_size * 100 / total_size) if total_size > 0 else 0\n"," speed = downloaded / elapsed_time if elapsed_time > 0 else 0\n","\n"," print(f\"\\rDownloaded: {downloaded:.1f}MB / {total:.1f}MB ({percent:.1f}%) - {speed:.1f}MB/s\",\n"," end='', flush=True)\n","\n"," gz_file = os.path.join(word2vec_dir, 'GoogleNews-vectors-negative300.bin.gz')\n"," urlretrieve(url, gz_file, progress_callback)\n"," print(\"\\nDownload complete!\")\n","\n"," # Extract the gzip file\n"," print(f\"Extracting {gz_file}...\")\n"," with gzip.open(gz_file, 'rb') as f_in:\n"," with open(model_file, 'wb') as f_out:\n"," shutil.copyfileobj(f_in, f_out)\n"," print(\"Extraction complete!\")\n","\n"," # Delete the gzip file to save space\n"," os.remove(gz_file)\n"," print(f\"Deleted temporary file: {gz_file}\")\n","\n"," return model_file\n","\n"," except Exception as e:\n"," print(f\"Error downloading or extracting Word2Vec embeddings: {str(e)}\")\n"," print(\"\\nTrying alternative download source...\")\n","\n"," # Alternative URL (Google Drive mirror)\n"," try:\n"," # Install gdown if not available\n"," import subprocess\n"," import sys\n","\n"," def install_gdown():\n"," subprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"gdown\"])\n","\n"," try:\n"," import gdown\n"," except ImportError:\n"," print(\"Installing gdown package for Google Drive downloads...\")\n"," install_gdown()\n"," import gdown\n","\n"," # Google Drive file ID for Word2Vec\n"," file_id = \"0B7XkCwpI5KDYNlNUTTlSS21pQmM\"\n","\n"," print(f\"Downloading Word2Vec embeddings from Google Drive (ID: {file_id})...\")\n"," output = gz_file\n"," gdown.download(id=file_id, output=output, quiet=False)\n","\n"," # Extract the gzip file\n"," print(f\"Extracting {gz_file}...\")\n"," with gzip.open(gz_file, 'rb') as f_in:\n"," with open(model_file, 'wb') as f_out:\n"," shutil.copyfileobj(f_in, f_out)\n"," print(\"Extraction complete!\")\n","\n"," # Delete the gzip file to save space\n"," os.remove(gz_file)\n"," print(f\"Deleted temporary file: {gz_file}\")\n","\n"," return model_file\n","\n"," except Exception as alt_error:\n"," print(f\"Error with alternative download: {str(alt_error)}\")\n","\n"," # Final fallback: direct user to manual download\n"," print(\"\\nAutomatic download failed. Please follow these manual steps:\")\n"," print(\"1. Download the Word2Vec embeddings from: https://drive.google.com/file/d/0B7XkCwpI5KDYNlNUTTlSS21pQmM/view?usp=sharing\")\n"," print(\"2. Extract the downloaded file\")\n"," print(f\"3. Place the 'GoogleNews-vectors-negative300.bin' file in the '{word2vec_dir}' directory\")\n","\n"," # Clean up any partial downloads\n"," if os.path.exists(gz_file):\n"," os.remove(gz_file)\n"," if os.path.exists(model_file) and os.path.getsize(model_file) < 1000000: # If file exists but is too small\n"," os.remove(model_file)\n","\n"," raise Exception(\"Failed to download Word2Vec embeddings automatically. Please download manually.\")\n","\n","# Example usage:\n","model_path = download_word2vec()\n","print(f\"Word2Vec model is available at: {model_path}\")"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"WMvPJS5tNwMu"},"outputs":[],"source":["from gensim.models import KeyedVectors\n","\n","def load_word2vec_embeddings():\n"," \"\"\"\n"," Charge les embeddings Word2Vec pré-entraînés.\n"," \"\"\"\n"," print(\"Chargement des embeddings Word2Vec...\")\n","\n"," # Charger le modèle Word2Vec\n"," word2vec_model = KeyedVectors.load_word2vec_format('content/pretrained-embeddings/word2vec/GoogleNews-vectors-negative300.bin', binary=True, limit=500000)\n","\n"," # Convertir en dictionnaire pour une utilisation plus facile\n"," embeddings_index = {}\n"," for word in word2vec_model.key_to_index:\n"," embeddings_index[word] = word2vec_model[word]\n","\n"," print(f\"Trouvé {len(embeddings_index)} vecteurs d'embeddings Word2Vec.\")\n"," return embeddings_index"]},{"cell_type":"markdown","metadata":{"id":"Xor_kNOVNwMu"},"source":["## Création des matrices d'embedding à partir des embeddings pré-entraînés"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"H1nz57olNwMu"},"outputs":[],"source":["def create_embedding_matrix(word_index, embeddings_index, embedding_dim):\n"," \"\"\"\n"," Crée une matrice d'embedding à partir des embeddings pré-entraînés.\n"," Affiche une barre de progression pendant le traitement.\n","\n"," Args:\n"," word_index (dict): Dictionnaire de mots et leurs indices\n"," embeddings_index (dict): Dictionnaire des embeddings pré-entraînés\n"," embedding_dim (int): Dimension des vecteurs d'embedding\n","\n"," Returns:\n"," numpy.ndarray: Matrice d'embedding\n"," \"\"\"\n"," vocab_size = len(word_index) + 1\n"," embedding_matrix = np.zeros((vocab_size, embedding_dim))\n","\n"," found_words = 0\n","\n"," # Utiliser tqdm pour afficher une barre de progression\n"," print(f\"Création de la matrice d'embedding pour {len(word_index)} mots...\")\n"," for word, i in tqdm(word_index.items(), total=len(word_index), desc=\"Création matrice d'embedding\"):\n"," embedding_vector = embeddings_index.get(word)\n"," if embedding_vector is not None:\n"," embedding_matrix[i] = embedding_vector\n"," found_words += 1\n","\n"," print(f\"Trouvé {found_words} mots ({found_words/len(word_index)*100:.2f}%) dans les embeddings pré-entraînés.\")\n"," return embedding_matrix"]},{"cell_type":"markdown","metadata":{"id":"XsGjsmVYNwMu"},"source":["## Optimisations matérielle (utilisation du GPU)\n","\n","1. **Désactivation du recurrent_dropout** - Permet l'utilisation de CuDNNLSTM optimisé pour GPU\n","2. **Activation de XLA** (Accelerated Linear Algebra) - Optimise les graphes d'opérations pour GPU\n","3. **Précision mixte** - Utilise float16 pour les calculs et float32 pour les variables\n","4. **Augmentation de la taille du batch** - Passée à 256 pour mieux exploiter le parallélisme GPU\n","5. **Optimisation du pipeline de données** - Utilisation de tf.data.Dataset avec prefetch\n","6. **Scheduler de taux d'apprentissage** - Décroissance exponentielle du taux pour améliorer la convergence\n","\n","Ces modifications permettent d'utiliser efficacement les capacités de notre **GTX 1060 3GB** tout en respectant les limitations de la mémoire."]},{"cell_type":"markdown","metadata":{"id":"lF2h27fxNwMu"},"source":["### Utilisation du GPU"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"TcLWpxKgNwMu","outputId":"77043b88-2bfc-4082-a05d-578cb6d16aa0","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1751829790359,"user_tz":-120,"elapsed":1095,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}}},"outputs":[{"output_type":"stream","name":"stderr","text":["WARNING:tensorflow:From /tmp/ipython-input-22-656146420.py:12: is_gpu_available (from tensorflow.python.framework.test_util) is deprecated and will be removed in a future version.\n","Instructions for updating:\n","Use `tf.config.list_physical_devices('GPU')` instead.\n"]},{"output_type":"stream","name":"stdout","text":["GPU disponible : [PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]\n","TensorFlow utilise GPU: True\n","Devices disponibles: [PhysicalDevice(name='/physical_device:CPU:0', device_type='CPU'), PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]\n","Compute dtype: float16\n","Variable dtype: float32\n"]}],"source":["import tensorflow as tf\n","\n","# Configuration de TensorFlow pour utiliser la GPU si disponible\n","physical_devices = tf.config.list_physical_devices('GPU')\n","if physical_devices:\n"," tf.config.experimental.set_memory_growth(physical_devices[0], True)\n"," print(\"GPU disponible :\", physical_devices)\n","else:\n"," print(\"Pas de GPU disponible, utilisation du CPU\")\n","\n","# Vérifier que TensorFlow utilise le GPU\n","print(f\"TensorFlow utilise GPU: {tf.test.is_gpu_available()}\")\n","print(f\"Devices disponibles: {tf.config.list_physical_devices()}\")\n","\n","# Optimiser les performances avec mixed precision\n","# Cette option accélère l'entraînement sur les GPU récents\n","policy = tf.keras.mixed_precision.Policy('mixed_float16')\n","tf.keras.mixed_precision.set_global_policy(policy)\n","print(f'Compute dtype: {policy.compute_dtype}')\n","print(f'Variable dtype: {policy.variable_dtype}')"]},{"cell_type":"markdown","metadata":{"id":"K6WAGmVVNwMu"},"source":["### Optimisations de la mémoire et configuration TensorFlow"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"EHdEo-FBNwMu","outputId":"e75df72d-816f-4d2a-95af-60b6b73515f4","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1751829790365,"user_tz":-120,"elapsed":5,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}}},"outputs":[{"output_type":"stream","name":"stdout","text":["Mémoire GPU dynamique activée\n","Politique de calcul: mixed_float16\n"]}],"source":["# Activer la mémoire GPU dynamique\n","gpus = tf.config.experimental.list_physical_devices('GPU')\n","if gpus:\n"," try:\n"," for gpu in gpus:\n"," tf.config.experimental.set_memory_growth(gpu, True)\n"," print(\"Mémoire GPU dynamique activée\")\n"," except RuntimeError as e:\n"," print(f\"Erreur: {e}\")\n","\n","# Activer XLA (Accelerated Linear Algebra) pour optimiser les graphes\n","tf.config.optimizer.set_jit(True) # Active la compilation Just-In-Time\n","\n","# Précision mixte pour accélérer les calculs\n","policy = tf.keras.mixed_precision.Policy('mixed_float16')\n","tf.keras.mixed_precision.set_global_policy(policy)\n","print(f'Politique de calcul: {policy.name}')"]},{"cell_type":"markdown","metadata":{"id":"5tWaCIapNwMu"},"source":["### Optimisation du chargement des données"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"_OYSmRuiNwMw"},"outputs":[],"source":["# 2. Optimiser le chargement des données\n","AUTOTUNE = tf.data.AUTOTUNE\n","BATCH_SIZE = 256 # Tester avec différentes valeurs: 128, 256, 512\n","\n","# Créer un dataset TensorFlow optimisé\n","def create_optimized_dataset(x, y, is_training=True):\n"," dataset = tf.data.Dataset.from_tensor_slices((x, y))\n"," if is_training:\n"," dataset = dataset.shuffle(10000)\n","\n"," # Utiliser un batch plus grand pour mieux utiliser le GPU\n"," dataset = dataset.batch(BATCH_SIZE)\n","\n"," # Précharger les données pour éviter les goulots d'étranglement\n"," dataset = dataset.prefetch(AUTOTUNE)\n"," return dataset\n","\n","# Séparer les données de validation et créer les datasets optimisés\n","val_size = int(0.1 * len(X_train_pad))\n","x_val = X_train_pad[-val_size:]\n","y_val = y_train[-val_size:]\n","x_train_final = X_train_pad[:-val_size]\n","y_train_final = y_train[:-val_size]\n","\n","train_dataset = create_optimized_dataset(x_train_final, y_train_final)\n","val_dataset = create_optimized_dataset(x_val, y_val, is_training=False)"]},{"cell_type":"markdown","metadata":{"id":"5angsL01NwMx"},"source":["Nos optimisations fonctionnent correctement :\n","\n","1. **XLA activé** : `Loaded cuDNN version 90300` et `Compiled cluster using XLA!` confirment que l'accélération XLA est bien activée.\n","2. **CuDNN chargé** : Le message indique que cuDNN (version 9.03) est correctement chargé, ce qui signifie que vos couches LSTM utiliseront l'implémentation optimisée pour GPU.\n","3. **GPU reconnu** : Le système a bien reconnu votre NVIDIA GeForce GTX 1060 3GB avec Compute Capability 6.1.\n","\n","Nous observervons :\n","- Une utilisation GPU bien supérieure à 20% (idéalement 70-90%)\n","- Un temps d'entraînement par epoch considérablement réduit\n","\n","Pour vérifier l'utilisation réelle du GPU pendant l'entraînement, nous pouvons exécuter :\n","\n","```shell\n","nvidia-smi -l 1\n","```"]},{"cell_type":"markdown","metadata":{"id":"PicWq6E0NwMx"},"source":["### Bilan de l'optimisation\n","\n","Nous avons réussi à optimiser significativement l'utilisation de notre GPU. Les modifications que nous avons apportées ont considérablement amélioré les performances :\n","\n","- Nous avons augmenté l'**utilisation de votre GPU de 20% à 73%**\n","- Nous utilisons maintenant intelligemment la mémoire disponible\n","- Nous avons activé les technologies d'**accélération comme XLA et CuDNN**\n","- Nous avons désactivé le **recurrent_dropout** pour permettre l'utilisation des implémentations GPU optimisées\n","- Nous avons implémenté la **précision mixte** pour accélérer les calculs\n","- Nous avons optimisé la **taille du batch** et le pipeline de données\n","\n","Nous avons atteint un excellent équilibre entre l'utilisation maximale des ressources et la stabilité du système."]},{"cell_type":"markdown","metadata":{"id":"NlECzxylNwMx"},"source":["## Création d'un modèles LSTM avec embeddings pré-entraînés\n","\n","Voici une description de la fonction `create_lstm_model_with_pretrained` qui crée un **modèle LSTM** avec des **embeddings pré-entraînés** :\n","\n","- Crée un modèle de réseau de neurones pour la **classification de texte** utilisant des **embeddings pré-entraînés**\n","- Initialise une couche d'embedding avec les poids fournis dans `embedding_matrix`\n","- Utilise une architecture profonde avec deux couches LSTM bidirectionnelles (128 puis 64 unités)\n","- Implémente plusieurs techniques de régularisation (dropout spatial et classique) pour éviter le surapprentissage\n","- Inclut une couche dense intermédiaire avec activation ReLU\n","- Se termine par une **couche de sortie avec activation sigmoïde**, adaptée aux problèmes de **classification binaire**\n","- Compile le modèle avec l'**optimiseur Adam**, une fonction de perte d'entropie croisée binaire et suit la métrique de précision\n","- Permet de contrôler si les embeddings sont entraînables ou figés via le paramètre `trainable`"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"1KZ4x6cGNwMx"},"outputs":[],"source":["def create_optimized_lstm_model(embedding_matrix, max_seq_length=MAX_SEQUENCE_LENGTH, trainable=False):\n"," vocab_size, embedding_dim = embedding_matrix.shape\n","\n"," # Entrée du modèle\n"," input_layer = tf.keras.layers.Input(shape=(max_seq_length,))\n","\n"," # Couche d'embedding avec des poids pré-entraînés\n"," embedding_layer = tf.keras.layers.Embedding(\n"," input_dim=vocab_size,\n"," output_dim=embedding_dim,\n"," weights=[embedding_matrix],\n"," input_length=max_seq_length,\n"," trainable=trainable\n"," )(input_layer)\n","\n"," # Dropout spatial\n"," dropout_1 = tf.keras.layers.SpatialDropout1D(0.3)(embedding_layer)\n","\n"," # Couche CuDNNLSTM optimisée pour GPU (via le backend GPU automatique de TF)\n"," # Note: TF2.x utilise automatiquement l'implémentation CuDNNLSTM quand recurrent_dropout=0\n"," lstm_layer = tf.keras.layers.Bidirectional(\n"," tf.keras.layers.LSTM(\n"," units=128,\n"," dropout=0.2,\n"," recurrent_dropout=0.0, # Mettre à 0 pour utiliser l'implémentation CuDNN optimisée\n"," return_sequences=True\n"," )\n"," )(dropout_1)\n","\n"," # Deuxième couche LSTM\n"," lstm_layer_2 = tf.keras.layers.Bidirectional(\n"," tf.keras.layers.LSTM(\n"," units=64,\n"," dropout=0.2,\n"," recurrent_dropout=0.0 # Mettre à 0 pour utiliser l'implémentation CuDNN optimisée\n"," )\n"," )(lstm_layer)\n","\n"," # Couche dense avec activation ReLU\n"," dense_1 = tf.keras.layers.Dense(64, activation='relu')(lstm_layer_2)\n"," dropout_2 = tf.keras.layers.Dropout(0.4)(dense_1)\n","\n"," # Couche de sortie\n"," output_layer = tf.keras.layers.Dense(1, activation='sigmoid')(dropout_2)\n","\n"," # Créer et compiler le modèle avec un optimiseur efficace sur GPU\n"," model = tf.keras.Model(inputs=input_layer, outputs=output_layer)\n","\n"," # Utiliser un taux d'apprentissage avec décroissance\n"," # lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(\n"," # initial_learning_rate=0.001,\n"," # decay_steps=1000,\n"," # decay_rate=0.9,\n"," # staircase=True\n"," # )\n","\n"," model.compile(\n"," optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), # taux fixe\n"," loss='binary_crossentropy',\n"," # on ajoute aussi le rappel car on veut tout de même limiter le nombre de faux négatifs\n"," metrics=[keras.metrics.Precision(name='precision'), keras.metrics.Recall(name='recall')]\n"," )\n","\n"," return model"]},{"cell_type":"markdown","metadata":{"id":"S_tupAxrNwMx"},"source":["## Fonction de sauvegarde locale des artefacts du modèle\n","\n","Sauvegarde tous les artefacts du modèle (modèle, tokenizer, fonction de prétraitement, historique) dans un sous-dossier dédié."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Mxy90vFuNwMx"},"outputs":[],"source":["import os\n","import dill # Plus puissant que pickle pour sauvegarder des fonctions\n","import datetime\n","import json\n","\n","def save_model_artifacts(model, model_name, vectorizer_name, history, tokenizer):\n"," \"\"\"\n"," Sauvegarde tous les artefacts du modèle (modèle, tokenizer, fonction de prétraitement, historique)\n"," dans un sous-dossier dédié.\n"," \"\"\"\n","\n"," # Créer un sous-dossier dédié pour ce modèle\n"," model_dir = f\"content/advanced-model/{model_name}_{vectorizer_name}\"\n"," os.makedirs(model_dir, exist_ok=True)\n","\n"," # Sous-dossiers pour les différents types d'artefacts\n"," checkpoints_dir = f\"{model_dir}/checkpoints\"\n"," os.makedirs(checkpoints_dir, exist_ok=True)\n","\n"," # 1. Sauvegarder le modèle final\n"," model_path = f\"{model_dir}/final_model_{model_name}_{vectorizer_name}.keras\"\n"," model.save(model_path)\n"," print(f\"Modèle sauvegardé dans {model_path}\")\n","\n"," # 2. Sauvegarder le tokenizer\n"," tokenizer_path = f\"{model_dir}/tokenizer.pickle\"\n"," with open(tokenizer_path, 'wb') as handle:\n"," pickle.dump(tokenizer, handle, protocol=pickle.HIGHEST_PROTOCOL)\n"," print(f\"Tokenizer sauvegardé dans {tokenizer_path}\")\n","\n"," # 3. Sauvegarder la fonction de prétraitement\n"," preprocess_path = f\"{model_dir}/preprocess_function.dill\"\n"," with open(preprocess_path, 'wb') as handle:\n"," dill.dump(preprocess_tweet, handle)\n"," print(f\"Fonction de prétraitement sauvegardée dans {preprocess_path}\")\n","\n"," # 4. Sauvegarder l'historique d'entraînement\n"," if history is not None:\n"," history_path = f\"{model_dir}/training_history.pickle\"\n"," with open(history_path, 'wb') as handle:\n"," pickle.dump(history.history, handle, protocol=pickle.HIGHEST_PROTOCOL)\n"," print(f\"Historique d'entraînement sauvegardé dans {history_path}\")\n","\n"," # 5. Sauvegarder les paramètres utilisés - Version ultra-sécurisée\n"," params_path = f\"{model_dir}/parameters.json\"\n","\n"," # Déterminer la dimension d'embedding de façon sûre\n"," embedding_dim = None\n","\n"," # Méthode 1: Accéder directement à l'attribut output_dim des couches Embedding\n"," for layer in model.layers:\n"," if isinstance(layer, tf.keras.layers.Embedding):\n"," embedding_dim = layer.output_dim\n"," break\n","\n"," # Méthode 2: Si ce n'est pas trouvé, utiliser une valeur basée sur le nom du vectorizer\n"," if embedding_dim is None:\n"," if 'word2vec' in vectorizer_name.lower():\n"," embedding_dim = 300 # Dimension standard pour Word2Vec\n"," elif 'glove' in vectorizer_name.lower() and '300d' in vectorizer_name.lower():\n"," embedding_dim = 300\n"," else:\n"," embedding_dim = 100 # Valeur par défaut\n","\n"," params = {\n"," \"model_name\": model_name,\n"," \"vectorizer_name\": vectorizer_name,\n"," \"max_sequence_length\": MAX_SEQUENCE_LENGTH,\n"," \"vocab_size\": MAX_VOCAB_SIZE,\n"," \"embedding_dim\": embedding_dim,\n"," \"date_created\": datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n"," }\n"," with open(params_path, 'w') as f:\n"," json.dump(params, f, indent=4)\n"," print(f\"Paramètres sauvegardés dans {params_path}\")\n","\n"," return model_dir"]},{"cell_type":"markdown","metadata":{"id":"BZLUgq5gNwMx"},"source":["## Entraînement : LSTM avec Word2Vec\n","\n","Nous créons un modèle d'analyse de sentiment des tweets basé sur des **réseaux de neurones récurrents (LSTM)** avec des **embeddings Word2Vec**.\n","\n","Nous chargeons d'abord les embeddings Word2Vec pré-entraînés et les intègrons dans la matrice d'embedding, puis nous définissons une **fonction d'entraînement complète** qui:\n","\n","- Crée un **modèle LSTM bidirectionnel** optimisé pour GPU\n","- Configure des **callbacks** comme early stopping, réduction du taux d'apprentissage et sauvegarde des meilleurs modèles\n","- Entraîne le modèle sur des **données de tweets** prétraitées en utilisant des optimisations GPU\n","- Évalue les **performances du modèle** avec diverses métriques (précision, rappel, F1, etc.)\n","- **Sauvegarde les artefacts du modèle** (modèle final, tokenizer, fonction de prétraitement)\n","- **Enregistre tous les paramètres et résultats dans MLflow** pour faciliter le suivi des expériences\n","- Génère des **visualisations des courbes d'apprentissage**\n","- Retourne le modèle entraîné, son historique et ses métriques de performance\n"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"qOq86PFNNwMx","outputId":"8ff016a9-09d8-4a8b-fc9e-d0cbef7197f2","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1751829803818,"user_tz":-120,"elapsed":13373,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}}},"outputs":[{"output_type":"stream","name":"stdout","text":["Chargement des embeddings Word2Vec...\n","Trouvé 500000 vecteurs d'embeddings Word2Vec.\n","Création de la matrice d'embedding pour 83730 mots...\n"]},{"output_type":"stream","name":"stderr","text":["Création matrice d'embedding: 100%|██████████| 83730/83730 [00:00<00:00, 355633.78it/s]"]},{"output_type":"stream","name":"stdout","text":["Trouvé 22721 mots (27.14%) dans les embeddings pré-entraînés.\n","Forme de la matrice d'embedding: (83731, 300)\n","Échantillon de valeurs: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n","Type de données: float64\n"]},{"output_type":"stream","name":"stderr","text":["\n"]}],"source":["word2vec_embeddings = load_word2vec_embeddings()\n","word2vec_matrix = create_embedding_matrix(tokenizer.word_index, word2vec_embeddings, 300)\n","\n","# Vérifiez la forme et les valeurs de la matrice d'embedding\n","print(\"Forme de la matrice d'embedding:\", word2vec_matrix.shape)\n","print(\"Échantillon de valeurs:\", word2vec_matrix[0, :10]) # Affiche les 10 premières valeurs de la première ligne\n","print(\"Type de données:\", word2vec_matrix.dtype)"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"KXMLd7jqNwMx"},"outputs":[],"source":["# Créer une fonction pour configurer le callback ModelCheckpoint\n","def create_model_checkpoint(model_name, vectorizer_name):\n"," \"\"\"\n"," Crée un callback ModelCheckpoint qui sauvegarde uniquement le meilleur modèle.\n"," \"\"\"\n"," # Créer le dossier pour les checkpoints\n"," checkpoint_dir = f\"content/advanced-model/{model_name}_{vectorizer_name}/checkpoints\"\n"," os.makedirs(checkpoint_dir, exist_ok=True)\n","\n"," # Créer un seul checkpoint pour le meilleur modèle\n"," best_checkpoint = tf.keras.callbacks.ModelCheckpoint(\n"," filepath=f\"{checkpoint_dir}/best_model.keras\",\n"," # on décide de monitorer val_precision car c'est ce que l'on souhaite maximiser\n"," # monitor='val_loss',\n"," monitor='val_precision',\n"," save_best_only=True,\n"," # mode='min',\n"," mode='max',\n"," verbose=1\n"," )\n","\n"," return best_checkpoint"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"JGLT8JhWNwMx"},"outputs":[],"source":["def train_word2vec_lstm_model(epochs=20):\n"," \"\"\"\n"," Entraîne un modèle LSTM avec embeddings Word2Vec en utilisant les optimisations GPU\n"," et le chargement de données optimisé.\n"," \"\"\"\n"," # Définir le nom du modèle et de la méthode d'embedding\n"," model_name = \"LSTM\"\n"," vectorizer_name = \"Word2Vec-Fige\"\n","\n"," # Créer les callbacks pour ce modèle\n"," checkpoint_callback = create_model_checkpoint(model_name, vectorizer_name)\n","\n"," # Autres callbacks\n"," early_stopping = tf.keras.callbacks.EarlyStopping(\n"," monitor='val_loss',\n"," patience=5,\n"," restore_best_weights=True\n"," )\n","\n"," reduce_lr = tf.keras.callbacks.ReduceLROnPlateau(\n"," monitor='val_loss',\n"," factor=0.2,\n"," patience=2,\n"," min_lr=0.00001\n"," )\n","\n"," # TensorBoard pour visualiser l'entraînement\n"," tensorboard_dir = f\"content/advanced-model/{model_name}_{vectorizer_name}/logs\"\n"," os.makedirs(tensorboard_dir, exist_ok=True)\n"," tensorboard_callback = tf.keras.callbacks.TensorBoard(\n"," log_dir=tensorboard_dir,\n"," histogram_freq=1,\n"," update_freq='epoch'\n"," )\n","\n"," # Créer le modèle optimisé pour GPU\n"," model = create_optimized_lstm_model(word2vec_matrix, trainable=False)\n","\n"," print(f\"Entraînement du modèle {model_name} avec embeddings {vectorizer_name}\")\n"," print(f\"Taille du batch: {BATCH_SIZE}\")\n"," print(f\"Utilisation de la précision mixte: {tf.keras.mixed_precision.global_policy().name}\")\n","\n"," # Entraîner le modèle avec les datasets optimisés\n"," history = model.fit(\n"," train_dataset,\n"," epochs=epochs,\n"," validation_data=val_dataset,\n"," callbacks=[early_stopping, reduce_lr, tensorboard_callback, checkpoint_callback],\n"," verbose=1\n"," )\n","\n"," # Déterminer le nombre réel d'époques complétées (en cas d'early stopping)\n"," real_epochs = len(history.history['loss'])\n"," print(f\"Nombre réel d'époques effectuées: {real_epochs}/{epochs}\")\n","\n"," # Sauvegarder tous les artefacts\n"," model_dir = save_model_artifacts(model, model_name, vectorizer_name, history, tokenizer)\n","\n"," # Utiliser evaluate_model pour obtenir les métriques\n"," metrics, cm, report, y_pred, y_pred_proba = evaluate_model(\n"," model,\n"," X_test_pad,\n"," y_test\n"," )\n","\n"," # Afficher les métriques\n"," print(\"\\nMétriques pour le modèle LSTM avec embedding Word2Vec:\")\n"," for key, value in metrics.items():\n"," print(f\"{key}: {value:.4f}\")\n","\n"," print(\"\\nRapport de classification:\")\n"," print(report)\n","\n","\n"," # Enregistrer avec MLflow\n"," params = {\n"," 'model_type': model_name,\n"," 'embedding_type': vectorizer_name,\n"," 'embedding_dim': word2vec_matrix.shape[1],\n"," 'vocab_size': len(tokenizer.word_index) + 1,\n"," 'max_sequence_length': MAX_SEQUENCE_LENGTH,\n"," 'trainable_embedding': False,\n"," 'max_epochs': epochs,\n"," 'real_epochs': real_epochs, # Ajouter le nombre réel d'époques\n"," 'batch_size': BATCH_SIZE,\n"," 'precision_policy': tf.keras.mixed_precision.global_policy().name,\n"," 'gpu_optimization': 'XLA,dynamic_memory,prefetch',\n"," 'sample_size': sample_size*2\n","\n"," }\n","\n"," # Enregistrer dans MLflow\n"," # run_id = log_model_to_mlflow(model, model_name, vectorizer_name, metrics, cm, report, X_test_pad, y_test, params)\n"," run_id = log_model_to_mlflow(model, model_name, vectorizer_name, metrics, cm, report, X_test_pad, y_test, history, params)\n","\n"," # Visualiser la courbe d'apprentissage\n"," plot_training_history(history, \"LSTM\", \"Word2Vec-Fige\", run_id=run_id)\n","\n"," # Récupérer le lien vers le run MLflow\n"," print(f\"\\nRun MLflow ID: {run_id}\")\n"," print(f\"Accédez à l'interface MLflow pour voir les détails complets.\")\n","\n"," return model, history, metrics, run_id"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"O8S9kFSFNwMx","outputId":"734480a6-2aa0-45e8-e3df-36ba91d7328f","colab":{"base_uri":"https://localhost:8080/","height":1000},"executionInfo":{"status":"ok","timestamp":1751830269652,"user_tz":-120,"elapsed":465796,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}}},"outputs":[{"output_type":"stream","name":"stdout","text":["Entraînement du modèle LSTM avec embeddings Word2Vec-Fige\n","Taille du batch: 256\n","Utilisation de la précision mixte: mixed_float16\n","Epoch 1/50\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 26ms/step - loss: 0.5872 - precision: 0.6836 - recall: 0.6817\n","Epoch 1: val_precision improved from -inf to 0.74873, saving model to content/advanced-model/LSTM_Word2Vec-Fige/checkpoints/best_model.keras\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m45s\u001b[0m 58ms/step - loss: 0.5871 - precision: 0.6837 - recall: 0.6818 - val_loss: 0.5082 - val_precision: 0.7487 - val_recall: 0.7563 - learning_rate: 0.0010\n","Epoch 2/50\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 26ms/step - loss: 0.5207 - precision: 0.7410 - recall: 0.7456\n","Epoch 2: val_precision improved from 0.74873 to 0.77025, saving model to content/advanced-model/LSTM_Word2Vec-Fige/checkpoints/best_model.keras\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m25s\u001b[0m 45ms/step - loss: 0.5207 - precision: 0.7410 - recall: 0.7456 - val_loss: 0.4784 - val_precision: 0.7703 - val_recall: 0.7720 - learning_rate: 0.0010\n","Epoch 3/50\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 18ms/step - loss: 0.4919 - precision: 0.7598 - recall: 0.7715\n","Epoch 3: val_precision did not improve from 0.77025\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m17s\u001b[0m 30ms/step - loss: 0.4919 - precision: 0.7598 - recall: 0.7715 - val_loss: 0.4653 - val_precision: 0.7639 - val_recall: 0.7960 - learning_rate: 0.0010\n","Epoch 4/50\n","\u001b[1m562/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 17ms/step - loss: 0.4779 - precision: 0.7699 - recall: 0.7760\n","Epoch 4: val_precision did not improve from 0.77025\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m16s\u001b[0m 29ms/step - loss: 0.4779 - precision: 0.7699 - recall: 0.7760 - val_loss: 0.4610 - val_precision: 0.7637 - val_recall: 0.8117 - learning_rate: 0.0010\n","Epoch 5/50\n","\u001b[1m561/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 17ms/step - loss: 0.4692 - precision: 0.7706 - recall: 0.7891\n","Epoch 5: val_precision did not improve from 0.77025\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m20s\u001b[0m 29ms/step - loss: 0.4691 - precision: 0.7706 - recall: 0.7891 - val_loss: 0.4646 - val_precision: 0.7382 - val_recall: 0.8591 - learning_rate: 0.0010\n","Epoch 6/50\n","\u001b[1m562/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 18ms/step - loss: 0.4627 - precision: 0.7774 - recall: 0.7892\n","Epoch 6: val_precision improved from 0.77025 to 0.77874, saving model to content/advanced-model/LSTM_Word2Vec-Fige/checkpoints/best_model.keras\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m17s\u001b[0m 30ms/step - loss: 0.4627 - precision: 0.7774 - recall: 0.7892 - val_loss: 0.4524 - val_precision: 0.7787 - val_recall: 0.7977 - learning_rate: 0.0010\n","Epoch 7/50\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 18ms/step - loss: 0.4556 - precision: 0.7805 - recall: 0.7927\n","Epoch 7: val_precision did not improve from 0.77874\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m22s\u001b[0m 32ms/step - loss: 0.4556 - precision: 0.7805 - recall: 0.7927 - val_loss: 0.4540 - val_precision: 0.7754 - val_recall: 0.8076 - learning_rate: 0.0010\n","Epoch 8/50\n","\u001b[1m561/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 17ms/step - loss: 0.4521 - precision: 0.7847 - recall: 0.7925\n","Epoch 8: val_precision did not improve from 0.77874\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m16s\u001b[0m 29ms/step - loss: 0.4521 - precision: 0.7847 - recall: 0.7925 - val_loss: 0.4514 - val_precision: 0.7682 - val_recall: 0.8142 - learning_rate: 0.0010\n","Epoch 9/50\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 17ms/step - loss: 0.4450 - precision: 0.7874 - recall: 0.7984\n","Epoch 9: val_precision did not improve from 0.77874\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m21s\u001b[0m 30ms/step - loss: 0.4450 - precision: 0.7874 - recall: 0.7984 - val_loss: 0.4492 - val_precision: 0.7741 - val_recall: 0.8102 - learning_rate: 0.0010\n","Epoch 10/50\n","\u001b[1m562/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 16ms/step - loss: 0.4412 - precision: 0.7906 - recall: 0.7971\n","Epoch 10: val_precision improved from 0.77874 to 0.79515, saving model to content/advanced-model/LSTM_Word2Vec-Fige/checkpoints/best_model.keras\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m17s\u001b[0m 30ms/step - loss: 0.4412 - precision: 0.7906 - recall: 0.7971 - val_loss: 0.4496 - val_precision: 0.7952 - val_recall: 0.7727 - learning_rate: 0.0010\n","Epoch 11/50\n","\u001b[1m562/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 16ms/step - loss: 0.4344 - precision: 0.7928 - recall: 0.8052\n","Epoch 11: val_precision did not improve from 0.79515\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m17s\u001b[0m 31ms/step - loss: 0.4344 - precision: 0.7928 - recall: 0.8052 - val_loss: 0.4515 - val_precision: 0.7818 - val_recall: 0.8014 - learning_rate: 0.0010\n","Epoch 12/50\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 18ms/step - loss: 0.4256 - precision: 0.7980 - recall: 0.8075\n","Epoch 12: val_precision did not improve from 0.79515\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m16s\u001b[0m 29ms/step - loss: 0.4256 - precision: 0.7980 - recall: 0.8075 - val_loss: 0.4455 - val_precision: 0.7865 - val_recall: 0.7943 - learning_rate: 2.0000e-04\n","Epoch 13/50\n","\u001b[1m561/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 16ms/step - loss: 0.4206 - precision: 0.8006 - recall: 0.8104\n","Epoch 13: val_precision did not improve from 0.79515\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m21s\u001b[0m 29ms/step - loss: 0.4206 - precision: 0.8006 - recall: 0.8104 - val_loss: 0.4451 - val_precision: 0.7867 - val_recall: 0.8019 - learning_rate: 2.0000e-04\n","Epoch 14/50\n","\u001b[1m561/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 16ms/step - loss: 0.4170 - precision: 0.8040 - recall: 0.8117\n","Epoch 14: val_precision did not improve from 0.79515\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m17s\u001b[0m 29ms/step - loss: 0.4170 - precision: 0.8040 - recall: 0.8117 - val_loss: 0.4419 - val_precision: 0.7950 - val_recall: 0.7912 - learning_rate: 2.0000e-04\n","Epoch 15/50\n","\u001b[1m561/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 19ms/step - loss: 0.4170 - precision: 0.8052 - recall: 0.8142\n","Epoch 15: val_precision did not improve from 0.79515\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m21s\u001b[0m 31ms/step - loss: 0.4170 - precision: 0.8053 - recall: 0.8142 - val_loss: 0.4468 - val_precision: 0.7831 - val_recall: 0.8031 - learning_rate: 2.0000e-04\n","Epoch 16/50\n","\u001b[1m562/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 17ms/step - loss: 0.4142 - precision: 0.8058 - recall: 0.8151\n","Epoch 16: val_precision did not improve from 0.79515\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m19s\u001b[0m 29ms/step - loss: 0.4142 - precision: 0.8058 - recall: 0.8151 - val_loss: 0.4477 - val_precision: 0.7841 - val_recall: 0.7965 - learning_rate: 2.0000e-04\n","Epoch 17/50\n","\u001b[1m560/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 18ms/step - loss: 0.4102 - precision: 0.8085 - recall: 0.8159\n","Epoch 17: val_precision did not improve from 0.79515\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m16s\u001b[0m 28ms/step - loss: 0.4102 - precision: 0.8085 - recall: 0.8159 - val_loss: 0.4485 - val_precision: 0.7838 - val_recall: 0.8012 - learning_rate: 4.0000e-05\n","Epoch 18/50\n","\u001b[1m562/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 16ms/step - loss: 0.4108 - precision: 0.8076 - recall: 0.8137\n","Epoch 18: val_precision did not improve from 0.79515\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m21s\u001b[0m 29ms/step - loss: 0.4108 - precision: 0.8076 - recall: 0.8138 - val_loss: 0.4487 - val_precision: 0.7842 - val_recall: 0.7999 - learning_rate: 4.0000e-05\n","Epoch 19/50\n","\u001b[1m561/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 17ms/step - loss: 0.4088 - precision: 0.8077 - recall: 0.8180\n","Epoch 19: val_precision did not improve from 0.79515\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m17s\u001b[0m 29ms/step - loss: 0.4088 - precision: 0.8077 - recall: 0.8180 - val_loss: 0.4472 - val_precision: 0.7844 - val_recall: 0.8043 - learning_rate: 1.0000e-05\n","Nombre réel d'époques effectuées: 19/50\n","Modèle sauvegardé dans content/advanced-model/LSTM_Word2Vec-Fige/final_model_LSTM_Word2Vec-Fige.keras\n","Tokenizer sauvegardé dans content/advanced-model/LSTM_Word2Vec-Fige/tokenizer.pickle\n","Fonction de prétraitement sauvegardée dans content/advanced-model/LSTM_Word2Vec-Fige/preprocess_function.dill\n","Historique d'entraînement sauvegardé dans content/advanced-model/LSTM_Word2Vec-Fige/training_history.pickle\n","Paramètres sauvegardés dans content/advanced-model/LSTM_Word2Vec-Fige/parameters.json\n","\u001b[1m1250/1250\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m9s\u001b[0m 5ms/step\n","\n","Métriques pour le modèle LSTM avec embedding Word2Vec:\n","accuracy: 0.7898\n","precision: 0.7970\n","recall: 0.7777\n","f1: 0.7872\n","roc_auc: 0.8748\n","\n","Rapport de classification:\n"," precision recall f1-score support\n","\n"," Négatif 0.78 0.80 0.79 20000\n"," Positif 0.80 0.78 0.79 20000\n","\n"," accuracy 0.79 40000\n"," macro avg 0.79 0.79 0.79 40000\n","weighted avg 0.79 0.79 0.79 40000\n","\n"]},{"output_type":"stream","name":"stderr","text":["2025/07/06 19:30:24 WARNING mlflow.models.model: `artifact_path` is deprecated. Please use `name` instead.\n"]},{"output_type":"stream","name":"stdout","text":["🏃 View run Modele_Avance_LSTM_Word2Vec-Fige at: https://mlflow.greg-madman-nas.duckdns.org/#/experiments/1/runs/1de54538ee73443687db131fcc86d922\n","🧪 View experiment at: https://mlflow.greg-madman-nas.duckdns.org/#/experiments/1\n","🏃 View run Modele_Avance_LSTM_Word2Vec-Fige at: https://mlflow.greg-madman-nas.duckdns.org/#/experiments/1/runs/1de54538ee73443687db131fcc86d922\n","🧪 View experiment at: https://mlflow.greg-madman-nas.duckdns.org/#/experiments/1\n","\n","Run MLflow ID: 1de54538ee73443687db131fcc86d922\n","Accédez à l'interface MLflow pour voir les détails complets.\n"]},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"iVBORw0KGgoAAAANSUhEUgAABKUAAAHqCAYAAADVi/1VAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzs3Xd8k9X+wPHPkzbdu7SUllJKWzayZM+CDAWZThwMBcX1c6JXQbkKXrkuVJxwRXGhosiUvWTvvcpeLW0ppYuOJOf3R0hoaFoKtE3H9/169dXmGec5z0nSnPPNGZpSSiGEEEIIIYQQQgghRBnSOToDQgghhBBCCCGEEKLqkaCUEEIIIYQQQgghhChzEpQSQgghhBBCCCGEEGVOglJCCCGEEEIIIYQQosxJUEoIIYQQQgghhBBClDkJSgkhhBBCCCGEEEKIMidBKSGEEEIIIYQQQghR5iQoJYQQQgghhBBCCCHKnASlhBBCCCGEEEIIIUSZk6CUqDD27NmDl5cXPXr0IDc319HZEUIIIYQQQgghxC2QoJSoEFJTUxk4cCANGzZk9uzZuLi43HRaq1atQtM0xo8ff1Pnf/fdd2iaxnfffXfTeRBCQNeuXdE0zdHZKJekbIQQQoiK7VbbHJWZlI3IT4JSosRommbz4+TkRLVq1ejWrRs///zzTadrMpkYMmQIer2ehQsX4uXlVYK5rtosDd9Vq1YV6/gtW7bw0EMPERERgaurKz4+PkRFRXH33Xfz3//+l8zMTABq165d4PVQ1I/lA2n8+PHWbY8++mih+Vi9erX1uNq1a99iKVRcRqMRPz8/9Ho96enpBfbHx8dby2n69Ol20+jSpQuaprFmzZrSzm6xnD17ls8++4w777yT2rVr4+rqSmBgID169ODPP/+0OfbSpUt4enri7u7OxYsXi0z39OnTODk5ERwc7NCelsOGDSvyvdC1a1eH5U0IUTlZ/r9URZaGb3H/t2ZnZ/PBBx/Qpk0bfH19cXFxoUaNGrRs2ZJnnnmG1atXA1e/oLyRHwvLY51Ox9GjRwvNS2xsrPXYqvxF6Icffoimabz66qt29z/xxBNF1gdXrlyJpml069atFHNZfEopFi1axLPPPkuzZs3w9/fHzc2NevXq8fzzz3P+/Hmb49944w00TWPMmDHXTXvUqFFomsbHH39cWtm/rhMnTlz3vVDcdoeoOpwdnQFR+bz11lsA5OXlcfDgQebMmcPKlSvZunUrH3300Q2nd/jwYVq3bs3XX39NtWrVbjl/rVu35sCBAzed1sCBA2nbti01atS45bxUJD/++CNDhw5FKUW3bt0YOHAg7u7unDx5krVr1zJ//nwGDRpEdHQ0zz//PKmpqTbnf/fdd5w8eZKhQ4cWqDhcW1l0dnZm1qxZfPrpp/j5+RXIy9SpU3F2dsZgMJTsTVYwTk5OdO3alTlz5rBmzRr69Oljs3/58uWAuQK8YsUKhg8fbrM/KyuLjRs34unpSbt27cos30X57LPPmDRpEpGRkcTGxhISEsLJkyf5888/WbZsGS+88IL1/4ivry/33nsv33//PT/88APPPfdcoel+++23mEwmhg4deks9LUtK//79adasWYHtlvfGjBkzyMrKKttMCSFEFZaRkUGXLl3Yvn07ISEhDB48mJCQEDIyMti1axfffPMNqampdOnShWbNmlnruxYnTpzg+++/JyIigmHDhhV5LUsd5n//+x/vvvtugf1xcXGsWrVK6jpA9+7dAVixYoXd/cuXL0fTNE6ePMnRo0eJiooqsB/gjjvuKN2MFlNOTg533nknLi4udO7cmTvuuAOj0ciKFSv45JNPmDlzJv/88w8xMTEAPP744/znP/9hxowZTJw4Eb1ebzfdzMxMZs6ciaurK0OHDi3LW7LL19eX559/3u6+2rVrExwcfEvtMVHJKCFKCKDsvaSWLVumNE1Tmqap48ePl33GRKG6dOmiALVy5coij8vMzFQ+Pj7KyclJLVu2zO4x69atUxcvXryla7311lsKUAMGDFCAmjJlSoFjUlJSlJubmxo4cKACVERERJF5r+w++eQTBagXX3yxwL7hw4crd3d31adPHxUWFlZg/+LFixWgevfuXRZZLcDymsjvjz/+UKtWrSpw7P79+5WPj48C1NatW63b161bpwDVpEmTQq9jNBpVRESEAtThw4dL7gZuwtChQxWgpk+f7tB8CCGqjsLqZ1XBypUrFaC6dOly3WPfeecdBaiePXuqnJycAvtTUlLUunXrbvlagAoLC1O33367CgkJUXl5eQWOGTNmjAKsdZ2q/JlhMplUYGCgcnJyUqmpqTb7Tp48qQB17733KkB98803Bc5v166dAtTGjRvLKstWltfEW2+9Zd2Wm5urJkyYoFJS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7nSrdayy8tVXXxWow1kcPHjQOhSqNOo6EyZMYPbs2SxevNga/LoZtWvXJi4uziawoJRi/PjxRf6vf/TRR9HpdMyYMYMZM2YA2O2J9swzz6DX63nhhRcKzO0D5qGO+YMDLVu2pH379uzcuZNJkyYVOP7ChQtkZ2cX+/4sdZ1x48YBtj3CAerVq0eNGjX48ccfOXToENHR0TZ17w4dOlCvXj3Wrl3LrFmzbM6dNWsW//zzD3Xr1rU7p5E9er2ehx56iPT09ALzGW3dupWffvrJ7nk7d+601snmzJlDnz59inU9sO0V/t1336HX6ws8V/379ycqKorPP/+chQsX2k1nw4YN1rqek5MTTz31FJcvX+bJJ58sMMQzNzfXpudjaenQoQNRUVGsXLmywBeB33zzjd3X3PDhw/Hz8+Pf//43mzdvLrDfZDIVGRwU5YPMKSXKpSlTphAXF8ebb77JDz/8QMeOHalevTrnzp3jwIEDbNmyhV9++cU6qXbPnj0ZO3YsEyZMoEGDBgwYMIDw8HDOnz/P2rVradu2Ld99912h1/vhhx/4+uuv6dixI1FRUfj7+3P06FHmzZuHq6vrdcdJe3l58e2333LvvffSpUsX7r33XmrVqsW2bdtYsmQJISEhfP311yVYQiXrvffeK7R8nnvuOXQ6Hf/3f//HK6+8QocOHWjcuDHe3t4kJiayYsUKjh07RnBwMB9++GGp5K9nz563nMbdd99NdHQ0H330EXv27KF58+acOnWK+fPn06dPH06dOlXouUOHDmXatGn861//sj62p6xft/lVr17d2gMI7E/iaam87dmzx+4xQ4YMYc6cOfz22280atSIAQMGoGkaf/31F8ePH+f+++/noYceKlZ+wFw5fu+993jppZdo3rw5999/P76+vixevJjU1FRuu+02du/ebXPO22+/zbRp03B3d6dZs2a89957BdJt1qwZAwYMsHvNUaNGMXPmTGul2N4wiBEjRrBt2za++OILoqKi6NWrF7Vq1SIlJYXjx4+zZs0ahg8fzldffQVAtWrV+Pnnn7nnnnuIjY3lzjvv5LbbbiMtLY3du3dz+vTpMhkC9+ijjzJz5kwWLVpE48aN6devH3l5efzxxx+0atWKQ4cOFQhEjhs3jl27dvHVV18xb948unXrRlhYGImJicTFxbFu3TomTpwok38KUQUUNdzt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gKwMyDhUN6rKSU+FI4e9da8O7qnLRThDz8SlpFT3ZQafQaDLReWAob4ORUREREREREQ6OeMOgIQkSEjCnPX1dqe62jvlrzZJlXHI57WtlZTyMeuCy4j57m1kZGTgOM7JDxARERERERERaSHjckFcH4jrgxk13tfhAOA/1a1ERERERERERKTbUFJKREREREREREQ6nJJSIiIiIiIiIiLS4ZSUEhERERERERGRDqeklIiIiIiIiIiIdDglpUREREREREREpMMpKSUiIiIiIiIiIh1OSSkREREREREREelwbl8HICIiIiKtt2LFCt544w3y8vJITk7mlltuYeDAgSc9bt26dTzzzDOMGTOGe++9t2674zgsXryY999/n+LiYoYMGcKtt95KfHx8e96GiIiIdCMaKSUiIiLSya1fv56FCxfyne98h3nz5pGcnMzcuXPJz88/4XFZWVm88MILDB06tMF7r732Gm+99RazZs3iscceIzAwkLlz51JRUdFetyEiIiLdjJJSIiIiIp3cm2++ybRp05gyZQqJiYnMmjULj8fDqlWrmjzGtm0WLFjANddcQ2xsbL33HMdh+fLlXHXVVYwdO5bk5GTuuusujh07xmeffdbetyMiIiLdhJJSIiIiIp1YVVUV+/btY/jw4XXbLMti+PDh7Nq1q8njlixZQkREBFOnTm3wXlZWFnl5eYwYMaJuW0hICAMHDjzhOUVERERaQjWlRERERDqxgoICbNsmKiqq3vaoqCjS09MbPWbnzp2sXLmSJ554otH38/LyAIiMjKy3PTIysu69xlRWVlJZWVn32hhDcHBw3fdtqfZ8bX3ezkRtoDbo7vcPagNQG4DaADpvGygpJSIiItKNlJaWsmDBAm677TYiIiLa9NxLly5lyZIlda/79evHvHnziImJadPrHC8uLq7dzt1ZqA3UBt39/kFtAGoDUBtA52sDJaVEREREOrGIiAgsy2owgikvL6/B6CmAI0eOkJ2dzbx58+q2OY4DwHXXXcf8+fPrjsvPz6dHjx51++Xn55OSktJkLFdeeSUzZ86se137aW12djZVVVUtvLMTM8YQFxdHZmZmXfzdjdpAbdDd7x/UBqA2ALUB+F8buN3uZn0opaRUC7jd7ddc7XnuzkJtoDYAtQGoDUBt0N3vH/yrDfwplsa43W769+/Ptm3bGDduHOAtYr5t2zamT5/eYP+EhASefPLJetsWLVpEWVkZ3//+9+nVqxcul4uoqCi2bt1al4QqKSlhz549XHTRRU3GEhAQQEBAQKMxtheXy9Vu5+4s1AZqg+5+/6A2ALUBqA3Af9qguf/2+3cvy88c/0lhW2vPYe2dhdpAbQBqA1AbgNqgu98/qA1aaubMmTz//PP079+fgQMHsnz5csrLy5k8eTIAzz33HNHR0dxwww14PB6SkpLqHR8aGgpQb/uMGTP473//S3x8PLGxsSxatIgePXowduzYFsenPlT7UhuoDbr7/YPaANQGoDaAztcGWn3Px0pLS7nvvvsoLS31dSg+ozZQG4DaANQGoDbo7vcPaoNTNWHCBL773e+yePFi7r33Xg4cOMDs2bPrpuHl5ORw7NixFp3z8ssvZ/r06fzxj3/k/vvvp7y8nNmzZ+PxeNrhDlpOz4raANQG3f3+QW0AagNQG0DnbQONlPIxx3HYv3+/X8z59BW1gdoA1AagNgC1QXe/f1AbtMb06dMbna4HMGfOnBMee+eddzbYZozh2muv5dprr22L8NqcnhW1AagNuvv9g9oA1AagNoDO2wYaKSUiIiIiIiIiIh1OSSkREREREREREelwSkr5WEBAAN/5zncaXammu1AbqA1AbQBqA1AbdPf7B7WBNJ+eFbUBqA26+/2D2gDUBqA2gM7bBsbpbBMORURERERERESk09NIKRERERERERER6XBKSomIiIiIiIiISIdTUkpERERERERERDqc29cBdAcrVqzgjTfeIC8vj+TkZG655RYGDhzY5P4fffQRr7zyCtnZ2cTFxXHjjTcyevToDoy47SxdupRPP/2Uw4cP4/F4GDx4MDfddBMJCQlNHrN69Wp+//vf19sWEBDAiy++2N7htovFixezZMmSetsSEhKYP39+k8d0pWcA4M477yQ7O7vB9osuuohbb721wfau8Axs376d119/nf3793Ps2DHuvvtuxo0bV/e+4zgsXryY999/n+LiYoYMGcKtt95KfHz8Cc/b0t8nvnSiNqiqqmLRokVs3LiRrKwsQkJCGD58ODfccAPR0dFNnvNUfp586WTPwfPPP8+aNWvqHXPmmWfyy1/+8oTn7SzPwcnu/5prrmn0uJtuuonLLrus0fc62zMgrfViabcAAA6/SURBVKM+lPpQ6kN1rz6U+k/qP4H6T9C9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\n"},"metadata":{}}],"source":["# Entraîner le modèle LSTM avec Word2Vec\n","model_lstm_word2vec, history_lstm_word2vec, metrics_lstm_word2vec, run_id_lstm_word2vec = train_word2vec_lstm_model(epochs=50)"]},{"cell_type":"markdown","metadata":{"id":"CD8guTB_NwMx"},"source":["## Chargement du modèle entraîné\n","\n","Dans cette fonction, nous créons un mécanisme pour charger un **modèle complet** avec tous ses composants associés. Nous récupérons l'ensemble des artefacts nécessaires pour faire fonctionner notre modèle d'analyse de sentiment à partir d'un emplacement spécifique.\n","\n","- Nous chargeons d'abord le **modèle Keras entraîné** à partir du fichier .keras sauvegardé\n","- Nous récupérons le **tokenizer** qui convertit le texte brut en séquences numériques\n","- Nous importons la **fonction de prétraitement** qui nettoie les tweets avant l'analyse\n","- Nous lisons les **paramètres du modèle** à partir d'un fichier JSON\n","- Nous retournons tous ces éléments dans un dictionnaire cohérent, prêt à être utilisé pour prédire le sentiment de nouveaux tweets"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"9nXo7O_XNwMx"},"outputs":[],"source":["# Fonction pour charger un modèle complet avec tous ses artefacts\n","def load_complete_model(model_name, vectorizer_name):\n"," \"\"\"\n"," Charge un modèle complet avec son tokenizer et sa fonction de prétraitement.\n"," \"\"\"\n"," model_dir = f\"content/advanced-model/{model_name}_{vectorizer_name}\"\n","\n"," # Charger le modèle\n"," model_path = f\"{model_dir}/final_model_{model_name}_{vectorizer_name}.keras\"\n"," model = tf.keras.models.load_model(model_path)\n","\n"," # Charger le tokenizer\n"," tokenizer_path = f\"{model_dir}/tokenizer.pickle\"\n"," with open(tokenizer_path, 'rb') as handle:\n"," tokenizer = pickle.load(handle)\n","\n"," # Charger la fonction de prétraitement\n"," preprocess_path = f\"{model_dir}/preprocess_function.dill\"\n"," with open(preprocess_path, 'rb') as handle:\n"," preprocess_function = dill.load(handle)\n","\n"," # Charger les paramètres\n"," params_path = f\"{model_dir}/parameters.json\"\n"," with open(params_path, 'r') as f:\n"," params = json.load(f)\n","\n"," return {\n"," \"model\": model,\n"," \"tokenizer\": tokenizer,\n"," \"preprocess\": preprocess_function,\n"," \"params\": params\n"," }"]},{"cell_type":"markdown","metadata":{"id":"P7Ge212GNwMx"},"source":["## Prédire avec le modèle entraîné\n","\n","Dans cette fonction, nous mettons en œuvre le cœur de notre système d'analyse de sentiment, permettant de prédire si un tweet exprime un sentiment positif ou négatif. Nous utilisons l'ensemble des composants précédemment chargés pour traiter le texte et générer une prédiction fiable.\n","\n","- **Prétraitement du texte** : Application des transformations de nettoyage sur le tweet brut\n","- **Tokenisation** : Conversion du texte prétraité en séquences numériques\n","- **Padding** : Ajustement des séquences à une longueur uniforme\n","- **Prédiction** : Calcul de la probabilité de sentiment par le modèle LSTM\n","- **Interprétation** : Classification du tweet comme positif ou négatif selon le seuil de 0.5\n","- **Évaluation de confiance** : Détermination du niveau de certitude de la prédiction\n","- **Formatage des résultats** : Présentation des résultats sous forme de dictionnaire structuré"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"LpuAgS8_NwMx"},"outputs":[],"source":["# Fonction pour prédire le sentiment avec un modèle chargé\n","def predict_sentiment(text, model_pack):\n"," \"\"\"\n"," Prédit le sentiment d'un texte en utilisant un modèle chargé.\n"," \"\"\"\n"," model = model_pack[\"model\"]\n"," tokenizer = model_pack[\"tokenizer\"]\n"," preprocess = model_pack[\"preprocess\"]\n"," params = model_pack[\"params\"]\n","\n"," # Prétraiter le texte\n"," preprocessed_text = preprocess(text)\n","\n"," # Tokeniser et encoder le texte\n"," tokens = tokenizer.texts_to_sequences([preprocessed_text])\n"," max_length = params.get(\"max_sequence_length\", MAX_SEQUENCE_LENGTH)\n"," padded_tokens = pad_sequences(tokens, maxlen=max_length, padding='post', truncating='post')\n","\n"," # Prédire le sentiment\n"," prediction = model.predict(padded_tokens)[0][0]\n","\n"," # Interpréter la prédiction\n"," sentiment = \"Positif\" if prediction >= 0.5 else \"Négatif\"\n"," confidence = prediction if prediction >= 0.5 else 1 - prediction\n","\n"," return {\n"," 'sentiment': sentiment,\n"," 'confidence': float(confidence),\n"," 'raw_score': float(prediction)\n"," }"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"eWAj3vceNwMx"},"outputs":[],"source":["# Liste améliorée de tweets pour tester le modèle\n","test_tweets_improved = [\n"," # Tweets positifs avec différentes caractéristiques\n"," \"I absolutely love flying with @AirParadis! Their service is amazing and their staff is so helpful :) #bestairline #travel\",\n"," \"Just landed after a wonderful flight... The crew was totally awesome and the food was perfect!!! Can't wait to fly with them again :D\",\n"," \"OMG! You really have to try @AirParadis. Best. Flight. Ever. Their new seats are extremely comfortable. http://airparadis.com/newseats #travel #comfort\",\n"," \"We had a very pleasant experience with our flight today. The staff completely exceeded our expectations ;) #happy #AirParadis\",\n"," \"My first time flying business class and I'm absolutely amazed!!! The service is 100% worth it... @AirParadis never disappoints :)\",\n","\n"," # Tweets négatifs avec différentes caractéristiques\n"," \"I hate how @AirParadis always delays their flights... This is the third time this month!!! :( #disappointed #travel\",\n"," \"The worst flight experience of my life? Definitely today with @AirParadis. Their customer service won't even respond to my complaints... #terrible\",\n"," \"Really @AirParadis??? Flight cancelled and no compensation??? That's how you treat your customers? SMH :(\",\n"," \"Our baggage was lost and nobody at @AirParadis seems to care! Don't they understand that we can't enjoy our vacation without our stuff??? http://badservice.com/complaint :-(\",\n"," \"Food was terrible, seats were uncomfortable, and the staff was not helpful at all... Never flying with @AirParadis again! #worstairline\",\n","\n"," # Tweets mixtes et nuancés\n"," \"The flight was good but the food wasn't really what I expected... @AirParadis can do better! #mixedfeelings\",\n"," \"IDK what to think about my @AirParadis experience? The crew was nice but the flight was delayed for 2 hours... #confused\",\n"," \"My husband loved the flight but I didn't... Too bad they can't make everyone happy :-) #AirParadis\",\n"," \"TBH, @AirParadis has improved their service since last year! Not perfect yet, but they're trying... #progress\",\n"," \"We were so excited for our trip but then our flight got delayed... at least the staff was very apologetic and gave us free drinks! @AirParadis\",\n","\n"," # Tweets spécifiquement pour tester les caractéristiques spéciales\n"," \"This is a tweet with many!!! exclamation!!! marks!!! to test how they affect sentiment analysis :)\",\n"," \"How does the model handle multiple??? question??? marks??? in a single tweet? @AirParadis\",\n"," \"Testing ellipses... many... many... ellipses... in... one... tweet... @AirParadis #test\",\n"," \"#many #hashtags #in #one #tweet #to #see #how #they #affect #the #analysis #AirParadis\",\n"," \"@mention1 @mention2 @mention3 @mention4 @mention5 multiple mentions in one tweet\",\n"," \"Multiple URLs in one tweet: http://example1.com http://example2.com http://example3.com @AirParadis\",\n"," \"Let's try all emoticons :) :( :D ;) :-) :-( :-D ;-) in a single tweet to see the impact\"\n","]"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"hRAWxNusNwMy","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1751830278905,"user_tz":-120,"elapsed":9239,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}},"outputId":"da9971f0-92e6-49fd-a56f-9da5946ddc8f"},"outputs":[{"output_type":"stream","name":"stdout","text":["\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 2s/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 33ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 31ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 29ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 31ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 31ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 30ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 31ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 32ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 31ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 30ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 31ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 31ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 30ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 32ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 32ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 33ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 29ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 29ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 39ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 35ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 34ms/step\n","\n","Test du modèle sur les exemples:\n","==================================================\n","Résumé: 22 tweets analysés\n","Tweets positifs: 10 (45.5%)\n","Tweets négatifs: 12 (54.5%)\n"]}],"source":["def test_model_on_examples(model_pack, test_tweets):\n"," \"\"\"\n"," Teste le modèle sur une liste de tweets et retourne un DataFrame avec les résultats des prédictions.\n"," \"\"\"\n"," results = {\n"," \"Positif\": 0,\n"," \"Négatif\": 0\n"," }\n","\n"," # Créer un DataFrame pour stocker les résultats\n"," predictions_data = []\n","\n"," for i, tweet in enumerate(test_tweets):\n"," # Utiliser la fonction predict_sentiment avec model_pack\n"," result = predict_sentiment(tweet, model_pack)\n","\n"," # Ajouter l'emoji approprié pour le sentiment\n"," emoji = \"💚\" if result['sentiment'] == \"Positif\" else \"❌\"\n","\n"," # Ajouter les données au DataFrame\n"," predictions_data.append({\n"," \"Tweet\": tweet,\n"," \"Sentiment\": result['sentiment'],\n"," \"Emoji\": emoji,\n"," \"Score de confiance\": result['confidence'],\n"," \"Score brut\": result['raw_score'],\n"," \"Index\": i+1\n"," })\n","\n"," # Comptage des résultats\n"," results[result['sentiment']] += 1\n","\n"," # Créer le DataFrame\n"," df_predictions = pd.DataFrame(predictions_data)\n","\n"," # Afficher un résumé\n"," print(\"\\nTest du modèle sur les exemples:\")\n"," print(\"=\"*50)\n"," print(f\"Résumé: {len(test_tweets)} tweets analysés\")\n"," print(f\"Tweets positifs: {results['Positif']} ({(results['Positif']/len(test_tweets)*100):.1f}%)\")\n"," print(f\"Tweets négatifs: {results['Négatif']} ({(results['Négatif']/len(test_tweets)*100):.1f}%)\")\n","\n"," # Retourner le DataFrame\n"," return df_predictions\n","\n","# Exemple d'utilisation:\n","# Charger le model_pack (qui contient model, tokenizer, preprocess, params)\n","lstm_word2vec_model_pack = load_complete_model(\"LSTM\", \"Word2Vec-Fige\")\n","\n","# Obtenir le DataFrame des prédictions\n","df_results_word2vec = test_model_on_examples(lstm_word2vec_model_pack, test_tweets_improved)\n","\n","# Optionnel: sauvegarder les résultats dans un fichier CSV\n","df_results_word2vec.to_csv(\"content/advanced-model/LSTM_Word2Vec-Fige/predictions_results.csv\", index=False)"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"aCXO6s63NwMy","colab":{"base_uri":"https://localhost:8080/","height":739},"executionInfo":{"status":"ok","timestamp":1751830278990,"user_tz":-120,"elapsed":84,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}},"outputId":"9f52a557-cf1d-4738-be5d-c44e17e7b163"},"outputs":[{"output_type":"execute_result","data":{"text/plain":[" Tweet Sentiment Emoji \\\n","0 I absolutely love flying with @AirParadis! The... Positif 💚 \n","1 Just landed after a wonderful flight... The cr... Positif 💚 \n","2 OMG! You really have to try @AirParadis. Best.... Positif 💚 \n","3 We had a very pleasant experience with our fli... Positif 💚 \n","4 My first time flying business class and I'm ab... Négatif ❌ \n","5 I hate how @AirParadis always delays their fli... Négatif ❌ \n","6 The worst flight experience of my life? Defini... Négatif ❌ \n","7 Really @AirParadis??? Flight cancelled and no ... Négatif ❌ \n","8 Our baggage was lost and nobody at @AirParadis... Négatif ❌ \n","9 Food was terrible, seats were uncomfortable, a... Négatif ❌ \n","10 The flight was good but the food wasn't really... Positif 💚 \n","11 IDK what to think about my @AirParadis experie... Négatif ❌ \n","12 My husband loved the flight but I didn't... To... Négatif ❌ \n","13 TBH, @AirParadis has improved their service si... Positif 💚 \n","14 We were so excited for our trip but then our f... Négatif ❌ \n","15 This is a tweet with many!!! exclamation!!! ma... Négatif ❌ \n","16 How does the model handle multiple??? question... Négatif ❌ \n","17 Testing ellipses... many... many... ellipses..... Positif 💚 \n","18 #many #hashtags #in #one #tweet #to #see #how ... Négatif ❌ \n","19 @mention1 @mention2 @mention3 @mention4 @menti... Positif 💚 \n","20 Multiple URLs in one tweet: http://example1.co... Positif 💚 \n","21 Let's try all emoticons :) :( :D ;) :-) :-( :-... Positif 💚 \n","\n"," Score de confiance Score brut Index \n","0 0.995117 0.995117 1 \n","1 0.995117 0.995117 2 \n","2 0.979980 0.979980 3 \n","3 0.986328 0.986328 4 \n","4 0.541992 0.458008 5 \n","5 0.992825 0.007175 6 \n","6 0.971252 0.028748 7 \n","7 0.727051 0.272949 8 \n","8 0.942810 0.057190 9 \n","9 0.909424 0.090576 10 \n","10 0.918457 0.918457 11 \n","11 0.915649 0.084351 12 \n","12 0.536621 0.463379 13 \n","13 0.588379 0.588379 14 \n","14 0.541748 0.458252 15 \n","15 0.836792 0.163208 16 \n","16 0.510498 0.489502 17 \n","17 0.675293 0.675293 18 \n","18 0.591064 0.408936 19 \n","19 0.909180 0.909180 20 \n","20 0.994141 0.994141 21 \n","21 0.951660 0.951660 22 "],"text/html":["\n","
\n","
\n","\n","
\n"," \n","
\n","
\n","
Tweet
\n","
Sentiment
\n","
Emoji
\n","
Score de confiance
\n","
Score brut
\n","
Index
\n","
\n"," \n"," \n","
\n","
0
\n","
I absolutely love flying with @AirParadis! The...
\n","
Positif
\n","
💚
\n","
0.995117
\n","
0.995117
\n","
1
\n","
\n","
\n","
1
\n","
Just landed after a wonderful flight... The cr...
\n","
Positif
\n","
💚
\n","
0.995117
\n","
0.995117
\n","
2
\n","
\n","
\n","
2
\n","
OMG! You really have to try @AirParadis. Best....
\n","
Positif
\n","
💚
\n","
0.979980
\n","
0.979980
\n","
3
\n","
\n","
\n","
3
\n","
We had a very pleasant experience with our fli...
\n","
Positif
\n","
💚
\n","
0.986328
\n","
0.986328
\n","
4
\n","
\n","
\n","
4
\n","
My first time flying business class and I'm ab...
\n","
Négatif
\n","
❌
\n","
0.541992
\n","
0.458008
\n","
5
\n","
\n","
\n","
5
\n","
I hate how @AirParadis always delays their fli...
\n","
Négatif
\n","
❌
\n","
0.992825
\n","
0.007175
\n","
6
\n","
\n","
\n","
6
\n","
The worst flight experience of my life? Defini...
\n","
Négatif
\n","
❌
\n","
0.971252
\n","
0.028748
\n","
7
\n","
\n","
\n","
7
\n","
Really @AirParadis??? Flight cancelled and no ...
\n","
Négatif
\n","
❌
\n","
0.727051
\n","
0.272949
\n","
8
\n","
\n","
\n","
8
\n","
Our baggage was lost and nobody at @AirParadis...
\n","
Négatif
\n","
❌
\n","
0.942810
\n","
0.057190
\n","
9
\n","
\n","
\n","
9
\n","
Food was terrible, seats were uncomfortable, a...
\n","
Négatif
\n","
❌
\n","
0.909424
\n","
0.090576
\n","
10
\n","
\n","
\n","
10
\n","
The flight was good but the food wasn't really...
\n","
Positif
\n","
💚
\n","
0.918457
\n","
0.918457
\n","
11
\n","
\n","
\n","
11
\n","
IDK what to think about my @AirParadis experie...
\n","
Négatif
\n","
❌
\n","
0.915649
\n","
0.084351
\n","
12
\n","
\n","
\n","
12
\n","
My husband loved the flight but I didn't... To...
\n","
Négatif
\n","
❌
\n","
0.536621
\n","
0.463379
\n","
13
\n","
\n","
\n","
13
\n","
TBH, @AirParadis has improved their service si...
\n","
Positif
\n","
💚
\n","
0.588379
\n","
0.588379
\n","
14
\n","
\n","
\n","
14
\n","
We were so excited for our trip but then our f...
\n","
Négatif
\n","
❌
\n","
0.541748
\n","
0.458252
\n","
15
\n","
\n","
\n","
15
\n","
This is a tweet with many!!! exclamation!!! ma...
\n","
Négatif
\n","
❌
\n","
0.836792
\n","
0.163208
\n","
16
\n","
\n","
\n","
16
\n","
How does the model handle multiple??? question...
\n","
Négatif
\n","
❌
\n","
0.510498
\n","
0.489502
\n","
17
\n","
\n","
\n","
17
\n","
Testing ellipses... many... many... ellipses.....
\n","
Positif
\n","
💚
\n","
0.675293
\n","
0.675293
\n","
18
\n","
\n","
\n","
18
\n","
#many #hashtags #in #one #tweet #to #see #how ...
\n","
Négatif
\n","
❌
\n","
0.591064
\n","
0.408936
\n","
19
\n","
\n","
\n","
19
\n","
@mention1 @mention2 @mention3 @mention4 @menti...
\n","
Positif
\n","
💚
\n","
0.909180
\n","
0.909180
\n","
20
\n","
\n","
\n","
20
\n","
Multiple URLs in one tweet: http://example1.co...
\n","
Positif
\n","
💚
\n","
0.994141
\n","
0.994141
\n","
21
\n","
\n","
\n","
21
\n","
Let's try all emoticons :) :( :D ;) :-) :-( :-...
\n","
Positif
\n","
💚
\n","
0.951660
\n","
0.951660
\n","
22
\n","
\n"," \n","
\n","
\n","
\n","\n","
\n"," \n","\n"," \n","\n"," \n","
\n","\n","\n","
\n"," \n","\n","\n","\n"," \n","
\n","\n","
\n"," \n"," \n"," \n","
\n","\n","
\n","
\n"],"application/vnd.google.colaboratory.intrinsic+json":{"type":"dataframe","variable_name":"df_results_word2vec","summary":"{\n \"name\": \"df_results_word2vec\",\n \"rows\": 22,\n \"fields\": [\n {\n \"column\": \"Tweet\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 22,\n \"samples\": [\n \"I absolutely love flying with @AirParadis! Their service is amazing and their staff is so helpful :) #bestairline #travel\",\n \"TBH, @AirParadis has improved their service since last year! Not perfect yet, but they're trying... #progress\",\n \"Our baggage was lost and nobody at @AirParadis seems to care! Don't they understand that we can't enjoy our vacation without our stuff??? http://badservice.com/complaint :-(\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Sentiment\",\n \"properties\": {\n \"dtype\": \"category\",\n \"num_unique_values\": 2,\n \"samples\": [\n \"N\\u00e9gatif\",\n \"Positif\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Emoji\",\n \"properties\": {\n \"dtype\": \"category\",\n \"num_unique_values\": 2,\n \"samples\": [\n \"\\u274c\",\n \"\\ud83d\\udc9a\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Score de confiance\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.1866448337305405,\n \"min\": 0.510498046875,\n \"max\": 0.9951171875,\n \"num_unique_values\": 21,\n \"samples\": [\n 0.9951171875,\n 0.591064453125\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Score brut\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.3730689855539598,\n \"min\": 0.007175445556640625,\n \"max\": 0.9951171875,\n \"num_unique_values\": 21,\n \"samples\": [\n 0.9951171875,\n 0.408935546875\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Index\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 6,\n \"min\": 1,\n \"max\": 22,\n \"num_unique_values\": 22,\n \"samples\": [\n 1,\n 14\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}"}},"metadata":{},"execution_count":35}],"source":["df_results_word2vec"]},{"cell_type":"markdown","metadata":{"id":"Yk_yH3-INwMy"},"source":["## Entrainement : LSTM avec GloVe 300d"]},{"cell_type":"markdown","metadata":{"id":"E-yiOEKYNwMy"},"source":["### Chargement et préparation des embeddings pré-entraînés GloVe"]},{"cell_type":"code","source":["import os\n","import requests\n","from tqdm import tqdm\n","from zipfile import ZipFile\n","\n","# Télécharger et préparer les embeddings GloVe\n","def download_glove_embeddings(url=\"https://nlp.stanford.edu/data/glove.6B.zip\",\n"," output_dir=\"content/pretrained-embeddings/glove.6B\"):\n"," \"\"\"\n"," Télécharge et extrait les embeddings GloVe si nécessaire.\n"," Inclut une barre de progression et vérifie si les fichiers existent déjà.\n"," \"\"\"\n"," # Check if directory already exists\n"," if os.path.exists(output_dir) and os.listdir(output_dir):\n"," print(f\"Le dossier {output_dir} existe déjà. Téléchargement ignoré.\")\n"," return\n","\n"," # Create directory if it doesn't exist\n"," os.makedirs(output_dir, exist_ok=True)\n","\n"," # Temporary zip file path\n"," zip_path = \"glove.6B.zip\"\n","\n"," # Download the file with progress bar\n"," print(\"Téléchargement du fichier...\")\n"," # Add verify=False to ignore SSL certificate issues\n"," response = requests.get(url, stream=True, verify=False)\n"," total_size = int(response.headers.get('content-length', 0))\n","\n"," with open(zip_path, 'wb') as f, tqdm(\n"," desc=\"Téléchargement\",\n"," total=total_size,\n"," unit='B',\n"," unit_scale=True,\n"," unit_divisor=1024,\n"," ) as bar:\n"," for data in response.iter_content(chunk_size=1024):\n"," size = f.write(data)\n"," bar.update(size)\n","\n"," # Extract with progress bar\n"," print(\"Extraction des fichiers...\")\n"," with ZipFile(zip_path, 'r') as zip_ref:\n"," for file in tqdm(zip_ref.namelist(), desc=\"Extraction\"):\n"," zip_ref.extract(file, output_dir)\n","\n"," # Remove the zip file\n"," os.remove(zip_path)\n"," print(\"Terminé!\")\n","\n","# Exécuter la fonction\n","download_glove_embeddings()"],"metadata":{"id":"9y9NubYo_DLG","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1751830278993,"user_tz":-120,"elapsed":3,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}},"outputId":"12613b2b-a219-4860-ba02-f8a00932f053"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Le dossier content/pretrained-embeddings/glove.6B existe déjà. Téléchargement ignoré.\n"]}]},{"cell_type":"code","execution_count":null,"metadata":{"id":"vk_8gucuNwMy"},"outputs":[],"source":["def load_glove_embeddings(embedding_dim=100):\n"," \"\"\"\n"," Charge les embeddings GloVe pré-entraînés.\n"," \"\"\"\n"," print(f\"Chargement des embeddings GloVe {embedding_dim}d...\")\n"," embeddings_index = {}\n","\n"," with open(f'content/pretrained-embeddings/glove.6B/glove.6B.{embedding_dim}d.txt', encoding='utf-8') as f:\n"," for line in f:\n"," values = line.rstrip().split(' ')\n"," word = values[0]\n"," coefs = np.asarray(values[1:], dtype='float32')\n"," embeddings_index[word] = coefs\n","\n"," print(f\"Trouvé {len(embeddings_index)} vecteurs d'embeddings GloVe.\")\n"," return embeddings_index"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"AegR2uCfNwMy","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1751830310660,"user_tz":-120,"elapsed":31665,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}},"outputId":"6150eeae-cf38-4ec3-a548-eeb1f3bbd2fd"},"outputs":[{"output_type":"stream","name":"stdout","text":["Chargement des embeddings GloVe 300d...\n","Trouvé 400000 vecteurs d'embeddings GloVe.\n","Création de la matrice d'embedding pour 83730 mots...\n"]},{"output_type":"stream","name":"stderr","text":["Création matrice d'embedding: 100%|██████████| 83730/83730 [00:00<00:00, 353325.63it/s]"]},{"output_type":"stream","name":"stdout","text":["Trouvé 37172 mots (44.40%) dans les embeddings pré-entraînés.\n"]},{"output_type":"stream","name":"stderr","text":["\n"]}],"source":["glove_embeddings_300d = load_glove_embeddings(embedding_dim=300)\n","glove_matrix_300d = create_embedding_matrix(tokenizer.word_index, glove_embeddings_300d, 300)"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"gPwavY_xNwMy"},"outputs":[],"source":["def train_glove_lstm_model(epochs=20):\n"," \"\"\"\n"," Entraîne un modèle LSTM avec embeddings GloVe 300d en utilisant les optimisations GPU\n"," et le chargement de données optimisé.\n"," \"\"\"\n"," # Définir le nom du modèle et de la méthode d'embedding\n"," model_name = \"LSTM\"\n"," vectorizer_name = \"GloVe-300d-Fige\"\n","\n"," # Créer les callbacks pour ce modèle\n"," checkpoint_callback = create_model_checkpoint(model_name, vectorizer_name)\n","\n"," # Autres callbacks\n"," early_stopping = tf.keras.callbacks.EarlyStopping(\n"," monitor='val_loss',\n"," patience=5,\n"," restore_best_weights=True\n"," )\n","\n"," reduce_lr = tf.keras.callbacks.ReduceLROnPlateau(\n"," monitor='val_loss',\n"," factor=0.2,\n"," patience=2,\n"," min_lr=0.00001\n"," )\n","\n"," # TensorBoard pour visualiser l'entraînement\n"," tensorboard_dir = f\"content/advanced-model/{model_name}_{vectorizer_name}/logs\"\n"," os.makedirs(tensorboard_dir, exist_ok=True)\n"," tensorboard_callback = tf.keras.callbacks.TensorBoard(\n"," log_dir=tensorboard_dir,\n"," histogram_freq=1,\n"," update_freq='epoch'\n"," )\n","\n"," # Créer le modèle optimisé pour GPU\n"," model = create_optimized_lstm_model(glove_matrix_300d, trainable=False)\n","\n"," print(f\"Entraînement du modèle {model_name} avec embeddings {vectorizer_name}\")\n"," print(f\"Taille du batch: {BATCH_SIZE}\")\n"," print(f\"Utilisation de la précision mixte: {tf.keras.mixed_precision.global_policy().name}\")\n","\n"," # Entraîner le modèle avec les datasets optimisés\n"," history = model.fit(\n"," train_dataset,\n"," epochs=epochs,\n"," validation_data=val_dataset,\n"," callbacks=[early_stopping, reduce_lr, tensorboard_callback, checkpoint_callback],\n"," verbose=1\n"," )\n","\n"," # Déterminer le nombre réel d'époques complétées (en cas d'early stopping)\n"," real_epochs = len(history.history['loss'])\n"," print(f\"Nombre réel d'époques effectuées: {real_epochs}/{epochs}\")\n","\n"," # Sauvegarder tous les artefacts\n"," model_dir = save_model_artifacts(model, model_name, vectorizer_name, history, tokenizer)\n","\n"," # Utiliser evaluate_model pour obtenir les métriques\n"," metrics, cm, report, y_pred, y_pred_proba = evaluate_model(\n"," model,\n"," X_test_pad,\n"," y_test\n"," )\n","\n"," # Afficher les métriques\n"," print(\"\\nMétriques pour le modèle LSTM avec embedding GloVe 300d:\")\n"," for key, value in metrics.items():\n"," print(f\"{key}: {value:.4f}\")\n","\n"," print(\"\\nRapport de classification:\")\n"," print(report)\n","\n"," # Enregistrer avec MLflow\n"," params = {\n"," 'model_type': model_name,\n"," 'embedding_type': vectorizer_name,\n"," 'embedding_dim': 300,\n"," 'vocab_size': len(tokenizer.word_index) + 1,\n"," 'max_sequence_length': MAX_SEQUENCE_LENGTH,\n"," 'trainable_embedding': False,\n"," 'max_epochs': epochs,\n"," 'real_epochs': real_epochs,\n"," 'batch_size': BATCH_SIZE,\n"," 'precision_policy': tf.keras.mixed_precision.global_policy().name,\n"," 'gpu_optimization': 'XLA,dynamic_memory,prefetch',\n"," 'sample_size': sample_size*2\n","\n"," }\n","\n"," # Enregistrer dans MLflow\n"," run_id = log_model_to_mlflow(model, model_name, vectorizer_name, metrics, cm, report, X_test_pad, y_test, history, params)\n","\n"," # Visualiser la courbe d'apprentissage\n"," plot_training_history(history, \"LSTM\", \"GloVe-300d-Fige\", run_id=run_id)\n","\n"," # Récupérer le lien vers le run MLflow\n"," print(f\"\\nRun MLflow ID: {run_id}\")\n"," print(f\"Accédez à l'interface MLflow pour voir les détails complets.\")\n","\n"," return model, history, metrics, run_id"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"HwGyTzEwNwMy","colab":{"base_uri":"https://localhost:8080/","height":1000},"executionInfo":{"status":"ok","timestamp":1751830700356,"user_tz":-120,"elapsed":389684,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}},"outputId":"cba5a433-e6c6-4898-b9fc-9f133a85cca8"},"outputs":[{"output_type":"stream","name":"stdout","text":["Entraînement du modèle LSTM avec embeddings GloVe-300d-Fige\n","Taille du batch: 256\n","Utilisation de la précision mixte: mixed_float16\n","Epoch 1/50\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 18ms/step - loss: 0.5846 - precision: 0.6888 - recall: 0.6777\n","Epoch 1: val_precision improved from -inf to 0.74994, saving model to content/advanced-model/LSTM_GloVe-300d-Fige/checkpoints/best_model.keras\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m38s\u001b[0m 51ms/step - loss: 0.5845 - precision: 0.6889 - recall: 0.6778 - val_loss: 0.4928 - val_precision: 0.7499 - val_recall: 0.7811 - learning_rate: 0.0010\n","Epoch 2/50\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 25ms/step - loss: 0.5067 - precision: 0.7539 - recall: 0.7542\n","Epoch 2: val_precision improved from 0.74994 to 0.76657, saving model to content/advanced-model/LSTM_GloVe-300d-Fige/checkpoints/best_model.keras\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m25s\u001b[0m 45ms/step - loss: 0.5067 - precision: 0.7539 - recall: 0.7542 - val_loss: 0.4712 - val_precision: 0.7666 - val_recall: 0.7825 - learning_rate: 0.0010\n","Epoch 3/50\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 18ms/step - loss: 0.4808 - precision: 0.7700 - recall: 0.7696\n","Epoch 3: val_precision improved from 0.76657 to 0.77947, saving model to content/advanced-model/LSTM_GloVe-300d-Fige/checkpoints/best_model.keras\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m18s\u001b[0m 32ms/step - loss: 0.4808 - precision: 0.7700 - recall: 0.7696 - val_loss: 0.4607 - val_precision: 0.7795 - val_recall: 0.7838 - learning_rate: 0.0010\n","Epoch 4/50\n","\u001b[1m561/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 18ms/step - loss: 0.4680 - precision: 0.7794 - recall: 0.7787\n","Epoch 4: val_precision did not improve from 0.77947\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m20s\u001b[0m 31ms/step - loss: 0.4680 - precision: 0.7794 - recall: 0.7787 - val_loss: 0.4558 - val_precision: 0.7790 - val_recall: 0.7973 - learning_rate: 0.0010\n","Epoch 5/50\n","\u001b[1m561/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 17ms/step - loss: 0.4549 - precision: 0.7842 - recall: 0.7902\n","Epoch 5: val_precision improved from 0.77947 to 0.78158, saving model to content/advanced-model/LSTM_GloVe-300d-Fige/checkpoints/best_model.keras\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m18s\u001b[0m 32ms/step - loss: 0.4549 - precision: 0.7842 - recall: 0.7902 - val_loss: 0.4493 - val_precision: 0.7816 - val_recall: 0.7962 - learning_rate: 0.0010\n","Epoch 6/50\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 18ms/step - loss: 0.4480 - precision: 0.7879 - recall: 0.7926\n","Epoch 6: val_precision improved from 0.78158 to 0.79068, saving model to content/advanced-model/LSTM_GloVe-300d-Fige/checkpoints/best_model.keras\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m18s\u001b[0m 31ms/step - loss: 0.4480 - precision: 0.7879 - recall: 0.7926 - val_loss: 0.4510 - val_precision: 0.7907 - val_recall: 0.7846 - learning_rate: 0.0010\n","Epoch 7/50\n","\u001b[1m561/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 18ms/step - loss: 0.4383 - precision: 0.7925 - recall: 0.7982\n","Epoch 7: val_precision improved from 0.79068 to 0.79648, saving model to content/advanced-model/LSTM_GloVe-300d-Fige/checkpoints/best_model.keras\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m18s\u001b[0m 32ms/step - loss: 0.4383 - precision: 0.7925 - recall: 0.7982 - val_loss: 0.4497 - val_precision: 0.7965 - val_recall: 0.7820 - learning_rate: 0.0010\n","Epoch 8/50\n","\u001b[1m562/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 18ms/step - loss: 0.4264 - precision: 0.8006 - recall: 0.8040\n","Epoch 8: val_precision did not improve from 0.79648\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m19s\u001b[0m 30ms/step - loss: 0.4264 - precision: 0.8006 - recall: 0.8040 - val_loss: 0.4476 - val_precision: 0.7895 - val_recall: 0.7979 - learning_rate: 2.0000e-04\n","Epoch 9/50\n","\u001b[1m562/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 18ms/step - loss: 0.4218 - precision: 0.8034 - recall: 0.8065\n","Epoch 9: val_precision did not improve from 0.79648\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m16s\u001b[0m 29ms/step - loss: 0.4217 - precision: 0.8034 - recall: 0.8065 - val_loss: 0.4470 - val_precision: 0.7929 - val_recall: 0.7899 - learning_rate: 2.0000e-04\n","Epoch 10/50\n","\u001b[1m561/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 17ms/step - loss: 0.4177 - precision: 0.8069 - recall: 0.8114\n","Epoch 10: val_precision did not improve from 0.79648\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m17s\u001b[0m 30ms/step - loss: 0.4176 - precision: 0.8069 - recall: 0.8114 - val_loss: 0.4476 - val_precision: 0.7918 - val_recall: 0.7935 - learning_rate: 2.0000e-04\n","Epoch 11/50\n","\u001b[1m560/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 17ms/step - loss: 0.4160 - precision: 0.8084 - recall: 0.8073\n","Epoch 11: val_precision did not improve from 0.79648\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m17s\u001b[0m 30ms/step - loss: 0.4160 - precision: 0.8084 - recall: 0.8073 - val_loss: 0.4439 - val_precision: 0.7879 - val_recall: 0.7983 - learning_rate: 2.0000e-04\n","Epoch 12/50\n","\u001b[1m560/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 16ms/step - loss: 0.4114 - precision: 0.8107 - recall: 0.8128\n","Epoch 12: val_precision did not improve from 0.79648\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m17s\u001b[0m 29ms/step - loss: 0.4114 - precision: 0.8107 - recall: 0.8128 - val_loss: 0.4477 - val_precision: 0.7933 - val_recall: 0.7859 - learning_rate: 2.0000e-04\n","Epoch 13/50\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 18ms/step - loss: 0.4082 - precision: 0.8122 - recall: 0.8132\n","Epoch 13: val_precision improved from 0.79648 to 0.79806, saving model to content/advanced-model/LSTM_GloVe-300d-Fige/checkpoints/best_model.keras\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m22s\u001b[0m 33ms/step - loss: 0.4082 - precision: 0.8122 - recall: 0.8132 - val_loss: 0.4512 - val_precision: 0.7981 - val_recall: 0.7848 - learning_rate: 2.0000e-04\n","Epoch 14/50\n","\u001b[1m562/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 17ms/step - loss: 0.4061 - precision: 0.8131 - recall: 0.8138\n","Epoch 14: val_precision did not improve from 0.79806\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m20s\u001b[0m 31ms/step - loss: 0.4061 - precision: 0.8131 - recall: 0.8138 - val_loss: 0.4503 - val_precision: 0.7909 - val_recall: 0.7964 - learning_rate: 4.0000e-05\n","Epoch 15/50\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 18ms/step - loss: 0.4043 - precision: 0.8120 - recall: 0.8154\n","Epoch 15: val_precision did not improve from 0.79806\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m19s\u001b[0m 29ms/step - loss: 0.4043 - precision: 0.8120 - recall: 0.8154 - val_loss: 0.4489 - val_precision: 0.7887 - val_recall: 0.8076 - learning_rate: 4.0000e-05\n","Epoch 16/50\n","\u001b[1m562/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m━\u001b[0m \u001b[1m0s\u001b[0m 18ms/step - loss: 0.4059 - precision: 0.8114 - recall: 0.8184\n","Epoch 16: val_precision did not improve from 0.79806\n","\u001b[1m563/563\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m17s\u001b[0m 30ms/step - loss: 0.4058 - precision: 0.8114 - recall: 0.8184 - val_loss: 0.4540 - val_precision: 0.7889 - val_recall: 0.7955 - learning_rate: 1.0000e-05\n","Nombre réel d'époques effectuées: 16/50\n","Modèle sauvegardé dans content/advanced-model/LSTM_GloVe-300d-Fige/final_model_LSTM_GloVe-300d-Fige.keras\n","Tokenizer sauvegardé dans content/advanced-model/LSTM_GloVe-300d-Fige/tokenizer.pickle\n","Fonction de prétraitement sauvegardée dans content/advanced-model/LSTM_GloVe-300d-Fige/preprocess_function.dill\n","Historique d'entraînement sauvegardé dans content/advanced-model/LSTM_GloVe-300d-Fige/training_history.pickle\n","Paramètres sauvegardés dans content/advanced-model/LSTM_GloVe-300d-Fige/parameters.json\n","\u001b[1m1250/1250\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m9s\u001b[0m 5ms/step\n","\n","Métriques pour le modèle LSTM avec embedding GloVe 300d:\n","accuracy: 0.7916\n","precision: 0.7915\n","recall: 0.7918\n","f1: 0.7917\n","roc_auc: 0.8761\n","\n","Rapport de classification:\n"," precision recall f1-score support\n","\n"," Négatif 0.79 0.79 0.79 20000\n"," Positif 0.79 0.79 0.79 20000\n","\n"," accuracy 0.79 40000\n"," macro avg 0.79 0.79 0.79 40000\n","weighted avg 0.79 0.79 0.79 40000\n","\n"]},{"output_type":"stream","name":"stderr","text":["2025/07/06 19:37:36 WARNING mlflow.models.model: `artifact_path` is deprecated. Please use `name` instead.\n"]},{"output_type":"stream","name":"stdout","text":["🏃 View run Modele_Avance_LSTM_GloVe-300d-Fige at: https://mlflow.greg-madman-nas.duckdns.org/#/experiments/1/runs/5b50de7aafde4b5793aaf188e07caa49\n","🧪 View experiment at: https://mlflow.greg-madman-nas.duckdns.org/#/experiments/1\n","🏃 View run Modele_Avance_LSTM_GloVe-300d-Fige at: https://mlflow.greg-madman-nas.duckdns.org/#/experiments/1/runs/5b50de7aafde4b5793aaf188e07caa49\n","🧪 View experiment at: https://mlflow.greg-madman-nas.duckdns.org/#/experiments/1\n","\n","Run MLflow ID: 5b50de7aafde4b5793aaf188e07caa49\n","Accédez à l'interface MLflow pour voir les détails complets.\n"]},{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"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a1FaAmvt2rUl+jiLFi0qVqa05EVFz3elLo9M79mzZ7Ht8fHxytHRUfn7+6v8/HyllFLvvfdeqf3HIkW/y6sTVtdz6NChYuenpmnqueeesxy3yNmzZ4uda1crmm1gMBgs24rWoLq6fUViYmIUoKKioizbivqLDz30UInyaWlplr+nyiSlyvopUtrr2qxZM6XT6Uo93owZM0r0uSrTdxe2IXffExX2+uuvA+bb3np7e9O7d28efvhhHnjggRJlu3btWmLb9u3bKSwsLHXdJ8By29NDhw5Ztm3ZsgVN0xg8eHClYr7tttt46aWXeOKJJ1ixYgWDBg2iZ8+etGrVqly3Ut61axcAAwYMKPGco6Mjffr04eTJk+zevZvGjRsXe75z584l9imaL3+t29IX2bNnD4sXLy62zdvbm0mTJl1334po3Lgxa9eu5dChQ6xatYodO3awbds2y8/HH3/MunXraNKkidWOOX78eJYvX87333/PnXfeyYIFC7jlllsICgqq1B1psrKyeP/991m0aBExMTFkZGQUW//n7Nmzxco/9NBDvPrqq3z55ZfF1h368ssvAYrNS7fFeVseRX+PVxozZsw11/+q7Pk8YcIE/vrrL+bMmcONN94IQE5ODt9++y3Ozs48+OCDgPmOmqmpqURGRjJjxoxSY3BxcSn2uyrtdzpmzJgS6wl8//33fP/996Snp7N//35ef/11evbsyezZs2v8NsIZGRkcPXqU0NBQmjVrVuL5fv36lXh91q1bx7p164ptCw8PLxF73759S5S7nt27dwPQq1evEs+5u7vTvn37EnUWrUPy559/WtYEvFJSUhKFhYXExMTQqVOnCsUjhKgdit6rgoODadGiRYnniz4Lit5DAO6//36effZZWrVqxT333EPfvn3p2bMnfn5+xfatav8K4L333itxR9/hw4db7sJlLU899RSPPPIIq1atYtOmTezevZtNmzYxf/585s+fz6uvvsr06dOtdrxu3brRpk0bPv/8c1555RXmzp2LyWSq1JqZRTZu3Mj777/P5s2bSUpKIj8/v9jzZ8+etXxuu7i4cNdddzFnzhxWrFjB0KFDAfN6kgcOHGDEiBHF7lRd0c+DLVu2ADBo0KBS10OyhnXr1pX4HB09erRlnaXSVOZ8L9rerFkzNm7cyKFDh2jZsiUA8+bNo6CggDFjxqDX64HL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K8yYMYOWLVsyfPhwQkNDOXfuHH/99Rfdu3fniy++KPN4X3/9NbNnz6ZXr140a9YMHx8fjh07xpIlS3Bycrru+kzu7u58/vnn3HnnnfTt25c777yTxo0bs3PnTlauXElAQACzZ8+24m/Iut56660yfz9PPfUUOp2Op59+mueff56ePXvSunVrPDw8SEpKsgxd9vf35913362W+G6++eYq1zFs2DAiIiKYNWsW+/bto0OHDpw+fZqlS5dyyy23cPr06TL3HT16NHPnzuXFF1+0PC5NTZ+3RQYOHMjChQsZPXo048aNY/r06fTt25egoCByc3OJj49n9erVpKSk0LZt22sucg5VP58nTJjAli1b2LBhA05OTqX+vl599VX27t3LJ598wpIlSxgwYADBwcEkJSURGxvLxo0bmTlzJq1atbpu++Pi4ujUqROdO3emefPmBAcHk5aWxp49e9iyZQt6vZ65c+da1rQq8vHHH9OjRw+eeuop1qxZQ8uWLdm6dStr164lKirKkmwt4uDgwLx58xgwYACjRo1i1KhRNG7cmDVr1rBjxw569uzJ5MmTi+3z7LPPsnjxYn766Sc6duzIoEGDSEtL44cffqBPnz7FklvVzdPTk48++ogHH3yQHj16cNdddxEYGMimTZvYu3cvffv25c8//yy2IG2LFi34/PPPGTduHNHR0QwePJioqCiMRiOnT59mw4YN+Pn5cfjw4RprhxCi4q413e3jjz/mueee4/fff+eXX36hXbt2DB06lOzsbH788UeSkpKYMmVKsYWCR4wYgbu7O927dyc8PBylFBs2bGD79u106tTJcrOLqvavrOHw4cNltr9x48ZMnz6d5cuXM3HiRMLDw+nZsyehoaHk5eURGxvLihUrMBqNPPXUU3Tp0sXq8TVu3NgqX1pOnjyZxx57jA4dOjBy5Ej0ej0bN27k4MGDDBs2jCVLlpS6X2hoKP3792fNmjU4OjrSpk2bUte1qsznwTfffEO/fv146aWX+Omnn+jXrx9KKWJjY1m5ciWHDx++7lpCDg4O/Pzzzzz00EP88ssvNG3alL59+9K6dWtcXV1JTk7mwIEDbNq0CYPBYJnudy0VPd+vdPPNNxMeHm5JNj355JMYDIZiZRo0aMDChQsZMWIE3bt3Z+DAgURHR6NpGnFxcWzevLncSTmA6dOns3HjRnr06EHjxo1xdXUlLi6O33//nbS0NHr06GHpoxbp0aMHzzzzDLNmzaJt27aMGjWK/Px8FixYQGpqKv/9739L/O7vuecefv75ZxYuXEiHDh0YNmwYKSkpLFiwgMLCQubMmWOZJgfm/uKnn37K3XffTe/evbn77rsJDAzkr7/+Yv/+/fTp06fUUZPVZcqUKSxevJjvv/+eI0eOcPPNN3Px4kVLn2vx4sUlFt2vaN9d2Ej5btInRPlvO6zU5Vuhr127tswyeXl56r///a+64YYblKenpzIYDCo0NFQNGDBA/ec//1Hnz58vsc+yZcvUoEGDlI+PjzIYDCokJEQNHz5crVmzxlKm6La9RbdOV8p8W97HHntMtW3bVvn4+ChnZ2fVrFkzNWbMGLVv375ixyjtVutFtm3bpoYPH64aNmyo9Hq9Cg0NVY899pg6e/ZsibKjR48u8zappcVYHa5321VALVq0SOXm5qpFixapiRMnqg4dOih/f3/l6OioPD09VceOHdXLL7+skpKSynWsa73mRefFnDlzrhu70WhUQInbwV7L6dOn1X333aeCgoKUs7OzatWqlXr77bctdV3rVs4REREKUL6+viovL6/MctV13pbH+fPn1Ztvvql69+6tGjZsqBwdHZW7u7tq0aKFeuihh9SSJUtK3JbZWufzlbKysiy3Ab733nvLLGcymdRXX32lBgwYoHx8fJRer1dBQUGqZ8+eaubMmer06dPlandqaqp6+eWXVa9evVRAQIDS6/XK1dVVtWjRQj366KPq4MGDZe57+vRpNWbMGMt+jRs3Vk8//fQ1b3N+4MABNWrUKNWgQQNlMBhUZGSkeu2111R2dnap5S9evKgmT56sgoKClJOTk2revLn697//rY4dO1bi9sTXU97bjl/rdf3tt9/UDTfcoFxcXJS3t7e67bbb1KFDh9Qtt9yiAHXhwoUS+/z9999q9OjRqnHjxspgMCgfHx8VHR2tJkyYUOHzVAhRc673GX/l33xOTo6aOXOmio6OVs7Ozsrd3V317NlTzZ8/v0S9//vf/9Tw4cNVkyZNlIuLi/Lx8VHt27dXb7/9tkpPT7eUq0j/ytqK3i+v9dOuXTullFJHjhxR//73v9XgwYNVs2bNlKurq+Xze8SIEWrJkiXlOtb13psBFRwcXK74X3755TLfx8syb9481a5dO+Xq6qoaNGighg8f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mzerKCUiIuLDDNM83HOK9ofPey+kY1JRSkRERKQVKyoqwrKsejsVx8TEkJ2dfdR7Nm3axOLFi3niiSeO+npt/82fLv2Ljo6ut0vykaqqqqiqqvIcG4ZBaGio5/umVPs8f9tWW3n7V97gv7krb+XtL/w5d1BRSkRERMSvlJWVMX36dG699VaioqKa9Nlz585lzpw5nuMuXbowdepUEhISmvR9jpSUlNRsz/Zlytv/+Gvuytu/+Gve4L+5qyglIiIi0opFRUVhmma9GUxOp7Pe7CmA/fv3k5eXx9SpUz3nalsIXHPNNUybNs1zX2FhIbGxsZ7rCgsLSUtLO2YsV1xxBaNGjfIc137qm5eXh8vlOsXMjs8wDJKSksjJyfGrFgjK27/yBv/NXXkrb3/RVnN3OBwn9aGUilIiIiIirZjD4SA9PZ3MzEwGDhwIuJuYZ2ZmHnXjmOTkZJ588sk652bNmkV5eTk33ngj8fHxBAQEEBMTww8//OApQpWWlrJ161YuvvjiY8YSGBhIYGDgUV9rroG2bdttahB/spS3//HX3JW3f/HXvMF/c1dRSkRERKSVGzVqFM8//zzp6elkZGSwcOFCKioqGDp0KADPPfcccXFxjBs3jqCgIDp37lzn/vDwcIA65y+99FLef/99OnToQGJiIrNmzSI2NtazG5+IiIhIY6koJSIiItLKDRo0iKKiImbPno3T6SQtLY1JkyZ5luHl5+efcgPVyy+/nIqKCl544QVKS0vp0aMHkyZNIigoqBkyEBEREX+kopSIiIhIGzBy5MijLtcDmDx58nHvnThxYr1zhmFw9dVXc/XVVzdFeCIiIiL1mN4OQERERERERERE/I+KUiIiIiIiIiIi0uJUlBIRERERERERkRanopSIiIiIiIiIiLQ4FaVERERERERERKTFqSglIiIiIiIiIiItTkUpERERERERERFpcSpKiYiIiIiIiIhIi3N4O4DWxOFovv9czflsX+evuStv/+KveYP/5q682462mFNL0xiq6Slv/+OvuStv/+KveUPby/1k8zFs27abORYREREREREREZE6tHzPy8rKyrj33nspKyvzdigtzl9zV97K21/4a+7K27/yFu/x1z9zytu/8gb/zV15K29/4c+5g4pSXmfbNllZWfjjhDV/zV15K29/4a+5K2//ylu8x1//zClv/8ob/Dd35a28/YU/5w4qSomIiIiIiIiIiBeoKCUiIiIiIiIiIi1ORSkvCwwM5KqrriIwMNDbobQ4f81deStvf+GvuStv/8pbvMdf/8wpb//KG/w3d+WtvP2FP+cO2n1PRERERERERES8QDOlRERERERERESkxakoJSIiIiIiIiIiLU5FKRERERERERERaXEObwfg7xYtWsS8efNwOp2kpqYyfvx4MjIyvB1Ws5k7dy7ff/89e/fuJSgoiNNOO43rr7+e5ORkb4fWoj744APefvttLr30Um688UZvh9PsCgoKeOutt1izZg0VFRUkJSVx++2307VrV2+H1mwsy2L27Nn873//w+l0EhcXxwUXXMCVV16JYRjeDq/JbNiwgf/+979kZWVx8OBB7rrrLgYOHOh53bZtZs+ezeeff05JSQk9evTglltuoUOHDl6MumkcL3eXy8WsWbNYvXo1ubm5hIWF0bt3b8aNG0dcXJyXI2+cE/2eH+nFF1/ks88+44YbbuCyyy5r4UilLfO38RNoDFXLn8ZQGj+13fET+O8YSuMnjZ9+SjOlvGjZsmXMmDGDq666iqlTp5KamsqUKVMoLCz0dmjNZsOGDfz85z9nypQpPPDAA1RXV/O3v/2N8vJyb4fWYrZu3cqnn35Kamqqt0NpEcXFxTz44IM4HA4mTZrE008/zW9+8xvCw8O9HVqz+uCDD/j000+5+eabefrpp7nuuuv473//y0cffeTt0JpURUUFaWlp3HzzzUd9/cMPP+Sjjz5iwoQJPPbYYwQHBzNlyhQqKytbONKmd7zcKysrycrK4sorr2Tq1KnceeedZGdn88QTT3gh0qZ1ot/zWt9//z1btmwhNja2hSITf+GP4yfQGAr8awyl8VPbHj+B/46hNH7S+OmnNFPKi+bPn8+IESMYNmwYABMmTGDVqlUsWbKEMWPGeDe4ZvKXv/ylzvHEiRO55ZZb2L59O7169fJSVC2nvLyc6dOnc+utt/L+++97O5wW8eGHH9KuXTtuv/12z7nExEQvRtQyNm/eTP/+/TnrrLMAd85ff/01W7du9XJkTatfv37069fvqK/Zts3ChQv55S9/yYABAwC44447mDBhAsuXL2fw4MEtGWqTO17uYWFhPPjgg3XOjR8/nkmTJpGfn098fHxLhNgsjpd3rYKCAl599VX+8pe/8Pjjj7dQZOIv/HH8BBpD+dsYSuOntj1+Av8dQ2n8dGz+On7STCkvcblcbN++nd69e3vOmaZJ79692bx5sxcja1mlpaUAREREeDmSlvHyyy/Tr18/+vTp4+1QWsyKFStIT0/nqaee4pZbbuGee+7hs88+83ZYze60004jMzOT7OxsAHbs2MGPP/54wn+M2pLc3FycTmedP+9hYWFkZGT41d9ztUpLSzEMg7CwMG+H0qwsy2L69OmMHj2aTp06eTscaWM0fjpMY6i2TeMn/x0/gcZQR9L4qe3TTCkvKSoqwrIsYmJi6pyPiYnx/CXc1lmWxeuvv0737t3p3Lmzt8NpdkuXLiUrK4u///3v3g6lReXm5vLpp59y2WWXccUVV7Bt2zZee+01HA4HQ4cO9XZ4zWbMmDGUlZXxpz/9CdM0sSyLa665hvPPP9/bobUYp9MJQHR0dJ3z0dHRntf8RWVlJTNnzmTw4MFtflD14YcfEhAQwCWXXOLtUKQN0vjJTWOotk/jJ/8dP4HGULU0fvIPKkqJ17zyyivs3r2bRx991NuhNLv8/Hxef/11HnjgAYKCgrwdTouyLIuuXbsybtw4ALp06cKuXbv49NNP2/Sg6ptvvuHrr7/mD3/4A506dWLHjh28/vrrxMbGtum8pT6Xy8XTTz8NwC233OLlaJrX9u3bWbhwIVOnTm1zDWlFfInGUG2fxk8aP/k7jZ/8h4pSXhIVFYVpmvUq3U6ns96nf23RK6+8wqpVq3jkkUdo166dt8Npdtu3b6ewsJB7773Xc86yLDZu3MiiRYt4++23Mc22uZo2NjaWlJSUOudSUlL47rvvvBRRy3jrrbe4/PLLPWv+O3fuTF5eHh988IHfDKpq/y4rLCys06yxsLCQtLQ07wTVwmoHVPn5+Tz00ENt/lO+jRs3UlRUVKcHimVZzJgxg4ULF/L88897MTppC/x9/AQaQ4F/jKE0fvLf8RNoDKXxk3+Nn1SU8hKHw0F6ejqZmZmerSAtyyIzM5ORI0d6ObrmY9s2r776Kt9//z2TJ0/2i4aNAL179+bJJ5+sc+7f//43ycnJXH755W1yMFWre/fu9ZZUZGdnk5CQ4KWIWkZFRUW931fTNLFt20sRtbzExERiYmL44YcfPAOo0tJStm7dysUXX+zd4FpA7YAqJyeHhx9+mMjISG+H1OyGDBlSp9cPwJQpUxgyZIinKbVIY/jr+Ak0hjqSP4yhNH46zN/GT+DfYyiNn9z8afykopQXjRo1iueff5709HQyMjJYuHAhFRUVbfpTgFdeeYWvv/6ae+65h9DQUM8nnWFhYW16SnZoaGi9ng/BwcFERka2+V4Ql112GQ8++CDvv/8+gwYNYuvWrXz++ef89re/9XZozerss8/m/fffJz4+npSUFHbs2MH8+fPb3D8s5eXl5OTkeI5zc3PZsWMHERERxMfHc+mll/L+++/ToUMHEhMTmTVrFrGxsZ6dZFqz4+UeExPDU089RVZWFvfeey+WZXn+vouIiMDhaL3//J7o9/yng0eHw0FMTAzJycktHaq0Uf44fgKNoY7kD2MojZ/a9vgJ/HcMpfGTm8ZPhxm2v5WdfcyiRYv473//i9PpJC0tjZtuuolu3bp5O6xmM3bs2KOev/3229v8YPKnJk+eTFpaGjfeeKO3Q2l2K1eu5O233yYnJ4fExEQuu+wyLrzwQm+H1azKysp49913+f777yksLCQuLo7Bgwdz1VVXtep/UH9q/fr1PPLII/XOX3DBBUycOBHbtpk9ezafffYZpaWl9OjRg5tvvrlN/AN7vNx/9atfcccddxz1vocffpjTTz+9ucNrNif6Pf+piRMncumll3LZZZe1RHjiJ/xt/AQaQx3JX8ZQGj+13fET+O8YSuOnujR+UlFKRERERERERES8oG0uwhYREREREREREZ+mopSIiIiIiIiIiLQ4FaVERERERERERKTFqSglIiIiIiIiIiItTkUpERERERERERFpcSpKiYiIiIiIiIhIi1NRSkREREREREREWpyKUiIiIiIiIiIi0uJUlBIRaWZffPEFY8eOZdu2bd4ORURERKTV0BhKpO1zeDsAEZGm8MUXX/Cvf/3rmK//7W9/47TTTmvBiERERER8n8ZQIuJNKkqJSJsyduxYEhMT651PSkryQjQiIiIirYPGUCLiDSpKiUib0q9fP7p27ertMERERERaFY2hRMQbVJQSEb+Rm5vLHXfcwfXXX49pmixcuJDCwkIyMjK4+eab6dy5c53rMzMzmT17NllZWQQEBNCrVy/GjRtHSkpKnesKCgp49913WbNmDYcOHSI2Npa+ffty00034XAc/mu2qqqKN954g6+++orKykr69OnDrbfeSlRUVIvkLyIiItIQGkOJSHNRo3MRaVNKS0spKiqq83Xo0KE613z11Vd89NFH/PznP+eKK65g9+7dPProozidTs8169atY8qUKRQWFvKrX/2KUaNG8eOPP/Lggw+Sm5vrua6goID777+fZcuWcd5553HTTTcxZMgQNmzYQEVFRZ33fe2119i5cye/+tWvuOiii1i5ciWvvPJKs/73EBERETkZGkOJiDdoppSItCl//etf650LDAxk5syZnuOcnByeffZZ4uLiAOjbty+TJk3iww8/5IYbbgDgrbfeIiIigilTphAREQHAgAEDuOeee5g9ezZ33HEHAG+//TZOp5PHHnuszpT3q6++Gtu268QRERHBAw88gGEYANi2zUcffURpaSlhYWFN+F9BRERE5NRoDCUi3qCilIi0KTfffDMdOnSoc840604KHTBggGcwBZCRkUG3bt1YvXo1N9xwAwcPHmTHjh2MHj3aM5gCSE1NpU+fPqxevRoAy7JYvnw5Z5999lF7MNQOnGpdeOGFdc717NmTBQsWkJeXR2pqasOTFhEREWkkjaFExBtUlBKRNiUjI+OETTp/OuCqPffNN98AkJeXB0BycnK96zp27MjatWspLy+nvLycsrKyen0UjiU+Pr7OcXh4OAAlJSUndb+IiIhIc9EYSkS8QT2lRERayE8/baz10ynqIiIiInKYxlAibZdmSomI39m3b99RzyUkJAB4fs3Ozq53XXZ2NpGRkYSEhBAUFERoaCi7du1q3oBFREREfIDGUCLS1DRTSkT8zvLlyykoKPAcb926lS1bttC3b18AYmNjSUtL48svv6wzLXzXrl2sXbuWfv36Ae5P7QYMGMDKlSvZtm1bvffRp3ciIiLSlmgMJSJNTTOlRKRNWb16NXv37q13vnv37p4GmUlJSTz44INcfPHFVFVVsXDhQiIjI7n88ss9119//fX8/e9/54EHHmDYsGFUVlayaNEiwsLCGDt2rOe6cePGsW7dOiZPnsyIESNISUnh4MGDfPvttzz66KOengciIiIivkxjKBHxBhWlRKRNmT179lHP33777fTq1QuAIUOGYJomCxYsoKioiIyMDMaPH09sbKzn+j59+jBp0iRmz57N7NmzCQgIoFevXlx33XUkJiZ6rouLi+Oxxx5j1qxZfP3115SVlREXF0ffvn0JDg5u3mRFREREmojGUCLiDYatuZEi4idyc3O54447uP766xk9erS3wxERERFpFTSGEpHmop5SIiIiIiIiIiLS4lSUEhERERERERGRFqeilIiIiIiIiIiItDj1lBIRERERERERkRanmVIiIiIiIiIiItLiVJQSEREREREREZEWp6KUiIiIiIiIiIi0OBWlRERERERERESkxakoJSIiIiIiIiIiLU5FKRERERERERERaXEqSomIiIiIiIiISItTUUpERERERERERFqcilIiIiIiIiIiItLi/j/LWrFRl0ZdewAAAABJRU5ErkJggg==\n"},"metadata":{}}],"source":["# Entraîner le modèle LSTM avec GloVe 300d\n","model_lstm_glove, history_lstm_glove, metrics_lstm_glove, run_id_lstm_glove = train_glove_lstm_model(epochs=50)"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Qq5sL0HcNwMy"},"outputs":[],"source":["# Charger le modèle pour la prédiction\n","lstm_glove_model_pack = load_complete_model(\"LSTM\", \"GloVe-300d-Fige\")"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Kc95Dyz8NwMy","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1751830703470,"user_tz":-120,"elapsed":2246,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}},"outputId":"9fac4c06-5630-4f50-bba5-f41005c5d833"},"outputs":[{"output_type":"stream","name":"stdout","text":["\n","Test de prédiction avec le modèle GloVe:\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 2s/step\n","{'sentiment': 'Positif', 'confidence': 0.9921875, 'raw_score': 0.9921875}\n"]}],"source":["# Tester le modèle sur quelques exemples\n","print(\"\\nTest de prédiction avec le modèle GloVe:\")\n","result = predict_sentiment(\"I love flying with this airline, the service is amazing!\", lstm_glove_model_pack)\n","print(result)"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"gAhcxPUoNwMy","colab":{"base_uri":"https://localhost:8080/","height":1000},"executionInfo":{"status":"ok","timestamp":1751830705513,"user_tz":-120,"elapsed":2042,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}},"outputId":"b49cfcf6-a4e7-4069-e497-0b789f6f7865"},"outputs":[{"output_type":"stream","name":"stdout","text":["\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 31ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 35ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 29ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 28ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 29ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 29ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 30ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 29ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 34ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 31ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 32ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 31ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 29ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 28ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 40ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 47ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 45ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 48ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 47ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 46ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 43ms/step\n","\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 43ms/step\n","\n","Test du modèle sur les exemples:\n","==================================================\n","Résumé: 22 tweets analysés\n","Tweets positifs: 13 (59.1%)\n","Tweets négatifs: 9 (40.9%)\n","\n","Aperçu des prédictions GloVe :\n"]},{"output_type":"execute_result","data":{"text/plain":[" Tweet Sentiment Emoji \\\n","0 I absolutely love flying with @AirParadis! The... Positif 💚 \n","1 Just landed after a wonderful flight... The cr... Positif 💚 \n","2 OMG! You really have to try @AirParadis. Best.... Positif 💚 \n","3 We had a very pleasant experience with our fli... Positif 💚 \n","4 My first time flying business class and I'm ab... Positif 💚 \n","5 I hate how @AirParadis always delays their fli... Négatif ❌ \n","6 The worst flight experience of my life? Defini... Négatif ❌ \n","7 Really @AirParadis??? Flight cancelled and no ... Négatif ❌ \n","8 Our baggage was lost and nobody at @AirParadis... Négatif ❌ \n","9 Food was terrible, seats were uncomfortable, a... Négatif ❌ \n","10 The flight was good but the food wasn't really... Positif 💚 \n","11 IDK what to think about my @AirParadis experie... Négatif ❌ \n","12 My husband loved the flight but I didn't... To... Positif 💚 \n","13 TBH, @AirParadis has improved their service si... Négatif ❌ \n","14 We were so excited for our trip but then our f... Positif 💚 \n","15 This is a tweet with many!!! exclamation!!! ma... Négatif ❌ \n","16 How does the model handle multiple??? question... Négatif ❌ \n","17 Testing ellipses... many... many... ellipses..... Positif 💚 \n","18 #many #hashtags #in #one #tweet #to #see #how ... Positif 💚 \n","19 @mention1 @mention2 @mention3 @mention4 @menti... Positif 💚 \n","20 Multiple URLs in one tweet: http://example1.co... Positif 💚 \n","21 Let's try all emoticons :) :( :D ;) :-) :-( :-... Positif 💚 \n","\n"," Score de confiance Score brut Index \n","0 0.995117 0.995117 1 \n","1 0.990234 0.990234 2 \n","2 0.939453 0.939453 3 \n","3 0.963379 0.963379 4 \n","4 0.649902 0.649902 5 \n","5 0.980865 0.019135 6 \n","6 0.975449 0.024551 7 \n","7 0.978058 0.021942 8 \n","8 0.933167 0.066833 9 \n","9 0.896606 0.103394 10 \n","10 0.651855 0.651855 11 \n","11 0.875000 0.125000 12 \n","12 0.576172 0.576172 13 \n","13 0.681396 0.318604 14 \n","14 0.731445 0.731445 15 \n","15 0.841064 0.158936 16 \n","16 0.666748 0.333252 17 \n","17 0.689941 0.689941 18 \n","18 0.819336 0.819336 19 \n","19 0.907227 0.907227 20 \n","20 0.984375 0.984375 21 \n","21 0.929199 0.929199 22 "],"text/html":["\n","
\n","
\n","\n","
\n"," \n","
\n","
\n","
Tweet
\n","
Sentiment
\n","
Emoji
\n","
Score de confiance
\n","
Score brut
\n","
Index
\n","
\n"," \n"," \n","
\n","
0
\n","
I absolutely love flying with @AirParadis! The...
\n","
Positif
\n","
💚
\n","
0.995117
\n","
0.995117
\n","
1
\n","
\n","
\n","
1
\n","
Just landed after a wonderful flight... The cr...
\n","
Positif
\n","
💚
\n","
0.990234
\n","
0.990234
\n","
2
\n","
\n","
\n","
2
\n","
OMG! You really have to try @AirParadis. Best....
\n","
Positif
\n","
💚
\n","
0.939453
\n","
0.939453
\n","
3
\n","
\n","
\n","
3
\n","
We had a very pleasant experience with our fli...
\n","
Positif
\n","
💚
\n","
0.963379
\n","
0.963379
\n","
4
\n","
\n","
\n","
4
\n","
My first time flying business class and I'm ab...
\n","
Positif
\n","
💚
\n","
0.649902
\n","
0.649902
\n","
5
\n","
\n","
\n","
5
\n","
I hate how @AirParadis always delays their fli...
\n","
Négatif
\n","
❌
\n","
0.980865
\n","
0.019135
\n","
6
\n","
\n","
\n","
6
\n","
The worst flight experience of my life? Defini...
\n","
Négatif
\n","
❌
\n","
0.975449
\n","
0.024551
\n","
7
\n","
\n","
\n","
7
\n","
Really @AirParadis??? Flight cancelled and no ...
\n","
Négatif
\n","
❌
\n","
0.978058
\n","
0.021942
\n","
8
\n","
\n","
\n","
8
\n","
Our baggage was lost and nobody at @AirParadis...
\n","
Négatif
\n","
❌
\n","
0.933167
\n","
0.066833
\n","
9
\n","
\n","
\n","
9
\n","
Food was terrible, seats were uncomfortable, a...
\n","
Négatif
\n","
❌
\n","
0.896606
\n","
0.103394
\n","
10
\n","
\n","
\n","
10
\n","
The flight was good but the food wasn't really...
\n","
Positif
\n","
💚
\n","
0.651855
\n","
0.651855
\n","
11
\n","
\n","
\n","
11
\n","
IDK what to think about my @AirParadis experie...
\n","
Négatif
\n","
❌
\n","
0.875000
\n","
0.125000
\n","
12
\n","
\n","
\n","
12
\n","
My husband loved the flight but I didn't... To...
\n","
Positif
\n","
💚
\n","
0.576172
\n","
0.576172
\n","
13
\n","
\n","
\n","
13
\n","
TBH, @AirParadis has improved their service si...
\n","
Négatif
\n","
❌
\n","
0.681396
\n","
0.318604
\n","
14
\n","
\n","
\n","
14
\n","
We were so excited for our trip but then our f...
\n","
Positif
\n","
💚
\n","
0.731445
\n","
0.731445
\n","
15
\n","
\n","
\n","
15
\n","
This is a tweet with many!!! exclamation!!! ma...
\n","
Négatif
\n","
❌
\n","
0.841064
\n","
0.158936
\n","
16
\n","
\n","
\n","
16
\n","
How does the model handle multiple??? question...
\n","
Négatif
\n","
❌
\n","
0.666748
\n","
0.333252
\n","
17
\n","
\n","
\n","
17
\n","
Testing ellipses... many... many... ellipses.....
\n","
Positif
\n","
💚
\n","
0.689941
\n","
0.689941
\n","
18
\n","
\n","
\n","
18
\n","
#many #hashtags #in #one #tweet #to #see #how ...
\n","
Positif
\n","
💚
\n","
0.819336
\n","
0.819336
\n","
19
\n","
\n","
\n","
19
\n","
@mention1 @mention2 @mention3 @mention4 @menti...
\n","
Positif
\n","
💚
\n","
0.907227
\n","
0.907227
\n","
20
\n","
\n","
\n","
20
\n","
Multiple URLs in one tweet: http://example1.co...
\n","
Positif
\n","
💚
\n","
0.984375
\n","
0.984375
\n","
21
\n","
\n","
\n","
21
\n","
Let's try all emoticons :) :( :D ;) :-) :-( :-...
\n","
Positif
\n","
💚
\n","
0.929199
\n","
0.929199
\n","
22
\n","
\n"," \n","
\n","
\n","
\n","\n","
\n"," \n","\n"," \n","\n"," \n","
\n","\n","\n","
\n"," \n","\n","\n","\n"," \n","
\n","\n","
\n"," \n"," \n"," \n","
\n","\n","
\n","
\n"],"application/vnd.google.colaboratory.intrinsic+json":{"type":"dataframe","variable_name":"df_results_glove","summary":"{\n \"name\": \"df_results_glove\",\n \"rows\": 22,\n \"fields\": [\n {\n \"column\": \"Tweet\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 22,\n \"samples\": [\n \"I absolutely love flying with @AirParadis! Their service is amazing and their staff is so helpful :) #bestairline #travel\",\n \"TBH, @AirParadis has improved their service since last year! Not perfect yet, but they're trying... #progress\",\n \"Our baggage was lost and nobody at @AirParadis seems to care! Don't they understand that we can't enjoy our vacation without our stuff??? http://badservice.com/complaint :-(\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Sentiment\",\n \"properties\": {\n \"dtype\": \"category\",\n \"num_unique_values\": 2,\n \"samples\": [\n \"N\\u00e9gatif\",\n \"Positif\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Emoji\",\n \"properties\": {\n \"dtype\": \"category\",\n \"num_unique_values\": 2,\n \"samples\": [\n \"\\u274c\",\n \"\\ud83d\\udc9a\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Score de confiance\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.13888291998594515,\n \"min\": 0.576171875,\n \"max\": 0.9951171875,\n \"num_unique_values\": 22,\n \"samples\": [\n 0.9951171875,\n 0.681396484375\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Score brut\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.3794701732781929,\n \"min\": 0.019134521484375,\n \"max\": 0.9951171875,\n \"num_unique_values\": 22,\n \"samples\": [\n 0.9951171875,\n 0.318603515625\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Index\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 6,\n \"min\": 1,\n \"max\": 22,\n \"num_unique_values\": 22,\n \"samples\": [\n 1,\n 14\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}"}},"metadata":{},"execution_count":43}],"source":["# Obtenir le DataFrame des prédictions pour le modèle GloVe\n","df_results_glove = test_model_on_examples(lstm_glove_model_pack, test_tweets_improved)\n","\n","# Sauvegarder les résultats dans un fichier CSV\n","df_results_glove.to_csv(\"content/advanced-model/LSTM_GloVe-300d-Fige/predictions_results.csv\", index=False)\n","\n","# Afficher un aperçu des prédictions\n","print(\"\\nAperçu des prédictions GloVe :\")\n","df_results_glove"]},{"cell_type":"markdown","source":["# Enregistrement du meilleur modèle\n","Dans le Model Registry de MLFlow, qui sera utilisé et mis à jour comme source pour l'API."],"metadata":{"id":"8D9ukAB3Xee4"}},{"cell_type":"code","source":["# Comparer les métriques de précision sur l'ensemble de test\n","precision_word2vec = metrics_lstm_word2vec.get('precision', 0)\n","precision_glove = metrics_lstm_glove.get('precision', 0)\n","\n","print(f\"Précision (Test) Word2Vec + LSTM: {precision_word2vec:.4f}\")\n","print(f\"Précision (Test) GloVe 300d + LSTM: {precision_glove:.4f}\")\n","\n","best_model_run_id = None\n","best_model_name = None\n","best_vectorizer_name = None\n","best_precision = 0\n","\n","# Déterminer le modèle avec la meilleure précision\n","if precision_word2vec >= precision_glove:\n"," best_model_run_id = run_id_lstm_word2vec\n"," best_model_name = \"LSTM\"\n"," best_vectorizer_name = \"Word2Vec-Fige\"\n"," best_precision = precision_word2vec\n","else:\n"," best_model_run_id = run_id_lstm_glove\n"," best_model_name = \"LSTM\"\n"," best_vectorizer_name = \"GloVe-300d-Fige\"\n"," best_precision = precision_glove\n","\n","\n","print(f\"\\nLe modèle {best_model_name} + {best_vectorizer_name} a la meilleure précision ({best_precision:.4f}).\")\n","\n","# Construire l'URI du modèle dans le run MLflow\n","logged_model_uri = f\"runs:/{best_model_run_id}/model_{best_model_name}_{best_vectorizer_name}\"\n","print(f\"\\nChargement du meilleur modèle depuis MLflow URI: {logged_model_uri}\")\n","\n","model_registry_name = \"SentimentAnalysisLSTM\"\n","client = mlflow.tracking.MlflowClient()\n","\n","try:\n"," # Charger le modèle Keras depuis MLflow (pas strictement nécessaire pour l'enregistrement, mais utile pour validation)\n"," # best_keras_model = mlflow.keras.load_model(logged_model_uri)\n"," # print(\"Modèle Keras chargé avec succès.\")\n","\n"," print(f\"Enregistrement du meilleur modèle dans le Model Registry sous le nom '{model_registry_name}'...\")\n","\n"," # Créer une nouvelle version dans le Model Registry\n"," model_version = mlflow.register_model(\n"," model_uri=logged_model_uri,\n"," name=model_registry_name\n"," )\n"," print(f\"Modèle enregistré dans le Model Registry sous la version {model_version.version}.\")\n","\n"," # Ajouter des tags au modèle enregistré\n"," client.set_model_version_tag(\n"," name=model_registry_name,\n"," version=model_version.version,\n"," key=\"embedding_type\",\n"," value=best_vectorizer_name\n"," )\n"," client.set_model_version_tag(\n"," name=model_registry_name,\n"," version=model_version.version,\n"," key=\"test_precision\",\n"," value=str(best_precision)\n"," )\n"," client.set_model_version_tag(\n"," name=model_registry_name,\n"," version=model_version.version,\n"," key=\"source_run_id\",\n"," value=best_model_run_id\n"," )\n","\n"," print(f\"Tags ajoutés à la version {model_version.version}.\")\n","\n"," # --- Logique de comparaison et de transition des stages ---\n","\n"," # Récupérer la version du modèle actuellement en production\n"," production_version = None\n"," try:\n"," for mv in client.search_model_versions(f\"name='{model_registry_name}'\"):\n"," if mv.current_stage == \"Production\":\n"," production_version = mv\n"," break\n"," except Exception as e:\n"," print(f\"Erreur lors de la recherche de la version en production : {e}\")\n","\n","\n"," if production_version:\n"," print(f\"\\nVersion actuelle en production: Version {production_version.version}\")\n"," # Récupérer la précision de la version en production (stockée dans les tags)\n"," production_precision_str = production_version.tags.get(\"test_precision\", \"0.0\")\n"," try:\n"," production_precision = float(production_precision_str)\n"," print(f\"Précision (Test) de la version en production: {production_precision:.4f}\")\n","\n"," # Comparer les précisions\n"," if best_precision > production_precision:\n"," print(f\"\\nLa nouvelle version ({model_version.version}) est meilleure que la version en production ({production_version.version}).\")\n"," print(\"Transition de la nouvelle version vers 'Production' et de l'ancienne version vers 'Staging'...\")\n","\n"," # Mettre la nouvelle version en production\n"," client.transition_model_version_stage(\n"," name=model_registry_name,\n"," version=model_version.version,\n"," stage=\"Production\",\n"," archive_existing_versions=True # Cela archive automatiquement l'ancienne version en production\n"," )\n"," print(f\"Version {model_version.version} mise en production.\")\n"," print(f\"Ancienne version {production_version.version} archivée.\")\n","\n"," else:\n"," print(f\"\\nLa nouvelle version ({model_version.version}) n'est pas meilleure que la version en production ({production_version.version}).\")\n"," print(\"Transition de la nouvelle version vers 'Staging'...\")\n"," # Mettre la nouvelle version en staging\n"," client.transition_model_version_stage(\n"," name=model_registry_name,\n"," version=model_version.version,\n"," stage=\"Staging\",\n"," archive_existing_versions=False # Ne pas archiver l'ancienne version en production\n"," )\n"," print(f\"Version {model_version.version} mise en staging.\")\n"," print(f\"La version {production_version.version} reste en production.\")\n","\n"," except ValueError:\n"," print(f\"Erreur: Impossible de convertir le tag 'test_precision' ({production_precision_str}) de la version en production en nombre flottant.\")\n"," print(f\"La nouvelle version {model_version.version} sera mise en 'Staging' par défaut.\")\n"," # Mettre la nouvelle version en staging si la précision de l'ancienne ne peut pas être lue\n"," client.transition_model_version_stage(\n"," name=model_registry_name,\n"," version=model_version.version,\n"," stage=\"Staging\",\n"," archive_existing_versions=False\n"," )\n","\n"," else:\n"," print(\"\\nAucune version en production trouvée. La nouvelle version sera mise en production.\")\n"," # Si aucune version n'est en production, mettre directement la nouvelle version en production\n"," client.transition_model_version_stage(\n"," name=model_registry_name,\n"," version=model_version.version,\n"," stage=\"Production\",\n"," archive_existing_versions=False\n"," )\n"," print(f\"Version {model_version.version} mise en production.\")\n","\n"," print(f\"\\nGestion des stages du modèle '{model_registry_name}' terminée.\")\n","\n","except Exception as e:\n"," print(f\"Erreur générale lors du traitement MLflow : {e}\")\n"," print(f\"Vérifiez que le run_id '{best_model_run_id}' est valide et que l'artefact existe bien.\")"],"metadata":{"id":"7Pf-LJdNOCHe","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1751830706459,"user_tz":-120,"elapsed":945,"user":{"displayName":"Grégoire","userId":"01249298206117462766"}},"outputId":"f9bdde12-3102-454d-c44c-60a35a0d60a0"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Précision (Test) Word2Vec + LSTM: 0.7970\n","Précision (Test) GloVe 300d + LSTM: 0.7915\n","\n","Le modèle LSTM + Word2Vec-Fige a la meilleure précision (0.7970).\n","\n","Chargement du meilleur modèle depuis MLflow URI: runs:/1de54538ee73443687db131fcc86d922/model_LSTM_Word2Vec-Fige\n","Enregistrement du meilleur modèle dans le Model Registry sous le nom 'SentimentAnalysisLSTM'...\n"]},{"output_type":"stream","name":"stderr","text":["Registered model 'SentimentAnalysisLSTM' already exists. Creating a new version of this model...\n","2025/07/06 19:38:25 WARNING mlflow.tracking._model_registry.fluent: Run with id 1de54538ee73443687db131fcc86d922 has no artifacts at artifact path 'model_LSTM_Word2Vec-Fige', registering model based on models:/m-b4c7c871087e4a2587f21367961f6d04 instead\n","2025/07/06 19:38:25 INFO mlflow.store.model_registry.abstract_store: Waiting up to 300 seconds for model version to finish creation. Model name: SentimentAnalysisLSTM, version 12\n","Created version '12' of model 'SentimentAnalysisLSTM'.\n"]},{"output_type":"stream","name":"stdout","text":["Modèle enregistré dans le Model Registry sous la version 12.\n","Tags ajoutés à la version 12.\n","\n","Version actuelle en production: Version 11\n","Précision (Test) de la version en production: 0.7830\n","\n","La nouvelle version (12) est meilleure que la version en production (11).\n","Transition de la nouvelle version vers 'Production' et de l'ancienne version vers 'Staging'...\n","Version 12 mise en production.\n","Ancienne version 11 archivée.\n","\n","Gestion des stages du modèle 'SentimentAnalysisLSTM' terminée.\n"]}]},{"cell_type":"markdown","source":["# Enregistrement de dépendances"],"metadata":{"id":"5iEc-YxAt3BU"}},{"cell_type":"code","source":["!pip freeze > requirements_modele_avance.txt"],"metadata":{"id":"jIw_YhFztVF2"},"execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.12"},"colab":{"provenance":[],"gpuType":"T4"},"accelerator":"GPU"},"nbformat":4,"nbformat_minor":0}