3364 lines
302 KiB
Text
3364 lines
302 KiB
Text
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"id": "y3x3_GfST76Z"
|
||
},
|
||
"source": [
|
||
"# Partie 4 : Analyse de Sentiment de Tweets avec BERT\n",
|
||
"\n",
|
||
"Dans ce notebook, nous explorons l'analyse de sentiment de tweets en utilisant **BERT (Bidirectional Encoder Representations from Transformers)**, un modèle de deep learning à la pointe de la technologie pour le traitement du langage naturel. Le dataset **Sentiment140** contient 1,6 million de tweets étiquetés (positifs ou négatifs), ce qui en fait une excellente ressource pour entraîner notre modèle. Contrairement aux approches traditionnelles qui nécessitent une ingénierie de caractéristiques complexe, **BERT comprend le contexte bidirectionnel des mots**, ce qui est particulièrement utile pour capturer les subtilités linguistiques des tweets comme l'ironie, les abréviations et les expressions idiomatiques propres aux réseaux sociaux.\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 (7, 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": "kW-8vumuT76b"
|
||
},
|
||
"source": [
|
||
"## Importation des bibliothèques"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"colab": {
|
||
"base_uri": "https://localhost:8080/"
|
||
},
|
||
"executionInfo": {
|
||
"elapsed": 18367,
|
||
"status": "ok",
|
||
"timestamp": 1752351535443,
|
||
"user": {
|
||
"displayName": "Grégoire",
|
||
"userId": "01249298206117462766"
|
||
},
|
||
"user_tz": -120
|
||
},
|
||
"id": "Xplx_nQRg0rF",
|
||
"outputId": "aa1a2afc-5393-4e50-de54-a2cd7e0acc05"
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Mounted at /content/drive\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"['content',\n",
|
||
" 'requirements_analyse_exploratoire.txt',\n",
|
||
" 'p07_01-notebook-analyse-exploratoire.ipynb',\n",
|
||
" 'requirements_bert.txt',\n",
|
||
" 'requirements_modele_simple.txt',\n",
|
||
" 'p07_02-notebook-modele-simple.ipynb',\n",
|
||
" 'requirements_modele_avance.txt',\n",
|
||
" 'p07_03-notebook-modele-avance.ipynb',\n",
|
||
" 'notebook-connexion-mlflow.ipynb',\n",
|
||
" 'p07_04-notebook-modele-bert.ipynb']"
|
||
]
|
||
},
|
||
"execution_count": 1,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"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()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"colab": {
|
||
"base_uri": "https://localhost:8080/"
|
||
},
|
||
"executionInfo": {
|
||
"elapsed": 32608,
|
||
"status": "ok",
|
||
"timestamp": 1752351568062,
|
||
"user": {
|
||
"displayName": "Grégoire",
|
||
"userId": "01249298206117462766"
|
||
},
|
||
"user_tz": -120
|
||
},
|
||
"id": "tXTBgiq7U8gK",
|
||
"outputId": "97fd036f-0f54-494b-8e5d-3a261d029091"
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m24.7/24.7 MB\u001b[0m \u001b[31m47.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.9/1.9 MB\u001b[0m \u001b[31m61.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m139.9/139.9 kB\u001b[0m \u001b[31m11.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m247.0/247.0 kB\u001b[0m \u001b[31m18.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m13.8/13.8 MB\u001b[0m \u001b[31m85.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m147.8/147.8 kB\u001b[0m \u001b[31m8.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m114.9/114.9 kB\u001b[0m \u001b[31m11.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m85.0/85.0 kB\u001b[0m \u001b[31m7.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m85.2/85.2 kB\u001b[0m \u001b[31m8.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m741.4/741.4 kB\u001b[0m \u001b[31m38.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m203.4/203.4 kB\u001b[0m \u001b[31m13.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m65.6/65.6 kB\u001b[0m \u001b[31m6.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m119.4/119.4 kB\u001b[0m \u001b[31m10.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m201.6/201.6 kB\u001b[0m \u001b[31m17.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||
"\u001b[?25h"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"!pip install mlflow boto3 dotenv --quiet"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"colab": {
|
||
"base_uri": "https://localhost:8080/"
|
||
},
|
||
"collapsed": true,
|
||
"executionInfo": {
|
||
"elapsed": 6287,
|
||
"status": "ok",
|
||
"timestamp": 1752351574355,
|
||
"user": {
|
||
"displayName": "Grégoire",
|
||
"userId": "01249298206117462766"
|
||
},
|
||
"user_tz": -120
|
||
},
|
||
"id": "W50jr7rUT76d",
|
||
"outputId": "437c63ff-9e8f-4251-a053-0216012499ba"
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"PyTorch version: 2.6.0+cu124\n",
|
||
"CUDA disponible: True\n",
|
||
"Appareil CUDA: Tesla T4\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"import torch\n",
|
||
"print(f\"PyTorch version: {torch.__version__}\")\n",
|
||
"print(f\"CUDA disponible: {torch.cuda.is_available()}\")\n",
|
||
"if torch.cuda.is_available():\n",
|
||
" print(f\"Appareil CUDA: {torch.cuda.get_device_name(0)}\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"id": "MMB0gwbBT76d"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"import os\n",
|
||
"import pickle\n",
|
||
"import subprocess\n",
|
||
"import re\n",
|
||
"import pandas as pd\n",
|
||
"import numpy as np\n",
|
||
"import torch\n",
|
||
"from torch.utils.data import Dataset, DataLoader\n",
|
||
"from torch.amp import GradScaler\n",
|
||
"from torch.optim import AdamW\n",
|
||
"from transformers import DistilBertTokenizer, DistilBertForSequenceClassification, get_scheduler\n",
|
||
"from sklearn.model_selection import train_test_split\n",
|
||
"from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score\n",
|
||
"from sklearn.metrics import confusion_matrix, classification_report, roc_curve, auc\n",
|
||
"import matplotlib.pyplot as plt\n",
|
||
"import seaborn as sns\n",
|
||
"from tqdm import tqdm\n",
|
||
"import html\n",
|
||
"import pickle\n",
|
||
"import zipfile\n",
|
||
"import requests\n",
|
||
"import json"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"colab": {
|
||
"base_uri": "https://localhost:8080/"
|
||
},
|
||
"executionInfo": {
|
||
"elapsed": 2633,
|
||
"status": "ok",
|
||
"timestamp": 1752351604138,
|
||
"user": {
|
||
"displayName": "Grégoire",
|
||
"userId": "01249298206117462766"
|
||
},
|
||
"user_tz": -120
|
||
},
|
||
"id": "OhgBsQDCUq4A",
|
||
"outputId": "f63ccc04-79c1-40fc-8c92-5ed975f67336"
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"MLflow Tracking URI: https://mlflow.greg-madman-nas.duckdns.org/\n",
|
||
"Identifiants AWS configurés\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"import mlflow\n",
|
||
"from mlflow.models.signature import infer_signature\n",
|
||
"from mlflow import MlflowClient\n",
|
||
"from mlflow.models.signature import ModelSignature\n",
|
||
"from mlflow.types import Schema, ColSpec, TensorSpec\n",
|
||
"from dotenv import load_dotenv\n",
|
||
"from google.colab import userdata\n",
|
||
"import mlflow.pytorch\n",
|
||
"\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\")\n",
|
||
"\n",
|
||
"# Créer l'expérience MLflow\n",
|
||
"mlflow.set_experiment(\"OC Projet 7\")\n",
|
||
"\n",
|
||
"#Création du dossier de sauvegarde du modèle\n",
|
||
"os.makedirs('content/bert-model/model', exist_ok=True)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"id": "SuNqSc3UT76d"
|
||
},
|
||
"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": {
|
||
"colab": {
|
||
"base_uri": "https://localhost:8080/"
|
||
},
|
||
"executionInfo": {
|
||
"elapsed": 26,
|
||
"status": "ok",
|
||
"timestamp": 1752351604172,
|
||
"user": {
|
||
"displayName": "Grégoire",
|
||
"userId": "01249298206117462766"
|
||
},
|
||
"user_tz": -120
|
||
},
|
||
"id": "Q5ACc3OUT76d",
|
||
"outputId": "940ac231-d2b1-4c8d-940c-3cc323079d56"
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"CPU times: user 60 µs, sys: 9 µs, total: 69 µs\n",
|
||
"Wall time: 259 µ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": "_D2V2EgHT76e"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# Définir le chemin vers le fichier CSV\n",
|
||
"csv_file_path = './content/data/training.1600000.processed.noemoticon.csv'"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"id": "Sv9nlaIq4BZo"
|
||
},
|
||
"source": [
|
||
"## 🧠📚 Entraînement spécifique de BERT\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",
|
||
" - BERT\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"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"id": "AFdxLghUT76e"
|
||
},
|
||
"source": [
|
||
"## Prétraitement des tweets"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"id": "NmOIhsWET76e"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# PRÉTRAITEMENT DES TWEETS\n",
|
||
"def preprocess_tweet_for_bert(tweet):\n",
|
||
" \"\"\"\n",
|
||
" Prétraite un tweet pour l'entraînement BERT en conservant la structure naturelle\n",
|
||
" du langage mais en normalisant certains éléments spécifiques aux réseaux sociaux.\n",
|
||
" \"\"\"\n",
|
||
" # Vérifier si le tweet est une chaîne de caractères\n",
|
||
" if not isinstance(tweet, str):\n",
|
||
" return \"\"\n",
|
||
"\n",
|
||
" # Remplacer les URLs par un token spécial\n",
|
||
" tweet = re.sub(r'https?://\\S+|www\\.\\S+', '[URL]', tweet)\n",
|
||
"\n",
|
||
" # Remplacer les mentions par un token spécial\n",
|
||
" tweet = re.sub(r'@\\w+', '[USER]', tweet)\n",
|
||
"\n",
|
||
" # Normaliser les hashtags (conserver le hashtag comme entité)\n",
|
||
" tweet = re.sub(r'#(\\w+)', r'#\\1', tweet)\n",
|
||
"\n",
|
||
" # Traiter le langage html\n",
|
||
" tweet = html.unescape(tweet)\n",
|
||
"\n",
|
||
" # Normaliser les espaces multiples\n",
|
||
" tweet = re.sub(r'\\s+', ' ', tweet)\n",
|
||
"\n",
|
||
" # Supprimer les caractères non imprimables et certains caractères spéciaux inutiles\n",
|
||
" tweet = re.sub(r'[^\\x20-\\x7E]', '', tweet)\n",
|
||
"\n",
|
||
" # Nettoyer les espaces en début et fin\n",
|
||
" tweet = tweet.strip()\n",
|
||
"\n",
|
||
" return tweet"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"id": "M6ViLmc7T76e"
|
||
},
|
||
"source": [
|
||
"## Préparations des données"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"id": "ap7LohJzT76e"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# PRÉPARATION DES DONNÉES\n",
|
||
"def prepare_data(df, sample_size=50000, random_state=42):\n",
|
||
" \"\"\"\n",
|
||
" Préparation des données pour l'entraînement BERT\n",
|
||
" \"\"\"\n",
|
||
" # Remappage des labels (0=négatif, 4=positif) vers (0=négatif, 1=positif)\n",
|
||
" df['target'] = df['target'].replace({0: 0, 4: 1})\n",
|
||
"\n",
|
||
" # Prétraitement des tweets\n",
|
||
" print(\"Prétraitement des tweets...\")\n",
|
||
" df['processed_text'] = df['text'].apply(preprocess_tweet_for_bert)\n",
|
||
"\n",
|
||
" # Sélection d'un échantillon pour l'entraînement.\n",
|
||
" # La distribution uniforme (50%/50%) des modalités ne posera pas problème pour le sous-échantillonnage.\n",
|
||
" sample_data = df.sample(n=sample_size, random_state=random_state)\n",
|
||
"\n",
|
||
" # Division train/val/test\n",
|
||
" train_val_texts, test_texts, train_val_labels, test_labels = train_test_split(\n",
|
||
" sample_data['processed_text'].values,\n",
|
||
" sample_data['target'].values,\n",
|
||
" test_size=0.2,\n",
|
||
" random_state=random_state\n",
|
||
" )\n",
|
||
"\n",
|
||
" train_texts, val_texts, train_labels, val_labels = train_test_split(\n",
|
||
" train_val_texts,\n",
|
||
" train_val_labels,\n",
|
||
" test_size=0.2,\n",
|
||
" random_state=random_state\n",
|
||
" )\n",
|
||
"\n",
|
||
" return {\n",
|
||
" 'train': {'texts': train_texts, 'labels': train_labels},\n",
|
||
" 'val': {'texts': val_texts, 'labels': val_labels},\n",
|
||
" 'test': {'texts': test_texts, 'labels': test_labels}\n",
|
||
" }"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"id": "lgWXn2SKT76e"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# CRÉATION D'UN DATASET PYTORCH\n",
|
||
"class TweetDataset(Dataset):\n",
|
||
" def __init__(self, texts, labels, tokenizer, max_length=128):\n",
|
||
" self.texts = texts\n",
|
||
" self.labels = labels\n",
|
||
" self.tokenizer = tokenizer\n",
|
||
" self.max_length = max_length\n",
|
||
"\n",
|
||
" def __len__(self):\n",
|
||
" return len(self.texts)\n",
|
||
"\n",
|
||
" def __getitem__(self, idx):\n",
|
||
" text = str(self.texts[idx])\n",
|
||
" label = self.labels[idx]\n",
|
||
"\n",
|
||
" # Tokenisation du texte\n",
|
||
" encoding = self.tokenizer(\n",
|
||
" text,\n",
|
||
" add_special_tokens=True,\n",
|
||
" max_length=self.max_length,\n",
|
||
" truncation=True,\n",
|
||
" padding='max_length',\n",
|
||
" return_tensors='pt'\n",
|
||
" )\n",
|
||
"\n",
|
||
" return {\n",
|
||
" 'input_ids': encoding['input_ids'].flatten(),\n",
|
||
" 'attention_mask': encoding['attention_mask'].flatten(),\n",
|
||
" 'label': torch.tensor(label, dtype=torch.long)\n",
|
||
" }"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"id": "P_S6MpCjT76f"
|
||
},
|
||
"source": [
|
||
"## Fonctions d'entraînement"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"id": "EsK_IQRlbu3C"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"import torch\n",
|
||
"from torch.cuda.amp import GradScaler\n",
|
||
"from sklearn.metrics import accuracy_score, precision_score, recall_score\n",
|
||
"from tqdm import tqdm\n",
|
||
"\n",
|
||
"def train_model(\n",
|
||
" model,\n",
|
||
" train_loader,\n",
|
||
" val_loader,\n",
|
||
" test_loader,\n",
|
||
" device,\n",
|
||
" epochs=20,\n",
|
||
" gradient_accumulation_steps=4,\n",
|
||
" patience=7,\n",
|
||
" lr=2e-5,\n",
|
||
" lr_factor=0.2,\n",
|
||
" min_lr=1e-6,\n",
|
||
"):\n",
|
||
" \"\"\"\n",
|
||
" Train a BERT model with gradient accumulation,\n",
|
||
" EarlyStopping on val_loss, and best model selection on val_precision.\n",
|
||
"\n",
|
||
" Args:\n",
|
||
" model: The BERT model to train.\n",
|
||
" train_loader: DataLoader for training data.\n",
|
||
" val_loader: DataLoader for validation data.\n",
|
||
" test_loader: DataLoader for test data.\n",
|
||
" device: 'cuda' or 'cpu' for training.\n",
|
||
" epochs: Maximum number of epochs to train.\n",
|
||
" gradient_accumulation_steps: Number of steps for gradient accumulation.\n",
|
||
" patience: Patience for EarlyStopping based on val_loss.\n",
|
||
" lr: Initial learning rate.\n",
|
||
" lr_factor: Factor to reduce learning rate in scheduler.\n",
|
||
" min_lr: Minimum learning rate allowed.\n",
|
||
"\n",
|
||
" Returns:\n",
|
||
" history: Training and validation history.\n",
|
||
" test_metrics: Metrics on the test set.\n",
|
||
" \"\"\"\n",
|
||
"\n",
|
||
" best_val_precision = 0.0\n",
|
||
" best_val_loss = float('inf')\n",
|
||
" no_val_loss_improvement_count = 0\n",
|
||
"\n",
|
||
" optimizer = torch.optim.AdamW(model.parameters(), lr=lr, eps=1e-8)\n",
|
||
" scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(\n",
|
||
" optimizer, mode=\"min\", factor=lr_factor, patience=2, min_lr=min_lr, verbose=True\n",
|
||
" )\n",
|
||
" scaler = GradScaler()\n",
|
||
"\n",
|
||
" history = {\n",
|
||
" \"train_loss\": [],\n",
|
||
" \"val_loss\": [],\n",
|
||
" \"train_accuracy\": [],\n",
|
||
" \"val_accuracy\": [],\n",
|
||
" \"train_precision\": [],\n",
|
||
" \"val_precision\": [],\n",
|
||
" \"val_recall\": []\n",
|
||
" }\n",
|
||
"\n",
|
||
" for epoch in range(epochs):\n",
|
||
" print(f\"\\n=== Epoch {epoch + 1}/{epochs} ===\")\n",
|
||
"\n",
|
||
" # Training phase\n",
|
||
" model.train()\n",
|
||
" train_loss, train_true, train_preds = 0.0, [], []\n",
|
||
"\n",
|
||
" for batch_idx, batch in enumerate(tqdm(train_loader, desc=\"Training\")):\n",
|
||
" input_ids = batch[\"input_ids\"].to(device)\n",
|
||
" attention_mask = batch[\"attention_mask\"].to(device)\n",
|
||
" labels = batch[\"label\"].to(device)\n",
|
||
"\n",
|
||
" optimizer.zero_grad()\n",
|
||
"\n",
|
||
" # with autocast(enabled=torch.cuda.is_available()):\n",
|
||
" with torch.amp.autocast(device_type='cuda' if torch.cuda.is_available() else 'cpu'):\n",
|
||
"\n",
|
||
" outputs = model(input_ids=input_ids, attention_mask=attention_mask, labels=labels)\n",
|
||
" loss = outputs.loss / gradient_accumulation_steps\n",
|
||
"\n",
|
||
" scaler.scale(loss).backward()\n",
|
||
"\n",
|
||
" if (batch_idx + 1) % gradient_accumulation_steps == 0 or (batch_idx + 1) == len(train_loader):\n",
|
||
" scaler.unscale_(optimizer)\n",
|
||
" torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)\n",
|
||
" scaler.step(optimizer)\n",
|
||
" scaler.update()\n",
|
||
"\n",
|
||
" train_loss += loss.item() * gradient_accumulation_steps\n",
|
||
" train_preds.extend(torch.argmax(outputs.logits, dim=1).cpu().numpy())\n",
|
||
" train_true.extend(labels.cpu().numpy())\n",
|
||
"\n",
|
||
" avg_train_loss = train_loss / len(train_loader)\n",
|
||
" train_accuracy = accuracy_score(train_true, train_preds)\n",
|
||
" train_precision = precision_score(train_true, train_preds, zero_division=0)\n",
|
||
" history[\"train_loss\"].append(avg_train_loss)\n",
|
||
" history[\"train_accuracy\"].append(train_accuracy)\n",
|
||
" history[\"train_precision\"].append(train_precision)\n",
|
||
"\n",
|
||
" print(f\"Train Loss: {avg_train_loss:.4f}, Train Accuracy: {train_accuracy:.4f}, Train Precision: {train_precision:.4f}\")\n",
|
||
"\n",
|
||
" # Validation phase\n",
|
||
" model.eval()\n",
|
||
" val_loss, val_true, val_preds = 0.0, [], []\n",
|
||
"\n",
|
||
" with torch.no_grad():\n",
|
||
" for batch in tqdm(val_loader, desc=\"Validation\"):\n",
|
||
" input_ids = batch[\"input_ids\"].to(device)\n",
|
||
" attention_mask = batch[\"attention_mask\"].to(device)\n",
|
||
" labels = batch[\"label\"].to(device)\n",
|
||
"\n",
|
||
" outputs = model(input_ids=input_ids, attention_mask=attention_mask, labels=labels)\n",
|
||
" loss = outputs.loss\n",
|
||
"\n",
|
||
" val_loss += loss.item()\n",
|
||
" val_preds.extend(torch.argmax(outputs.logits, dim=1).cpu().numpy())\n",
|
||
" val_true.extend(labels.cpu().numpy())\n",
|
||
"\n",
|
||
" avg_val_loss = val_loss / len(val_loader)\n",
|
||
" val_accuracy = accuracy_score(val_true, val_preds)\n",
|
||
" val_precision = precision_score(val_true, val_preds, zero_division=0)\n",
|
||
" val_recall = recall_score(val_true, val_preds, zero_division=0) # calcul recall ajouté\n",
|
||
"\n",
|
||
" history[\"val_loss\"].append(avg_val_loss)\n",
|
||
" history[\"val_accuracy\"].append(val_accuracy)\n",
|
||
" history[\"val_precision\"].append(val_precision)\n",
|
||
" history[\"val_recall\"].append(val_recall) # ajout dans l'historique\n",
|
||
"\n",
|
||
" print(f\"Val Loss: {avg_val_loss:.4f}, Val Accuracy: {val_accuracy:.4f}, Val Precision: {val_precision:.4f}, Val Recall: {val_recall:.4f}\")\n",
|
||
"\n",
|
||
" # Scheduler step on val_loss\n",
|
||
" scheduler.step(avg_val_loss)\n",
|
||
"\n",
|
||
" # Save best model based on val_precision\n",
|
||
" if val_precision > best_val_precision:\n",
|
||
" best_val_precision = val_precision\n",
|
||
" torch.save(model.state_dict(), \"./content/bert-model/model/best_model.pth\")\n",
|
||
" print(\"New best model saved based on val_precision.\")\n",
|
||
"\n",
|
||
" # EarlyStopping on val_loss\n",
|
||
" if avg_val_loss < best_val_loss:\n",
|
||
" best_val_loss = avg_val_loss\n",
|
||
" no_val_loss_improvement_count = 0\n",
|
||
" else:\n",
|
||
" no_val_loss_improvement_count += 1\n",
|
||
" print(f\"No val_loss improvement. Patience: {no_val_loss_improvement_count}/{patience}\")\n",
|
||
"\n",
|
||
" if no_val_loss_improvement_count >= patience:\n",
|
||
" print(\"EarlyStopping activated.\")\n",
|
||
" break\n",
|
||
"\n",
|
||
" # Load best model\n",
|
||
" model.load_state_dict(torch.load(\"./content/bert-model/model/best_model.pth\"))\n",
|
||
" print(\"Best model loaded for evaluation.\")\n",
|
||
"\n",
|
||
" # Evaluate on test set\n",
|
||
" test_metrics = evaluate_model(model, test_loader, device)\n",
|
||
"\n",
|
||
" return history, test_metrics"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"id": "3gDy-63XT76f"
|
||
},
|
||
"source": [
|
||
"## Fonction d'évaluation"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"id": "g2DZWDoNT76f"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# FONCTION D'ÉVALUATION\n",
|
||
"def evaluate_model(model, test_loader, device):\n",
|
||
" \"\"\"\n",
|
||
" Évalue le modèle sur le jeu de test et retourne les métriques et prédictions\n",
|
||
" \"\"\"\n",
|
||
" model.eval()\n",
|
||
" test_preds, test_true = [], []\n",
|
||
" test_probs = []\n",
|
||
"\n",
|
||
" with torch.no_grad():\n",
|
||
" for batch in tqdm(test_loader, desc=\"Évaluation sur le jeu de test\"):\n",
|
||
" input_ids = batch['input_ids'].to(device)\n",
|
||
" attention_mask = batch['attention_mask'].to(device)\n",
|
||
" labels = batch['label'].to(device)\n",
|
||
"\n",
|
||
" outputs = model(\n",
|
||
" input_ids=input_ids,\n",
|
||
" attention_mask=attention_mask\n",
|
||
" )\n",
|
||
"\n",
|
||
" # Récupération des prédictions et probabilités\n",
|
||
" logits = outputs.logits\n",
|
||
" probs = torch.nn.functional.softmax(logits, dim=1)\n",
|
||
" preds = torch.argmax(logits, dim=1).cpu().numpy()\n",
|
||
" true = labels.cpu().numpy()\n",
|
||
"\n",
|
||
" test_preds.extend(preds)\n",
|
||
" test_true.extend(true)\n",
|
||
" test_probs.extend(probs[:, 1].cpu().numpy()) # Probabilité de la classe positive\n",
|
||
"\n",
|
||
" # Calcul des métriques\n",
|
||
" accuracy = accuracy_score(test_true, test_preds)\n",
|
||
" precision = precision_score(test_true, test_preds)\n",
|
||
" recall = recall_score(test_true, test_preds)\n",
|
||
" f1 = f1_score(test_true, test_preds)\n",
|
||
"\n",
|
||
" # Matrice de confusion\n",
|
||
" cm = confusion_matrix(test_true, test_preds)\n",
|
||
"\n",
|
||
" # Classification report\n",
|
||
" report = classification_report(test_true, test_preds, target_names=['Négatif', 'Positif'])\n",
|
||
"\n",
|
||
" # Courbe ROC et AUC\n",
|
||
" fpr, tpr, _ = roc_curve(test_true, test_probs)\n",
|
||
" roc_auc = auc(fpr, tpr)\n",
|
||
"\n",
|
||
" # Regrouper toutes les métriques\n",
|
||
" metrics = {\n",
|
||
" 'accuracy': accuracy,\n",
|
||
" 'precision': precision,\n",
|
||
" 'recall': recall,\n",
|
||
" 'f1': f1,\n",
|
||
" 'roc_auc': roc_auc,\n",
|
||
" 'fpr': fpr,\n",
|
||
" 'tpr': tpr,\n",
|
||
" 'confusion_matrix': cm,\n",
|
||
" 'classification_report': report,\n",
|
||
" 'predictions': test_preds,\n",
|
||
" 'true_labels': test_true,\n",
|
||
" 'probabilities': test_probs\n",
|
||
" }\n",
|
||
"\n",
|
||
" return metrics"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"id": "o0S7DzDJdvbV"
|
||
},
|
||
"source": [
|
||
"## Afficher la matrice de confusion"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"id": "nsUgEh2pT76f"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# FONCTION POUR TRACER LA MATRICE DE CONFUSION\n",
|
||
"def plot_confusion_matrix(cm, class_names):\n",
|
||
" \"\"\"\n",
|
||
" Tracer la matrice de confusion\n",
|
||
" \"\"\"\n",
|
||
" plt.figure(figsize=(8, 6))\n",
|
||
" sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=class_names, yticklabels=class_names)\n",
|
||
" plt.xlabel('Prédictions')\n",
|
||
" plt.ylabel('Valeurs réelles')\n",
|
||
" plt.title('Matrice de confusion')\n",
|
||
"\n",
|
||
" # Save confusion matrix\n",
|
||
" filename = f'content/bert-model/confusion_matrix.png'\n",
|
||
" plt.savefig(filename)\n",
|
||
"\n",
|
||
" return plt.gcf()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"id": "ORnBybYLT76g"
|
||
},
|
||
"source": [
|
||
"## Fonction pour tracer la courbe ROC AUC"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"id": "Pf-tDY3OT76g"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# FONCTION POUR TRACER LA COURBE ROC\n",
|
||
"def plot_roc_curve(fpr, tpr, roc_auc, model_name, run_id=None):\n",
|
||
" \"\"\"\n",
|
||
" Trace la courbe ROC et l'enregistre dans MLflow\n",
|
||
" \"\"\"\n",
|
||
" plt.figure(figsize=(8, 6))\n",
|
||
" plt.plot(fpr, tpr, label=f'ROC curve (area = {roc_auc:.3f})')\n",
|
||
" plt.plot([0, 1], [0, 1], 'k--')\n",
|
||
" plt.xlim([0.0, 1.0])\n",
|
||
" plt.ylim([0.0, 1.05])\n",
|
||
" plt.xlabel('Taux de faux positifs')\n",
|
||
" plt.ylabel('Taux de vrais positifs')\n",
|
||
" plt.title(f'Courbe ROC - {model_name}')\n",
|
||
" plt.legend(loc=\"lower right\")\n",
|
||
"\n",
|
||
" # Sauvegarder la figure localement\n",
|
||
" filename = f'content/bert-model/roc_curve_{model_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(plt.gcf(), f\"roc_curve_{model_name}.png\")\n",
|
||
"\n",
|
||
" return plt.gcf()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"id": "WD_nm9eDT76f"
|
||
},
|
||
"source": [
|
||
"## Fonction pour tracer l'historique d'entraînement"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"id": "UKzSUOlqT76g"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# FONCTION POUR TRACER L'HISTORIQUE D'ENTRAÎNEMENT\n",
|
||
"def plot_training_history(history, model_name, run_id=None):\n",
|
||
" \"\"\"\n",
|
||
" Trace l'historique d'entraînement du modèle et l'enregistre dans MLflow\n",
|
||
" \"\"\"\n",
|
||
" fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))\n",
|
||
"\n",
|
||
" # Tracer l'accuracy\n",
|
||
" ax1.plot(history['train_precision'], label='train')\n",
|
||
" ax1.plot(history['val_precision'], label='validation')\n",
|
||
" ax1.set_title(f'Precision - {model_name}')\n",
|
||
" ax1.set_xlabel('Epoch')\n",
|
||
" ax1.set_ylabel('Precision')\n",
|
||
" ax1.legend()\n",
|
||
"\n",
|
||
" # Tracer la loss\n",
|
||
" ax2.plot(history['train_loss'], label='train')\n",
|
||
" ax2.plot(history['val_loss'], label='validation')\n",
|
||
" ax2.set_title(f'Loss - {model_name}')\n",
|
||
" ax2.set_xlabel('Epoch')\n",
|
||
" ax2.set_ylabel('Loss')\n",
|
||
" ax2.legend()\n",
|
||
"\n",
|
||
" plt.tight_layout()\n",
|
||
"\n",
|
||
" # Sauvegarder la figure localement\n",
|
||
" os.makedirs('content/bert-model', exist_ok=True)\n",
|
||
" filename = f'content/bert-model/training_history_{model_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}.png\")\n",
|
||
"\n",
|
||
" return fig"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"id": "aXZRXEMnT76g"
|
||
},
|
||
"source": [
|
||
"## Enregistrement du modèle dans MLFlow\n",
|
||
"\n",
|
||
"1. Définition de la signature du modèle pour MLflow\n",
|
||
"2. Démarrage d'une exécution MLflow avec un nom spécifique\n",
|
||
"3. Enregistrement des paramètres du modèle\n",
|
||
"4. Enregistrement des métriques de performance (accuracy, precision, recall, f1, roc_auc)\n",
|
||
"5. Création et enregistrement de visualisations (matrice de confusion, courbe ROC)\n",
|
||
"6. Enregistrement du rapport de classification\n",
|
||
"7. Sauvegarde locale du modèle BERT\n",
|
||
"8. Enregistrement du modèle PyTorch dans MLflow avec sa signature\n",
|
||
"9. Sauvegarde locale du tokenizer et enregistrement dans MLflow\n",
|
||
"10. Sauvegarde locale de la fonction de prétraitement (preprocessor) via pickle et enregistrement dans MLflow\n",
|
||
"11. Génération et enregistrement du fichier requirements.txt\n",
|
||
"10. Retourne l'**identifiant unique (Run ID)** de l'exécution MLflow qui vient d'être complétée, permettant de la référencer ultérieurement.\n",
|
||
"\n",
|
||
"## Tableau des chemins des artefacts\n",
|
||
"\n",
|
||
"| Artefact | Chemin local | Chemin MLflow |\n",
|
||
"|----------|--------------|---------------|\n",
|
||
"| Matrice de confusion | `content/bert-model/confusion_matrix.png` | `confusion_matrix_{model_name}.png` |\n",
|
||
"| Courbe ROC | `content/bert-model/roc_curve_{model_name}.png` | `roc_curve_{model_name}.png` |\n",
|
||
"| Historique d'entraînement | `content/bert-model/training_history_{model_name}.png` | `training_history_{model_name}.png` (si run_id fourni) |\n",
|
||
"| Rapport de classification | `content/bert-model/classification_report.txt` | Racine des artefacts |\n",
|
||
"| Modèle BERT | `content/bert-model/model/` | `model/` |\n",
|
||
"| Tokenizer | `content/bert-model/tokenizer/` | `tokenizer/` |\n",
|
||
"| Preprocessor | `content/bert-model/preprocessor/preprocessor.pkl` | `preprocessor/preprocessor.pkl` |\n",
|
||
"| Requirements | `content/bert-model/requirements.txt` | (Utilisé par MLflow comme dépendances du modèle) |\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"id": "3OppER9A_iPX"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# FONCTION POUR ENREGISTRER LE MODÈLE DANS MLFLOW\n",
|
||
"def log_model_to_mlflow(model, tokenizer, model_name, metrics, params=None):\n",
|
||
" \"\"\"\n",
|
||
" Enregistre le modèle et ses performances dans MLflow, y compris la signature.\n",
|
||
" Gère correctement les devices et la sérialisation JSON des métriques NumPy.\n",
|
||
" Supprime input_example pour éviter l'avertissement de validation avec le flavor pytorch.\n",
|
||
"\n",
|
||
" Args:\n",
|
||
" model (torch.nn.Module): Le modèle PyTorch (Hugging Face) entraîné.\n",
|
||
" tokenizer: Le tokenizer Hugging Face associé au modèle.\n",
|
||
" model_name (str): Un nom pour identifier ce modèle/cette exécution.\n",
|
||
" metrics (dict): Un dictionnaire contenant les métriques de performance.\n",
|
||
" params (dict, optional): Un dictionnaire des hyperparamètres utilisés. Defaults to None.\n",
|
||
"\n",
|
||
" Returns:\n",
|
||
" str: L'ID de l'exécution MLflow.\n",
|
||
" \"\"\"\n",
|
||
" class_names = ['Négatif', 'Positif']\n",
|
||
"\n",
|
||
" # --- Définir la signature du modèle ---\n",
|
||
" sample_input_text = [\"Ceci est un exemple de texte pour inférer la signature.\"]\n",
|
||
" inputs = tokenizer(\n",
|
||
" sample_input_text, return_tensors=\"pt\", padding=\"max_length\",\n",
|
||
" truncation=True, max_length=128\n",
|
||
" )\n",
|
||
" try:\n",
|
||
" model_device = next(model.parameters()).device\n",
|
||
" except StopIteration:\n",
|
||
" model_device = torch.device(\"cpu\")\n",
|
||
" except Exception:\n",
|
||
" model_device = torch.device(\"cpu\")\n",
|
||
"\n",
|
||
" inputs_on_device = None\n",
|
||
" try:\n",
|
||
" inputs_on_device = {k: v.to(model_device) for k, v in inputs.items()}\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"Error moving input tensors to device {model_device}: {e}. Skipping signature inference.\")\n",
|
||
"\n",
|
||
" input_data_for_signature = {k: v.cpu().numpy() for k, v in inputs.items()} # For potential future use, still on CPU\n",
|
||
"\n",
|
||
" predictions = None\n",
|
||
" signature = None\n",
|
||
" if inputs_on_device:\n",
|
||
" model.eval()\n",
|
||
" with torch.no_grad():\n",
|
||
" try:\n",
|
||
" outputs = model(**inputs_on_device)\n",
|
||
" if hasattr(outputs, 'logits'):\n",
|
||
" predictions = outputs.logits.cpu().numpy()\n",
|
||
" elif isinstance(outputs, torch.Tensor):\n",
|
||
" predictions = outputs.cpu().numpy()\n",
|
||
" else:\n",
|
||
" # Fallback attempt\n",
|
||
" for val in getattr(outputs, 'values', lambda: [])(): # Handle dicts or sequences\n",
|
||
" if isinstance(val, torch.Tensor):\n",
|
||
" predictions = val.cpu().numpy()\n",
|
||
" break\n",
|
||
"\n",
|
||
" if predictions is not None:\n",
|
||
" # Infer signature using the CPU numpy inputs and CPU numpy predictions\n",
|
||
" signature = infer_signature(input_data_for_signature, predictions)\n",
|
||
" print(\"Model signature inferred successfully.\")\n",
|
||
" else:\n",
|
||
" print(\"Warning: Could not extract prediction tensor for signature.\")\n",
|
||
"\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"Error during model prediction or signature inference: {e}\")\n",
|
||
" else:\n",
|
||
" print(\"Skipping signature inference because input tensors could not be moved to model device.\")\n",
|
||
" # --- Fin de la définition de la signature ---\n",
|
||
"\n",
|
||
" # Démarrer une exécution MLflow\n",
|
||
" with mlflow.start_run(run_name=f\"Model_Bert-{model_name}\") as run:\n",
|
||
"\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 performance\n",
|
||
" mlflow.log_metric(\"accuracy\", metrics['accuracy'])\n",
|
||
" mlflow.log_metric(\"precision\", metrics['precision'])\n",
|
||
" mlflow.log_metric(\"recall\", metrics['recall'])\n",
|
||
" mlflow.log_metric(\"f1\", metrics['f1'])\n",
|
||
" mlflow.log_metric(\"roc_auc\", metrics['roc_auc'])\n",
|
||
"\n",
|
||
" mlflow.log_param(\"model_base\", model_name)\n",
|
||
" mlflow.set_tag(\"model_base\", model_name)\n",
|
||
"\n",
|
||
" # Tracer et enregistrer la matrice de confusion\n",
|
||
" fig_cm = plot_confusion_matrix(metrics['confusion_matrix'], class_names)\n",
|
||
" mlflow.log_figure(fig_cm, f\"confusion_matrix_{model_name}.png\")\n",
|
||
"\n",
|
||
" # Tracer et enregistrer la courbe ROC\n",
|
||
" fig_roc = plot_roc_curve(metrics['fpr'], metrics['tpr'], metrics['roc_auc'], model_name)\n",
|
||
" mlflow.log_figure(fig_roc, f\"roc_curve_{model_name}.png\")\n",
|
||
"\n",
|
||
" # Enregistrer le rapport de classification\n",
|
||
" report_path = f\"content/bert-model/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(metrics['classification_report'])\n",
|
||
" mlflow.log_artifact(report_path)\n",
|
||
"\n",
|
||
"\n",
|
||
" # Sauvegarder le modèle localement\n",
|
||
" model_path = f\"content/bert-model/model\"\n",
|
||
" os.makedirs(model_path, exist_ok=True)\n",
|
||
" try:\n",
|
||
" model.save_pretrained(model_path)\n",
|
||
" print(\"Model logged to MLflow artifact path 'model'.\")\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"Warning: Failed to save or log model: {e}\")\n",
|
||
"\n",
|
||
"\n",
|
||
" # Enregistrer le tokenizer localement et sur MLFlow\n",
|
||
" tokenizer_path = f\"content/bert-model/tokenizer\"\n",
|
||
" os.makedirs(tokenizer_path, exist_ok=True)\n",
|
||
" try:\n",
|
||
" tokenizer.save_pretrained(tokenizer_path)\n",
|
||
" mlflow.log_artifact(tokenizer_path)\n",
|
||
" print(\"Tokenizer logged to MLflow artifact path 'tokenizer'.\")\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"Warning: Failed to save or log tokenizer: {e}\")\n",
|
||
"\n",
|
||
"\n",
|
||
" # --- Sauvegarder la fonction preprocessor via pickle ---\n",
|
||
" local_save_directory = \"content/bert-model/preprocessor\" # Attention au double \"content\" si c'est bien voulu\n",
|
||
" local_pickle_filename = \"preprocessor.pkl\"\n",
|
||
" local_pickle_filepath = os.path.join(local_save_directory, local_pickle_filename)\n",
|
||
" # Sous-dossier cible dans les artefacts MLflow\n",
|
||
" mlflow_artifact_subdir = \"preprocessor\"\n",
|
||
" try:\n",
|
||
" os.makedirs(local_save_directory, exist_ok=True)\n",
|
||
" with open(local_pickle_filepath, \"wb\") as f_out:\n",
|
||
" pickle.dump(preprocess_tweet_for_bert, f_out)\n",
|
||
" mlflow.log_artifact(local_pickle_filepath, artifact_path=mlflow_artifact_subdir)\n",
|
||
" except NameError:\n",
|
||
" print(f\"\\nWarning: La fonction 'preprocess_tweet_for_bert' n'est pas définie. Impossible de la sauvegarder.\\n\")\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"\\nWarning: Impossible de sauvegarder (pickle) ou logger la fonction de prétraitement : {e}\\n\")\n",
|
||
"\n",
|
||
"\n",
|
||
" # Enregistrer le fichier requirements.txt\n",
|
||
" requirements_path = \"content/bert-model/requirements.txt\"\n",
|
||
" try:\n",
|
||
" with open(requirements_path, 'w') as f:\n",
|
||
" import sys\n",
|
||
" subprocess.check_call([sys.executable, '-m', 'pip', 'freeze'], stdout=f)\n",
|
||
" except subprocess.CalledProcessError as e:\n",
|
||
" print(f\"Warning: Failed to generate requirements.txt: {e}. Logging without pip_requirements.\")\n",
|
||
" requirements_path = None\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"An unexpected error occurred during requirements generation: {e}\")\n",
|
||
" requirements_path = None\n",
|
||
"\n",
|
||
" # --- Enregistrer le modèle PyTorch sans input_example ---\n",
|
||
" try:\n",
|
||
" mlflow.pytorch.log_model(\n",
|
||
" pytorch_model=model,\n",
|
||
" artifact_path=\"model\", # Simplement \"model\" pour être cohérent\n",
|
||
" signature=signature,\n",
|
||
" pip_requirements=requirements_path if requirements_path else None\n",
|
||
" )\n",
|
||
" print(f\"Model '{model_name}' logged to MLflow artifact path 'model_{model_name}'.\")\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"FATAL: Error logging PyTorch model to MLflow: {e}\")\n",
|
||
" return None\n",
|
||
"\n",
|
||
" print(f\"MLflow logging attempt finished for run '{run.info.run_id}'.\")\n",
|
||
"\n",
|
||
" return run.info.run_id"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"id": "1PHu82H-YNtN"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# FONCTION POUR ENREGISTRER LE MODÈLE DANS MLFLOW\n",
|
||
"def log_model_to_mlflow(model, tokenizer, model_name, metrics, history=None, params=None):\n",
|
||
" \"\"\"\n",
|
||
" Enregistre le modèle et ses performances dans MLflow, y compris la signature.\n",
|
||
" Gère correctement les devices et la sérialisation JSON des métriques NumPy.\n",
|
||
" Supprime input_example pour éviter l'avertissement de validation avec le flavor pytorch.\n",
|
||
"\n",
|
||
" Args:\n",
|
||
" model (torch.nn.Module): Le modèle PyTorch (Hugging Face) entraîné.\n",
|
||
" tokenizer: Le tokenizer Hugging Face associé au modèle.\n",
|
||
" model_name (str): Un nom pour identifier ce modèle/cette exécution.\n",
|
||
" metrics (dict): Un dictionnaire contenant les métriques de performance.\n",
|
||
" params (dict, optional): Un dictionnaire des hyperparamètres utilisés. Defaults to None.\n",
|
||
"\n",
|
||
" Returns:\n",
|
||
" str: L'ID de l'exécution MLflow.\n",
|
||
" \"\"\"\n",
|
||
" class_names = ['Négatif', 'Positif']\n",
|
||
"\n",
|
||
" # --- Définir la signature du modèle ---\n",
|
||
" sample_input_text = [\"Ceci est un exemple de texte pour inférer la signature.\"]\n",
|
||
" inputs = tokenizer(\n",
|
||
" sample_input_text, return_tensors=\"pt\", padding=\"max_length\",\n",
|
||
" truncation=True, max_length=128\n",
|
||
" )\n",
|
||
" try:\n",
|
||
" model_device = next(model.parameters()).device\n",
|
||
" except StopIteration:\n",
|
||
" model_device = torch.device(\"cpu\")\n",
|
||
" except Exception:\n",
|
||
" model_device = torch.device(\"cpu\")\n",
|
||
"\n",
|
||
" inputs_on_device = None\n",
|
||
" try:\n",
|
||
" inputs_on_device = {k: v.to(model_device) for k, v in inputs.items()}\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"Error moving input tensors to device {model_device}: {e}. Skipping signature inference.\")\n",
|
||
"\n",
|
||
" input_data_for_signature = {k: v.cpu().numpy() for k, v in inputs.items()} # For potential future use, still on CPU\n",
|
||
"\n",
|
||
" predictions = None\n",
|
||
" signature = None\n",
|
||
" if inputs_on_device:\n",
|
||
" model.eval()\n",
|
||
" with torch.no_grad():\n",
|
||
" try:\n",
|
||
" outputs = model(**inputs_on_device)\n",
|
||
" if hasattr(outputs, 'logits'):\n",
|
||
" predictions = outputs.logits.cpu().numpy()\n",
|
||
" elif isinstance(outputs, torch.Tensor):\n",
|
||
" predictions = outputs.cpu().numpy()\n",
|
||
" else:\n",
|
||
" # Fallback attempt\n",
|
||
" for val in getattr(outputs, 'values', lambda: [])(): # Handle dicts or sequences\n",
|
||
" if isinstance(val, torch.Tensor):\n",
|
||
" predictions = val.cpu().numpy()\n",
|
||
" break\n",
|
||
"\n",
|
||
" if predictions is not None:\n",
|
||
" # Infer signature using the CPU numpy inputs and CPU numpy predictions\n",
|
||
" signature = infer_signature(input_data_for_signature, predictions)\n",
|
||
" print(\"Model signature inferred successfully.\")\n",
|
||
" else:\n",
|
||
" print(\"Warning: Could not extract prediction tensor for signature.\")\n",
|
||
"\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"Error during model prediction or signature inference: {e}\")\n",
|
||
" else:\n",
|
||
" print(\"Skipping signature inference because input tensors could not be moved to model device.\")\n",
|
||
" # --- Fin de la définition de la signature ---\n",
|
||
"\n",
|
||
" # Démarrer une exécution MLflow\n",
|
||
" with mlflow.start_run(run_name=f\"Model_Bert-{model_name}\") as run:\n",
|
||
"\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",
|
||
" if history is not None:\n",
|
||
" val_precisions = history.get(\"val_precision\", [])\n",
|
||
" if val_precisions:\n",
|
||
" best_epoch_idx = val_precisions.index(max(val_precisions))\n",
|
||
"\n",
|
||
" val_precision_at_best = val_precisions[best_epoch_idx]\n",
|
||
" val_loss_at_best = history.get(\"val_loss\", [None])[best_epoch_idx]\n",
|
||
" val_recall_at_best = history.get(\"val_recall\", [None])[best_epoch_idx]\n",
|
||
"\n",
|
||
" mlflow.log_metric(\"val_precision\", val_precision_at_best)\n",
|
||
" mlflow.log_metric(\"val_loss\", val_loss_at_best)\n",
|
||
" mlflow.log_metric(\"val_recall\", val_recall_at_best)\n",
|
||
"\n",
|
||
"\n",
|
||
" # Enregistrer les métriques de performance\n",
|
||
" mlflow.log_metric(\"test_precision\", metrics['precision'])\n",
|
||
" mlflow.log_metric(\"test_accuracy\", metrics['accuracy'])\n",
|
||
" mlflow.log_metric(\"test_recall\", metrics['recall'])\n",
|
||
" mlflow.log_metric(\"test_f1\", metrics['f1'])\n",
|
||
" mlflow.log_metric(\"test_roc_auc\", metrics['roc_auc'])\n",
|
||
"\n",
|
||
" mlflow.log_param(\"model_base\", model_name)\n",
|
||
" mlflow.set_tag(\"model_base\", model_name)\n",
|
||
"\n",
|
||
" # Tracer et enregistrer la matrice de confusion\n",
|
||
" fig_cm = plot_confusion_matrix(metrics['confusion_matrix'], class_names)\n",
|
||
" mlflow.log_figure(fig_cm, f\"confusion_matrix_{model_name}.png\")\n",
|
||
"\n",
|
||
" # Tracer et enregistrer la courbe ROC\n",
|
||
" fig_roc = plot_roc_curve(metrics['fpr'], metrics['tpr'], metrics['roc_auc'], model_name)\n",
|
||
" mlflow.log_figure(fig_roc, f\"roc_curve_{model_name}.png\")\n",
|
||
"\n",
|
||
" # Enregistrer le rapport de classification\n",
|
||
" report_path = f\"content/bert-model/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(metrics['classification_report'])\n",
|
||
" mlflow.log_artifact(report_path)\n",
|
||
"\n",
|
||
"\n",
|
||
" # Sauvegarder le modèle localement\n",
|
||
" model_path = f\"content/bert-model/model\"\n",
|
||
" os.makedirs(model_path, exist_ok=True)\n",
|
||
" try:\n",
|
||
" model.save_pretrained(model_path)\n",
|
||
" print(\"Model logged to MLflow artifact path 'model'.\")\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"Warning: Failed to save or log model: {e}\")\n",
|
||
"\n",
|
||
"\n",
|
||
" # Enregistrer le tokenizer localement et sur MLFlow\n",
|
||
" tokenizer_path = f\"content/bert-model/tokenizer\"\n",
|
||
" os.makedirs(tokenizer_path, exist_ok=True)\n",
|
||
" try:\n",
|
||
" tokenizer.save_pretrained(tokenizer_path)\n",
|
||
" mlflow.log_artifact(tokenizer_path)\n",
|
||
" print(\"Tokenizer logged to MLflow artifact path 'tokenizer'.\")\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"Warning: Failed to save or log tokenizer: {e}\")\n",
|
||
"\n",
|
||
"\n",
|
||
" # --- Sauvegarder la fonction preprocessor via pickle ---\n",
|
||
" local_save_directory = \"content/bert-model/preprocessor\" # Attention au double \"content\" si c'est bien voulu\n",
|
||
" local_pickle_filename = \"preprocessor.pkl\"\n",
|
||
" local_pickle_filepath = os.path.join(local_save_directory, local_pickle_filename)\n",
|
||
" # Sous-dossier cible dans les artefacts MLflow\n",
|
||
" mlflow_artifact_subdir = \"preprocessor\"\n",
|
||
" try:\n",
|
||
" os.makedirs(local_save_directory, exist_ok=True)\n",
|
||
" with open(local_pickle_filepath, \"wb\") as f_out:\n",
|
||
" pickle.dump(preprocess_tweet_for_bert, f_out)\n",
|
||
" mlflow.log_artifact(local_pickle_filepath, artifact_path=mlflow_artifact_subdir)\n",
|
||
" except NameError:\n",
|
||
" print(f\"\\nWarning: La fonction 'preprocess_tweet_for_bert' n'est pas définie. Impossible de la sauvegarder.\\n\")\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"\\nWarning: Impossible de sauvegarder (pickle) ou logger la fonction de prétraitement : {e}\\n\")\n",
|
||
"\n",
|
||
"\n",
|
||
" # Enregistrer le fichier requirements.txt\n",
|
||
" requirements_path = \"content/bert-model/requirements.txt\"\n",
|
||
" try:\n",
|
||
" with open(requirements_path, 'w') as f:\n",
|
||
" import sys\n",
|
||
" subprocess.check_call([sys.executable, '-m', 'pip', 'freeze'], stdout=f)\n",
|
||
" except subprocess.CalledProcessError as e:\n",
|
||
" print(f\"Warning: Failed to generate requirements.txt: {e}. Logging without pip_requirements.\")\n",
|
||
" requirements_path = None\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"An unexpected error occurred during requirements generation: {e}\")\n",
|
||
" requirements_path = None\n",
|
||
"\n",
|
||
" # --- Enregistrer le modèle PyTorch sans input_example ---\n",
|
||
" try:\n",
|
||
" mlflow.pytorch.log_model(\n",
|
||
" pytorch_model=model,\n",
|
||
" artifact_path=\"model\", # Simplement \"model\" pour être cohérent\n",
|
||
" signature=signature,\n",
|
||
" pip_requirements=requirements_path if requirements_path else None\n",
|
||
" )\n",
|
||
" print(f\"Model '{model_name}' logged to MLflow artifact path 'model_{model_name}'.\")\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"FATAL: Error logging PyTorch model to MLflow: {e}\")\n",
|
||
" return None\n",
|
||
"\n",
|
||
" print(f\"MLflow logging attempt finished for run '{run.info.run_id}'.\")\n",
|
||
"\n",
|
||
" return run.info.run_id"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"id": "o1uxWQimT76g"
|
||
},
|
||
"source": [
|
||
"## Entrainement du modèle : `DistilBertForSequenceClassification`\n",
|
||
"\n",
|
||
"[DistilBertForSequenceClassification](https://huggingface.co/docs/transformers/model_doc/distilbert#transformers.DistilBertForSequenceClassification) est un modèle basé sur **DistilBERT** avec **une couche de classification ou de régression ajoutée à la tête (head)**. Il est conçu pour les tâches de **classification de séquence**.\n",
|
||
"\n",
|
||
"**DistilBertForSequenceClassification** est une version allégée de BERT, idéale pour des tâches de classification de texte. Il est facile à utiliser grâce aux classes `AutoTokenizer` et `AutoModel`, et il prend en charge plusieurs types de classification (mono-étiquette, multi-étiquettes). Il s’intègre naturellement avec **PyTorch** et peut être fine-tuné sur des tâches spécifiques.\n",
|
||
"\n",
|
||
"#### 📌 **Caractéristiques principales :** \n",
|
||
"- **Hérite de `PreTrainedModel`**, ce qui lui permet d’utiliser les fonctionnalités standards des modèles pré-entraînés (téléchargement, sauvegarde, ajustement des embeddings, etc.). \n",
|
||
"- **Sous-classe de `torch.nn.Module`**, donc il fonctionne comme un module PyTorch classique. \n",
|
||
"- Utilisé pour **la classification de texte** (binaire, multi-classes ou multi-étiquettes). \n",
|
||
"\n",
|
||
"### ⚙️ **Méthode `forward` (passage avant du modèle)** \n",
|
||
"\n",
|
||
"**Entrées possibles :** \n",
|
||
"- `input_ids` : Identifiants des tokens dans le vocabulaire (obtenus avec un tokenizer). \n",
|
||
"- `attention_mask` : Masque pour ignorer les tokens de padding (1 = pris en compte, 0 = ignoré). \n",
|
||
"- `head_mask` : Masque pour désactiver certaines têtes d’attention. \n",
|
||
"- `inputs_embeds` : Embeddings d’entrée à utiliser à la place de `input_ids`. \n",
|
||
"- `labels` : Étiquettes pour la classification, utilisées pour calculer la perte (`CrossEntropy` ou `MSE` selon `num_labels`). \n",
|
||
"\n",
|
||
"**Sorties possibles :** \n",
|
||
"- `loss` : Perte (si `labels` est fourni). \n",
|
||
"- `logits` : Scores de classification (avant application de **Softmax**). \n",
|
||
"- `hidden_states` : États cachés de toutes les couches du modèle (si demandé). \n",
|
||
"- `attentions` : Poids des mécanismes d’attention (si demandé). \n",
|
||
"\n",
|
||
"### Analyse de sentiment de tweet\n",
|
||
"\n",
|
||
"Pour une **analyse de sentiment de tweet** avec **deux classes distinctes** (0 = négatif, 1 = positif), il faut utiliser **une classification simple** (**single-label classification**). \n",
|
||
"\n",
|
||
"- Chaque tweet appartient **exclusivement** à une seule catégorie (**négatif ou positif, mais pas les deux**). \n",
|
||
"- La classification **multi-étiquettes** est utilisée lorsque **plusieurs catégories peuvent s’appliquer simultanément** (ex : un tweet peut être à la fois « joyeux » et « informatif »). \n",
|
||
"\n",
|
||
"### 🔹 **Comment configurer le modèle pour une classification binaire ?**\n",
|
||
"\n",
|
||
"1. Charger un modèle pré-entraîné et indiquer `num_labels=2`.\n",
|
||
"2. Le modèle renverra 0 ou 1, indiquant si le tweet est négatif ou positif. \n",
|
||
"\n",
|
||
"Pour entraîner le modèle sur un dataset personnalisé (ex : tweets annotés manuellement), il faudra fine-tuner DistilBERT avec une **Cross-Entropy Loss** adaptée à la classification binaire.\n",
|
||
"\n",
|
||
"### Documentation\n",
|
||
"\n",
|
||
"- `distilbert-base-uncased` : https://huggingface.co/docs/transformers/model_doc/distilbert"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"id": "kVj7LqF-bZGq"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# FONCTION PRINCIPALE D'ENTRAÎNEMENT\n",
|
||
"def train_bert_sentiment(data_path, model_name=\"distilbert-base-uncased\", batch_size=4, epochs=3, sample_size=20000):\n",
|
||
" \"\"\"\n",
|
||
" Fonction principale pour l'entraînement du modèle DistilBERT sur une tâche d'analyse de sentiments.\n",
|
||
" \"\"\"\n",
|
||
"\n",
|
||
" # Définir les paramètres\n",
|
||
" params = {\n",
|
||
" 'model_name': model_name,\n",
|
||
" 'batch_size': batch_size,\n",
|
||
" 'learning_rate': 2e-5,\n",
|
||
" 'epochs': epochs,\n",
|
||
" 'max_length': 128,\n",
|
||
" 'sample_size': sample_size\n",
|
||
" }\n",
|
||
"\n",
|
||
" # Charger les données\n",
|
||
" print(\"Chargement du dataset...\")\n",
|
||
" column_names = ['target', 'ids', 'date', 'flag', 'user', 'text']\n",
|
||
"\n",
|
||
" try:\n",
|
||
" raw_data = pd.read_csv(data_path, encoding='utf-8', names=column_names)\n",
|
||
" except UnicodeDecodeError:\n",
|
||
" print(\"Lecture du fichier en latin-1...\")\n",
|
||
" raw_data = pd.read_csv(data_path, encoding='latin-1', names=column_names)\n",
|
||
"\n",
|
||
" # Préparer les données\n",
|
||
" print(\"Préparation des données...\")\n",
|
||
" data_splits = prepare_data(raw_data, sample_size=sample_size)\n",
|
||
"\n",
|
||
" # Initialiser le tokenizer et le modèle\n",
|
||
" print(\"Initialisation du modèle DistilBERT...\")\n",
|
||
" tokenizer = DistilBertTokenizer.from_pretrained(model_name)\n",
|
||
" model = DistilBertForSequenceClassification.from_pretrained(\n",
|
||
" model_name,\n",
|
||
" num_labels=2 # Sentiment binaire (0 = négatif, 1 = positif)\n",
|
||
" )\n",
|
||
"\n",
|
||
" # Ajustement du batch size selon la mémoire GPU\n",
|
||
" adjusted_batch_size = min(8, batch_size)\n",
|
||
" print(f\"Batch size ajusté à {adjusted_batch_size} pour économiser la mémoire GPU.\")\n",
|
||
"\n",
|
||
" # Création des datasets et des dataloaders\n",
|
||
" train_dataset = TweetDataset(data_splits['train']['texts'], data_splits['train']['labels'], tokenizer)\n",
|
||
" val_dataset = TweetDataset(data_splits['val']['texts'], data_splits['val']['labels'], tokenizer)\n",
|
||
" test_dataset = TweetDataset(data_splits['test']['texts'], data_splits['test']['labels'], tokenizer)\n",
|
||
"\n",
|
||
" train_loader = DataLoader(train_dataset, batch_size=adjusted_batch_size, shuffle=True)\n",
|
||
" val_loader = DataLoader(val_dataset, batch_size=adjusted_batch_size * 2)\n",
|
||
" test_loader = DataLoader(test_dataset, batch_size=adjusted_batch_size * 2)\n",
|
||
"\n",
|
||
" # Détection du device (GPU/CPU)\n",
|
||
" device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
|
||
" print(f\"Utilisation de : {device}\")\n",
|
||
"\n",
|
||
" # Déplacement du modèle sur le device\n",
|
||
" model.to(device)\n",
|
||
"\n",
|
||
" # Entraînement du modèle\n",
|
||
" print(\"Début de l'entraînement...\")\n",
|
||
"\n",
|
||
" # Ajustement de l'accumulation de gradients\n",
|
||
" gradient_accumulation_steps = max(1, 16 // adjusted_batch_size) # Éviter des valeurs trop élevées\n",
|
||
" print(f\"Accumulation de gradient ajustée à {gradient_accumulation_steps} étapes.\")\n",
|
||
"\n",
|
||
" history, metrics = train_model(\n",
|
||
" model,\n",
|
||
" train_loader,\n",
|
||
" val_loader,\n",
|
||
" test_loader,\n",
|
||
" device,\n",
|
||
" epochs=epochs,\n",
|
||
" gradient_accumulation_steps=gradient_accumulation_steps\n",
|
||
" )\n",
|
||
"\n",
|
||
" # Enregistrement du modèle dans MLflow\n",
|
||
" print(\"Enregistrement du modèle dans MLflow...\")\n",
|
||
" run_id = log_model_to_mlflow(model, tokenizer, model_name, metrics, history, params)\n",
|
||
"\n",
|
||
" # Tracer et enregistrer l'historique d'entraînement\n",
|
||
" plot_training_history(history, model_name, run_id)\n",
|
||
"\n",
|
||
" # Retourner le modèle entraîné et le tokenizer\n",
|
||
" return {\n",
|
||
" 'model': model,\n",
|
||
" 'tokenizer': tokenizer,\n",
|
||
" 'metrics': metrics,\n",
|
||
" 'run_id': run_id\n",
|
||
" }\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"colab": {
|
||
"base_uri": "https://localhost:8080/",
|
||
"height": 1000,
|
||
"referenced_widgets": [
|
||
"f4c7033b02a2493085d1ac0cfac9cccf",
|
||
"3d5883b5f0bb4098bda8599622824948",
|
||
"3502027e67de4c36b46688597314fb2e",
|
||
"4db20c46a69043fdb7d29ccaa5f03e12",
|
||
"eb20692f8413420f9ca58df09b2d5feb",
|
||
"e47e179020f54e5b84017148d09480e9",
|
||
"e23da7120310469798127dfbf039919e",
|
||
"44325b25ca5f41d2a5ff31e6cdcf179f",
|
||
"b6aead1ab91f4ad1a903009b95c39036",
|
||
"2eadd184b69d41a696fed5c7bc5b1843",
|
||
"a52850e715624d3986a292dca1e6fa62",
|
||
"2bd37c30fbe74e3eb9f7d0a660b94772",
|
||
"5a904bdfc6e3488b963f9952ed7936c9",
|
||
"63840ffc38eb4932b39d00edfcbe5f15",
|
||
"a994789a34be47ffbafa558d1a15821d",
|
||
"9acf152a8b914b9faadc6a6a11f7300b",
|
||
"d20225cccfc64b0ba25c555cf5a3efba",
|
||
"0e164b5d9d17436d8cb259187680274c",
|
||
"716f683828664694823b072c3811c7c5",
|
||
"d52088f4990f492bb35d1f54c419637d",
|
||
"cf42f21334ba4e7e9c83edb6d2f95871",
|
||
"cc9639e12a1448a580b3794087a09ad1",
|
||
"502800fba0c04ec6b54b83a1e9fbfc11",
|
||
"b5cc33676b3648fd9f341bbdb5a31de5",
|
||
"0793c0a09e3b4ec6832080435b507ffa",
|
||
"771269ab33bf4b68b5a4acd4cada3de9",
|
||
"84cd157aa0884ec5b6629011f678339f",
|
||
"12e78de1f0eb45e59ce29473694e6895",
|
||
"d7d394ea510749f7b1820274c0553db2",
|
||
"10faa872bd504fa49fc1cf05c58ce391",
|
||
"b9c7bef298474c949940154207dea96a",
|
||
"d7fd75e7490946f29f20b0b4ed63ef3c",
|
||
"adb66ec7c3fd46089ff61496e4db9e02",
|
||
"e333785179dd45d89ae039fd7e6361da",
|
||
"bac5e480209c4cd09cb3b891dd7683f3",
|
||
"48b5dc12ca9241a7955b798e2b204792",
|
||
"8cca18086a53470894d018a04a8bc2be",
|
||
"340dc17022ec42e9ba4e61726711566a",
|
||
"58026471ff914aaeba005c52aab2db47",
|
||
"4db07c2a0409413384cfe1ca0dc08ff4",
|
||
"c764fa8136b24134a8b92649d91eb854",
|
||
"f828ba130d4b42a580f10d8879f1a1fd",
|
||
"f35f52483ef240c3adab0cce32a7b818",
|
||
"360c34394459499ea4c3b4ba3367ba39",
|
||
"f05015da03d84663852c114110489c96",
|
||
"a44c09d432ba40a589247626a09cfe34",
|
||
"89896a47fccc4fb4915014b4f0b7048b",
|
||
"9a86ae6790d84aa1866eaba2d1df3216",
|
||
"214fc3b57b6c4697a1632038fd7a40fa",
|
||
"a60693496b574f659ecd8be5feb863fd",
|
||
"e50178d16de24d03bc38804424557a05",
|
||
"dee2c3aa487545cba7e32834d11ea883",
|
||
"7c173af0d57c497ca04a7fb5320a5f8d",
|
||
"198afd4b3f094ffc8354b69d987334b4",
|
||
"326ff209eb5741e793ccc3696e65b58c"
|
||
]
|
||
},
|
||
"executionInfo": {
|
||
"elapsed": 3417524,
|
||
"status": "ok",
|
||
"timestamp": 1752355021870,
|
||
"user": {
|
||
"displayName": "Grégoire",
|
||
"userId": "01249298206117462766"
|
||
},
|
||
"user_tz": -120
|
||
},
|
||
"id": "8Y3ycjLlT76h",
|
||
"outputId": "c1430b51-ecc5-47f3-8b5b-00e5cebfbfee"
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Chargement du dataset...\n",
|
||
"Lecture du fichier en latin-1...\n",
|
||
"Préparation des données...\n",
|
||
"Prétraitement des tweets...\n",
|
||
"Initialisation du modèle DistilBERT...\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"/usr/local/lib/python3.11/dist-packages/huggingface_hub/utils/_auth.py:94: UserWarning: \n",
|
||
"The secret `HF_TOKEN` does not exist in your Colab secrets.\n",
|
||
"To authenticate with the Hugging Face Hub, create a token in your settings tab (https://huggingface.co/settings/tokens), set it as secret in your Google Colab and restart your session.\n",
|
||
"You will be able to reuse this secret in all of your notebooks.\n",
|
||
"Please note that authentication is recommended but still optional to access public models or datasets.\n",
|
||
" warnings.warn(\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"application/vnd.jupyter.widget-view+json": {
|
||
"model_id": "f4c7033b02a2493085d1ac0cfac9cccf",
|
||
"version_major": 2,
|
||
"version_minor": 0
|
||
},
|
||
"text/plain": [
|
||
"tokenizer_config.json: 0%| | 0.00/48.0 [00:00<?, ?B/s]"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"application/vnd.jupyter.widget-view+json": {
|
||
"model_id": "2bd37c30fbe74e3eb9f7d0a660b94772",
|
||
"version_major": 2,
|
||
"version_minor": 0
|
||
},
|
||
"text/plain": [
|
||
"vocab.txt: 0%| | 0.00/232k [00:00<?, ?B/s]"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"application/vnd.jupyter.widget-view+json": {
|
||
"model_id": "502800fba0c04ec6b54b83a1e9fbfc11",
|
||
"version_major": 2,
|
||
"version_minor": 0
|
||
},
|
||
"text/plain": [
|
||
"tokenizer.json: 0%| | 0.00/466k [00:00<?, ?B/s]"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"application/vnd.jupyter.widget-view+json": {
|
||
"model_id": "e333785179dd45d89ae039fd7e6361da",
|
||
"version_major": 2,
|
||
"version_minor": 0
|
||
},
|
||
"text/plain": [
|
||
"config.json: 0%| | 0.00/483 [00:00<?, ?B/s]"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"application/vnd.jupyter.widget-view+json": {
|
||
"model_id": "f05015da03d84663852c114110489c96",
|
||
"version_major": 2,
|
||
"version_minor": 0
|
||
},
|
||
"text/plain": [
|
||
"model.safetensors: 0%| | 0.00/268M [00:00<?, ?B/s]"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Some weights of DistilBertForSequenceClassification were not initialized from the model checkpoint at distilbert-base-uncased and are newly initialized: ['classifier.bias', 'classifier.weight', 'pre_classifier.bias', 'pre_classifier.weight']\n",
|
||
"You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Batch size ajusté à 8 pour économiser la mémoire GPU.\n",
|
||
"Utilisation de : cuda\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"/tmp/ipython-input-11-3727908452.py:49: FutureWarning: `torch.cuda.amp.GradScaler(args...)` is deprecated. Please use `torch.amp.GradScaler('cuda', args...)` instead.\n",
|
||
" scaler = GradScaler()\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Début de l'entraînement...\n",
|
||
"Accumulation de gradient ajustée à 2 étapes.\n",
|
||
"\n",
|
||
"=== Epoch 1/20 ===\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Training: 100%|██████████| 8000/8000 [05:45<00:00, 23.16it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Train Loss: 0.4394, Train Accuracy: 0.8031, Train Precision: 0.8034\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Validation: 100%|██████████| 1000/1000 [01:01<00:00, 16.24it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Val Loss: 0.3890, Val Accuracy: 0.8237, Val Precision: 0.8271, Val Recall: 0.8196\n",
|
||
"New best model saved based on val_precision.\n",
|
||
"\n",
|
||
"=== Epoch 2/20 ===\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Training: 100%|██████████| 8000/8000 [05:43<00:00, 23.32it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Train Loss: 0.3690, Train Accuracy: 0.8485, Train Precision: 0.8531\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Validation: 100%|██████████| 1000/1000 [01:01<00:00, 16.31it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Val Loss: 0.4044, Val Accuracy: 0.8261, Val Precision: 0.8585, Val Recall: 0.7820\n",
|
||
"New best model saved based on val_precision.\n",
|
||
"No val_loss improvement. Patience: 1/7\n",
|
||
"\n",
|
||
"=== Epoch 3/20 ===\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Training: 100%|██████████| 8000/8000 [05:43<00:00, 23.29it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Train Loss: 0.3252, Train Accuracy: 0.8739, Train Precision: 0.8764\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Validation: 100%|██████████| 1000/1000 [01:01<00:00, 16.30it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Val Loss: 0.4862, Val Accuracy: 0.8305, Val Precision: 0.8485, Val Recall: 0.8058\n",
|
||
"No val_loss improvement. Patience: 2/7\n",
|
||
"\n",
|
||
"=== Epoch 4/20 ===\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Training: 100%|██████████| 8000/8000 [05:39<00:00, 23.53it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Train Loss: 0.2858, Train Accuracy: 0.8981, Train Precision: 0.9007\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Validation: 100%|██████████| 1000/1000 [01:01<00:00, 16.27it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Val Loss: 0.4425, Val Accuracy: 0.8290, Val Precision: 0.8427, Val Recall: 0.8101\n",
|
||
"No val_loss improvement. Patience: 3/7\n",
|
||
"\n",
|
||
"=== Epoch 5/20 ===\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Training: 100%|██████████| 8000/8000 [05:39<00:00, 23.55it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Train Loss: 0.2207, Train Accuracy: 0.9297, Train Precision: 0.9331\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Validation: 100%|██████████| 1000/1000 [01:01<00:00, 16.27it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Val Loss: 0.5597, Val Accuracy: 0.8371, Val Precision: 0.8329, Val Recall: 0.8444\n",
|
||
"No val_loss improvement. Patience: 4/7\n",
|
||
"\n",
|
||
"=== Epoch 6/20 ===\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Training: 100%|██████████| 8000/8000 [05:40<00:00, 23.52it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Train Loss: 0.1950, Train Accuracy: 0.9413, Train Precision: 0.9433\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Validation: 100%|██████████| 1000/1000 [01:01<00:00, 16.26it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Val Loss: 0.5975, Val Accuracy: 0.8342, Val Precision: 0.8513, Val Recall: 0.8109\n",
|
||
"No val_loss improvement. Patience: 5/7\n",
|
||
"\n",
|
||
"=== Epoch 7/20 ===\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Training: 100%|██████████| 8000/8000 [05:39<00:00, 23.56it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Train Loss: 0.1738, Train Accuracy: 0.9499, Train Precision: 0.9525\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Validation: 100%|██████████| 1000/1000 [01:01<00:00, 16.32it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Val Loss: 0.6491, Val Accuracy: 0.8343, Val Precision: 0.8456, Val Recall: 0.8189\n",
|
||
"No val_loss improvement. Patience: 6/7\n",
|
||
"\n",
|
||
"=== Epoch 8/20 ===\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Training: 100%|██████████| 8000/8000 [05:39<00:00, 23.58it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Train Loss: 0.1501, Train Accuracy: 0.9583, Train Precision: 0.9594\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Validation: 100%|██████████| 1000/1000 [01:01<00:00, 16.27it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Val Loss: 0.6904, Val Accuracy: 0.8323, Val Precision: 0.8382, Val Recall: 0.8247\n",
|
||
"No val_loss improvement. Patience: 7/7\n",
|
||
"EarlyStopping activated.\n",
|
||
"Best model loaded for evaluation.\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Évaluation sur le jeu de test: 100%|██████████| 1250/1250 [01:16<00:00, 16.28it/s]\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Enregistrement du modèle dans MLflow...\n",
|
||
"Model signature inferred successfully.\n",
|
||
"Model logged to MLflow artifact path 'model'.\n",
|
||
"Tokenizer logged to MLflow artifact path 'tokenizer'.\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"2025/07/12 21:16:52 WARNING mlflow.models.model: `artifact_path` is deprecated. Please use `name` instead.\n"
|
||
]
|
||
},
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Model 'distilbert-base-uncased' logged to MLflow artifact path 'model_distilbert-base-uncased'.\n",
|
||
"MLflow logging attempt finished for run 'f73e340c220c48bfa23ed135e16ab844'.\n",
|
||
"🏃 View run Model_Bert-distilbert-base-uncased at: https://mlflow.greg-madman-nas.duckdns.org/#/experiments/1/runs/f73e340c220c48bfa23ed135e16ab844\n",
|
||
"🧪 View experiment at: https://mlflow.greg-madman-nas.duckdns.org/#/experiments/1\n",
|
||
"🏃 View run Model_Bert-distilbert-base-uncased at: https://mlflow.greg-madman-nas.duckdns.org/#/experiments/1/runs/f73e340c220c48bfa23ed135e16ab844\n",
|
||
"🧪 View experiment at: https://mlflow.greg-madman-nas.duckdns.org/#/experiments/1\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"image/png": "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366IZmRk3LGPKlWqKD093ey+ly5dUkxMjAIDA+/6mf6pZs2aGj58uHbs2KHHHntMixcvtuj9AJBfkEgCyFWdO3fWI488ojZt2uinn37S6dOntXnzZvXr109nz56VJPXv318TJkzQypUrdezYMb322mtZ9oD8u3LlyikiIkLdu3fXypUrTX0uWbJEklS2bFkZDAatXr1aFy5cyPYpOhUrVlSbNm3Us2dPbdu2TQcOHNBLL72kkiVLqk2bNjn6bKdPn9bw4cMVHR2t33//XevXr9fx48eZJwngoUUiCSBXFSpUSFu3blWZMmXUvn17ValSRT169NDNmzfl4eEhSXrjjTfUpUsXRUREKDg4WIULF1a7du3u2u/s2bP13HPP6bXXXlPlypXVs2dPXbt2TZJUsmRJjRkzRsOGDZOvr6/69u2bbR/z589X7dq11bp1awUHB8toNOr777/PMpx9t8927NgxhYeH69FHH1WvXr0UGRmpV1991YJvCADyD4Pxn5u3AQAAADlARRIAAABWIZEEAACAVUgkAQAAYBUSSQAAAFiFRBIAAABWIZEEAACAVUgkAQAAYBUSSQAAAFiFRBIAAABWIZEEAACAVUgkAQAAYBUSSQAAAFjl/wCv2Whgw70JXwAAAABJRU5ErkJggg==\n",
|
||
"text/plain": [
|
||
"<Figure size 800x600 with 2 Axes>"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"image/png": "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\n",
|
||
"text/plain": [
|
||
"<Figure size 800x600 with 1 Axes>"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
},
|
||
{
|
||
"data": {
|
||
"image/png": "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+18x/gvxREdHM3z4cBITE/nwww9ZtmwZ69evz3XJWE5ODnFxccTGxvLee+/x66+/8v7771OlShWeeuqp/3Qc/2ncuHE88cQTNG7cmGeeeYa9e/dyzz334OvrS0hIyFWXve+++9iyZQv9+vUjNDSU48ePs2DBAg4ePEhoaCgjR46kX79+eHh42JMTgYGB1x3jpEmTOHPmDH369CE9PZ0PP/yQ2267jb/++su+vi1bttCkSROCg4MZOHAgpUuX5ptvvqFDhw589913dOzYMdc6e/fujb+/P4MHDyYtLY02bdqwc+dOvvrqKz744AP8/PwA8Pf3z5f4FixYwN69e4mPjycoKIgtW7YwduxYtmzZwp9//mkfQD355JPMmDGDvn37Eh4ezqlTp1i6dCnbtm2jQYMGAPz222+0adOGqKgoXnvtNRwcHJgwYQK33XYbf/zxBzExMdd9jK9m2rRpnDlzhieeeAKLxcI777zDvffey969e+3/jzZt2kSzZs1wcnLi8ccfJzQ0lD179vDDDz/w5ptvArB69WqWL19Oly5dqFChAvv37+fTTz+lZcuWbN261f5/d8iQIQwfPpzHHnuMmJgYUlNTWbNmDevWraN169ZA3t/vhIQEbr31VrKzs+39xo4di5ubW74eIxGRkmDLli00a9YMLy8vXnzxRZycnPjss89o2bIlS5YsITY2Fsjb3/FrjSHyw19//cUdd9yBv78/Q4YMITs7m9deey1PY5Fr7cMTTzzB0aNHWbBgAZMnT77hGHft2kXnzp158skn6d69OxMmTOCBBx5g3rx59mN17tw5WrRowZEjR3jiiSeoWLEiy5cvZ9CgQRw7doyRI0fmWueECRNIT0/n8ccfx8XFhY4dO3LmzBkGDx7M448/TrNmzQBo3LhxvsS3d+9eZs2axQMPPEBYWBiJiYl89tlntGjRgq1bt1K+fHnAVg7j6aef5v7776d///6kp6ezadMmVq5caR9zJyYmcsstt2CxWOjbty/+/v78/PPPPProo6SmpvLMM8/c8LG+nN27d3P//ffz6KOP0r17d8aPH0+PHj2Iioqidu3aAJw9e5ZmzZqxbds2evbsSYMGDTh58iRz5szh8OHD+Pn5kZqayhdffMGDDz5Ir169OHPmDOPGjSMuLo5Vq1bZL5nMy3eIvL7fhmHQvn17li5dypNPPkmtWrX4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y/79rFWrFlarlUOHDgHX/jt+o2OI8+fPX/LZdrV4z58/f8OfAdfah/xStWrVS06EVq9eHcA+jti1axfz5s275DOvVatWwH8b45w9ezbX8Txx4sR1x2e1Wvnggw+oVq1ars/3TZs25fp8f+mll/Dw8CAmJoZq1arRp0+fXPUwT5w4QXJyMmPHjr1kX+Pj43Pt679/D86fP5/nff6nf49x4NLx9p49e/L0XeHLL7+kXr169hpk/v7+zJ07N9cxyMt3iLy+3wcOHKBcuXJ4eHjkWl5jHLkZVFNKSqyYmBj73feu5J9nZy6wWq0EBAQwderUyy7zX88eBQQEsGHDBubPn8/PP//Mzz//zIQJE+jWrRtffvnlf1r3BTc6i6d///65YmjRokWei4lfr2eeeYZ27doxa9Ys5s+fz6uvvsrw4cP57bffqF+//k3Z5uVcmBn0/PPPX/HsZ9WqVXM9v56aQvfeey9LliyxP+/evXuei4Ne0KlTJ5YvX84LL7xAZGQkHh4eWK1W7rzzzlwzmzp16kSzZs34/vvv+eWXX3j33Xd5++23mTlzJm3atLH3fffdd694S2cPDw+WLVvGrbfemqt93759hIaGYrFYMAzjkuWulLS60u/i5dZxNf369WPChAk888wzNGrUCG9vbywWC126dMl1DJo3b86ePXuYPXs2v/zyC1988QUffPABY8aM4bHHHruh91tERArOtf6Ow42NIaZPn25PTlxwvZ9F+bkPBcVqtdK6dWtefPHFy75+IUl0wfWMcd577z2GDh1qf16pUqXrLjb/1ltv8eqrr9KzZ09ef/11fH19cXBw4Jlnnsn1+V6rVi127NjBjz/+yLx58/juu+/45JNPGDx4MEOHDrX3ffjhh69YF6levXqAbYbeP02YMIEePXpc8UqHmz3GmTJlCj169KBDhw688MILBAQE4OjoyPDhw+0nwSFv3yGu9/0WKQhKSolcpypVqvDrr7/SpEmTq34wV6lSBYDNmzdf95dYZ2dn2rVrR7t27bBarfTu3ZvPPvuMV1999bLrqlSpEgA7duyw30Xwgh07dthf/69efPFFHn74Yfvzf152daWYdu3alSumrKws9u3bR0RExDW3V6VKFZ577jmee+45du3aRWRkJO+//z5TpkwBrn4ZZF5dbur8zp077YVQL8zqcnJysp9FuhFXivX999/PdcbsQsHOvMZ3+vRpFi5cyNChQxk8ePBVlwPbQKt379707t2b48eP06BBA958803atGlj/5318vK66r5GRERcMjU8KCgIsP1OXO4y0H/P1surC8f/cndE/KcZM2bQvXt33n//fXtbenr6Ze8S4+vrS3x8PPHx8Zw9e5bmzZszZMgQHnvsset6vytVqnTZ47xjx45r7ZaIiPyDv78/7u7ul/37uX37dhwcHHLdIOVqf8cvuNYY4t/i4uLyXDrhwp1g/8tnwLX2IT/GOBdm//5zXTt37gSwjyOqVKnC2bNnb8oYp1u3bjRt2tT+/N/j5rzEN2PGDG699VbGjRuXa9nk5GT7jWMuKF26NJ07d6Zz585kZmZy77338uabbzJo0CD8/f3x9PQkJyfnmvv679+DC0XJL4x7k5OTc91A6EbHOGA7/nkZ41SuXJmZM2fmOlYXZnD/07W+Q+T1/a5UqRILFy7k7NmzuWZLaYwjN4Mu3xO5Tp06dSInJ4fXX3/9kteys7PtX4LvuOMOPD09GT58OOnp6bn6Xe0MyalTp3I9d3BwsJ+5ycjIuOwyDRs2JCAggDFjxuTq8/PPP7Nt2zbuuuuuPO3btYSHh9OqVSv7Iyoq6op9GzZsiL+/P2PGjCEzM9PePnHixGveTvbcuXOXHLMqVarg6emZa/9Kly79n29NO2vWrFw1oVatWsXKlStp06YNYDvr1LJlSz777DOOHTt2yfL/nop+JaVLlwa4JN6oqKhcxzQ8PPy64rtwFu7fv1P/vltOTk7OJZcGBgQEUL58efsxjYqKokqVKrz33nucPXv2ivtapkyZXDG3atXKXsusSpUqbN++Pddx2bhxY64p9NfD39+f5s2bM378eA4ePJjrtX/us6Oj4yXH4OOPP77k7OW//395eHhQtWpV+zG4nve7bdu2/Pnnn6xatSrX61eaRSkiIpfn6OjIHXfcwezZs3PNpElMTGTatGk0bdoULy8v4Np/x/M6hvi3cuXKXfLZdrV44+LimDVrVq7Ppm3btjF//vxr7u+19gGuPG64HkePHuX777+3P09NTWXSpElERkbaTyZ16tSJFStWXDbu5ORksrOzr7mdK8VauXLlXMezSZMm1x3f5T7fv/3220vqef77mDo7OxMeHo5hGGRlZeHo6Mh9993Hd999d9kk0D8/3//9e3Bh5tSFk3f/rLOVlpb2n65kuO+++9i4cWOu43DBhf2+3Fhv5cqVrFixIlf/vHyHyOv73bZtW7Kzs/n000/tr+fk5PDxxx9f9z6KXItmSolcpxYtWvDEE08wfPhwNmzYwB133IGTkxO7du3i22+/5cMPP+T+++/Hy8uLDz74gMcee4zo6Gi6du1KmTJl2LhxI+fOnbviB9hjjz1GUlISt912GxUqVODAgQN8/PHHREZGUqtWrcsu4+TkxNtvv018fDwtWrTgwQcfJDExkQ8//JDQ0FCeffbZm3lIrhjTG2+8wRNPPMFtt91G586d2bdvHxMmTLhmTamdO3dy++2306lTJ8LDwylVqhTff/89iYmJdOnSxd4vKiqKTz/9lDfeeIOqVasSEBBwyUyxa6latSpNmzblqaeeIiMjg5EjR1K2bNlc05pHjx5N06ZNqVu3Lr169aJy5cokJiayYsUKDh8+zMaNG6+5nQsJvJdffpkuXbrg5OREu3bt7AO5G43Py8vLXi8jKyuL4OBgfvnlF/bt25drPWfOnKFChQrcf//9RERE4OHhwa+//srq1avts4scHBz44osvaNOmDbVr1yY+Pp7g4GCOHDnCokWL8PLy4ocffrhqvD179mTEiBHExcXx6KOPcvz4ccaMGUPt2rXtRWqv10cffUTTpk1p0KABjz/+OGFhYezfv5+5c+eyYcMGAO6++24mT56Mt7c34eHhrFixgl9//ZWyZcvmWld4eDgtW7YkKioKX19f1qxZw4wZM+jbt6+9T17f7xdffJHJkydz55130r9/f0qXLs3YsWOpVKnSTakNIiJS1I0fP/6ydTL79+/PG2+8wYIFC2jatCm9e/emVKlSfPbZZ2RkZPDOO+/Y+17r73hexxD/1dChQ5k3bx7NmjWjd+/eZGdn8/HHH1O7du1rfgbk5bPowrjh6aefJi4uDkdHx+uOv3r16jz66KOsXr2awMBAxo8fT2JiIhMmTLD3eeGFF5gzZw533303PXr0ICoqirS0NP766y9mzJjB/v37L5mR9G9VqlTBx8eHMWPG4OnpSenSpYmNjb1m/am8xHf33XczbNgw4uPjady4MX/99RdTp069ZCx5xx13EBQURJMmTQgMDGTbtm2MGjWKu+66C09PTwD+7//+j0WLFhEbG0uvXr0IDw8nKSmJdevW8euvv161VuqFbVSsWJFHH32UF154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RERERBxMfW+erqKUCZbuSefnnWk4Wy2Mv7FdvW1YJiIiIiIiIiLV54+apycczOTAHzZPD6BFYy+HqEWoKFXLSspsvDRnBwDDe0bRMtjH5IhEREREREREpC46W/P0jLwi1h3MJCHxxKnm6dlnNE8P9HIlNsqf+3pHc1nzQNPiV1Gqli3YlsK+tDwCvFx5/JpWZocjIiIiIiIiIvVIkLcbAzqGMqBjKGA0T99w6IRRqDrVPP14fjELt6dyS9empsaqolQtu7FzKFaLhTK7HT9PF7PDEREREREREZF6zNvNmctbN+by1mc2T4+PDjA1NhWlapnFYuGGzqFmhyEiIiIiIiIiDdDvm6ebzWp2ACIiIiIiIiIi0vA4RFHq3XffJSoqCnd3d+Lj40lISDjv+ZMnT6ZNmzZ4eHgQERHBk08+SWFhYZVeU0REREREREREao/pRakZM2YwduxYJkyYwIYNG+jSpQv9+/cnLS3trOdPmzaNcePGMWHCBHbu3Mknn3zCjBkzeOaZZy75NUVEREREREREpHaZXpSaNGkSDz30EPfddx/t27fn/fffx9PTk6lTp571/FWrVtG7d2/uvvtuoqKiuO6667jrrrsqzYS62NcUEREREREREZHaZWpRqri4mPXr19OvX7/yY1arlX79+rF69eqzPqdXr16sX7++vAh14MAB5s2bx8CBAy/5NYuKisjJyal0ExERERERERGRmmPq7nsZGRmUlZUREhJS6XhISAi7du0663PuvvtuMjIy6NOnD3a7ndLSUh555JHy5XuX8poTJ07kxRdfrIZ3JCIiIiIiIiIiF8L05XsXa8mSJbzyyiu89957bNiwgZkzZzJ37lxeeumlS37Np59+muzs7PJbcnJyNUYsIiIiIiIiIiL/y9SZUkFBQTg5OZGamlrpeGpqKk2aNDnrc8aPH8+wYcN48MEHAejUqRP5+fk8/PDDPPvss5f0mm5ubri5uVXDOxIRERERERERkQth6kwpV1dXunfvzuLFi8uP2Ww2Fi9eTM+ePc/6nIKCAqzWymE7OTkBYLfbL+k1RURERERERESkdpk6Uwpg7NixjBgxgtjYWOLi4pg8eTL5+fncd999AAwfPpzw8HAmTpwIwKBBg5g0aRJdu3YlPj6effv2MX78eAYNGlRenPqj1xQREREREREREXOZXpQaOnQo6enpPP/8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0WaH5HBsNhtFRUVmh1HrrrnmGrZu3cqmTZvKb7Gxsdxzzz1s2rQJJycns0M0VV5eHvv37yc0NNTsUEzRu3fvM7ZD37NnD82aNTMpIsfw6aefEhwczA033GB2KHKRlC/J+Shf+mPKl5QvnY3yJeVLZ+Mo+ZKW79WisWPHMmLECGJjY4mLi2Py5Mnk5+dz3333mR2aKfLy8ipV6xMTE9m0aRMBAQFERkaaGFntGzVqFNOmTeOHH37Ax8envG+Gn58fHh4eJkdX+55++mmuv/56IiMjyc3NZdq0aSxZsoSFCxeaHVqt8/HxOaNXhpeXF4GBgQ2yh8af//xnBg0aRLNmzTh69CgTJkzAycmJu+66y+zQTPHkk0/Sq1cvXnnlFe644w4SEhL48MMP+fDDD80OzTQ2m41PP/2UESNG4OysNKcuUr5UmfKlCsqXKlO+VEH5UmXKlypTvnQmh8qXTNnzrwH797//bY+MjLS7urra4+Li7L/99pvZIZnm119/tQNn3EaMGGF2aLXubOMA2D/99FOzQzPF/fffb2/WrJnd1dXV3rhxY/s111xjX7RokdlhOYyGvMXx0KFD7aGhoXZXV1d7eHi4fejQofZ9+/aZHZapfvzxR3vHjh3tbm5u9rZt29o//PBDs0My1cKFC+2Afffu3WaHIlWgfKmC8qUKypcqU750fsqXlC/9nvKlyhwpX7LY7XZ77ZXARERERERERERE1FNKRERERERERERMoKKUiIiIiIiIiIjUOhWlRERERERERESk1qkoJSIiIiIiIiIitU5FKRERERERERERqXUqSomIiIiIiIiISK1TUUpERERERERERGqdilIiIiIiIiIiIlLrVJQSEakhFouF77//3uwwRERERByW8iWRhk1FKRGpl0aOHInFYjnjNmDAALNDExEREXEIypdExGzOZgcgIlJTBgwYwKefflrpmJubm0nRiIiIiDge5UsiYibNlBKResvNzY0mTZpUuvn7+wPGVPEpU6Zw/fXX4+HhQfPmzfn2228rPX/r1q1cffXVeHh4EBgYyMMPP0xeXl6lc6ZOnUqHDh1wc3MjNDSU0aNHV3o8IyODW265BU9PT1q1asXs2bNr9k2LiIiIXATlSyJiJhWlRKTBGj9+PEOGDGHz5s3cc8893HnnnezcuROA/Px8+vfvj7+/P2vXruWbb77h559/rpRETZkyhVGjRvHwww+zdetWZs+eTcuWLStd48UXX+SOO+5gy5YtDBw4kHvuuYfMzMxafZ8iIiIil0r5kojUKLuISD00YsQIu5OTk93Ly6vS7eWXX7bb7XY7YH/kkUcqPSc+Pt7+6KOP2u12u/3DDz+0+/v72/Py8sofnzt3rt1qtdpTUlLsdrvdHhYWZn/22WfPGQNgf+6558rv5+Xl2QH7/Pnzq+19ioiIiFwq5UsiYjb1lBKReuuqq65iypQplY4FBASU/7lnz56VHuvZsyebNm0CYOfOnXTp0gUvL6/yx3v37o3NZmP37t1YLBaOHj3KNddcc94YOnfuXP5nLy8vfH19SUtLu9S3JCIiIlKtlC+JiJlUlBKResvLy+uM6eHVxcPD44LOc3FxqXTfYrFgs9lqIiQRERGRi6Z8SUTMpJ5SItJg/fbbb2fcb9euHQDt2rVj8+bN5Ofnlz++cuVKrFYrbdq0wcfHh6ioKBYvXlyrMYuIiIjUJuVLIlKTNFNKROqtoqIiUlJSKh1zdnYmKCgIgG+++YbY2Fj69OnDl19+SUJCAp988gkA99xzDxMmTGDEiBG88MILpKenM2bMGIYNG0ZISAgAL7zwAo888gjBwcFcf/315ObmsnLlSsaMGVO7b1RERETkEilfEhEzqSglIvXWggULCA0NrXSsTZs27Nq1CzB2epk+fTqPPfYYoaGhfPXVV7Rv3x4AT09PFi5cyOOPP06PHj3w9PRkyJAhTJo0qfy1RowYQWFhIW+++SZ//vOfCQoK4rbbbqu9NygiIiJSRcqXRMRMFrvdbjc7CBGR2maxWJg1axaDBw82OxQRERERh6R8SURqmnpKiYiIiIiIiIhIrVNRSkREREREREREap2W74mIiIiIiIiISK3TTCkREREREREREal1KkqJiIiIiIiIiEitU1FKRERERERERERqnYpSIiIiIiIiIiJS61SUEhERERERERGRWqeilIiIiIiIiIiI1DoVpUREREREREREpNapKCUiIiIiIiIiIrVORSkREREREREREal1/w8MVwdoalikxwAAAABJRU5ErkJggg==\n",
|
||
"text/plain": [
|
||
"<Figure size 1200x500 with 2 Axes>"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"# Entraîner le modèle\n",
|
||
"bert_pack = train_bert_sentiment(\n",
|
||
" data_path=csv_file_path,\n",
|
||
" model_name=\"distilbert-base-uncased\",\n",
|
||
" batch_size=16,\n",
|
||
" epochs=20,\n",
|
||
" sample_size=100000\n",
|
||
")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"id": "gYK8Th3rT76h"
|
||
},
|
||
"source": [
|
||
"## Chargement du modèle"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"id": "yYPiB5A8N7l_"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# FONCTION POUR CHARGER LE MODÈLE ENTRAINÉ\n",
|
||
"def load_bert_model(model_base_dir=\"content/bert-model\"):\n",
|
||
" \"\"\"\n",
|
||
" Charge le modèle BERT entraîné, le tokenizer et le preprocessor\n",
|
||
" à partir de l'arborescence des artefacts sauvegardés.\n",
|
||
"\n",
|
||
" Args:\n",
|
||
" model_base_dir (str): Répertoire de base contenant tous les artefacts du modèle\n",
|
||
" (par défaut: \"content/bert-model\")\n",
|
||
"\n",
|
||
" Returns:\n",
|
||
" dict: Un dictionnaire contenant le modèle, le tokenizer et la fonction de prétraitement\n",
|
||
" \"\"\"\n",
|
||
" # Définir les chemins des différents artefacts\n",
|
||
" model_dir = os.path.join(model_base_dir, \"model\")\n",
|
||
" tokenizer_dir = os.path.join(model_base_dir, \"tokenizer\")\n",
|
||
" preprocessor_dir = os.path.join(model_base_dir, \"preprocessor\")\n",
|
||
" preprocessor_file = os.path.join(preprocessor_dir, \"preprocessor.pkl\")\n",
|
||
"\n",
|
||
" # Charger le modèle\n",
|
||
" try:\n",
|
||
" model = DistilBertForSequenceClassification.from_pretrained(model_dir)\n",
|
||
" print(f\"Modèle chargé avec succès depuis '{model_dir}'\")\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"Erreur lors du chargement du modèle : {e}\")\n",
|
||
" raise\n",
|
||
"\n",
|
||
" # Charger le tokenizer\n",
|
||
" try:\n",
|
||
" tokenizer = DistilBertTokenizer.from_pretrained(tokenizer_dir)\n",
|
||
" print(f\"Tokenizer chargé avec succès depuis '{tokenizer_dir}'\")\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"Erreur lors du chargement du tokenizer : {e}\")\n",
|
||
" raise\n",
|
||
"\n",
|
||
" # Charger la fonction de prétraitement\n",
|
||
" try:\n",
|
||
" with open(preprocessor_file, \"rb\") as f_in:\n",
|
||
" preprocess_tweet_for_bert = pickle.load(f_in)\n",
|
||
" print(f\"Fonction 'preprocess_tweet_for_bert' chargée avec succès depuis '{preprocessor_file}'\")\n",
|
||
" except FileNotFoundError:\n",
|
||
" print(f\"Erreur : Fichier preprocessor introuvable à l'emplacement '{preprocessor_file}'.\")\n",
|
||
" preprocess_tweet_for_bert = None\n",
|
||
" except Exception as e:\n",
|
||
" print(f\"Erreur lors du chargement de la fonction de prétraitement : {e}\")\n",
|
||
" preprocess_tweet_for_bert = None\n",
|
||
"\n",
|
||
" # Vérifier si on a bien chargé la fonction de prétraitement\n",
|
||
" if preprocess_tweet_for_bert is None:\n",
|
||
" print(\"ATTENTION: Fonction de prétraitement non chargée. Les prédictions pourraient être affectées.\")\n",
|
||
"\n",
|
||
" # Création d'un pack pour faciliter l'utilisation\n",
|
||
" model_pack = {\n",
|
||
" 'model': model,\n",
|
||
" 'tokenizer': tokenizer,\n",
|
||
" 'preprocess': preprocess_tweet_for_bert\n",
|
||
" }\n",
|
||
"\n",
|
||
" return model_pack"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"id": "tB3Uiz5pT76h"
|
||
},
|
||
"source": [
|
||
"## Fonction de prédiction"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"id": "RkFU6mWxT76h"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# FONCTION DE PRÉDICTION\n",
|
||
"def predict_sentiment(tweet, model_pack):\n",
|
||
" \"\"\"\n",
|
||
" Prédit le sentiment d'un tweet à l'aide du modèle BERT\n",
|
||
" \"\"\"\n",
|
||
" model = model_pack['model']\n",
|
||
" tokenizer = model_pack['tokenizer']\n",
|
||
" preprocess = model_pack['preprocess']\n",
|
||
"\n",
|
||
" # Prétraitement du tweet\n",
|
||
" processed_tweet = preprocess(tweet)\n",
|
||
"\n",
|
||
" # Tokenisation\n",
|
||
" encoding = tokenizer(\n",
|
||
" processed_tweet,\n",
|
||
" return_tensors=\"pt\",\n",
|
||
" truncation=True,\n",
|
||
" padding=True,\n",
|
||
" max_length=128\n",
|
||
" )\n",
|
||
"\n",
|
||
" # Détection du device\n",
|
||
" device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
|
||
" model = model.to(device)\n",
|
||
"\n",
|
||
" # Passer au mode évaluation\n",
|
||
" model.eval()\n",
|
||
"\n",
|
||
" # Déplacer les tenseurs sur le device\n",
|
||
" input_ids = encoding['input_ids'].to(device)\n",
|
||
" attention_mask = encoding['attention_mask'].to(device)\n",
|
||
"\n",
|
||
" # Prédiction\n",
|
||
" with torch.no_grad():\n",
|
||
" outputs = model(input_ids=input_ids, attention_mask=attention_mask)\n",
|
||
" logits = outputs.logits\n",
|
||
" probabilities = torch.nn.functional.softmax(logits, dim=1)\n",
|
||
"\n",
|
||
" # Récupérer le sentiment prédit et le score de confiance\n",
|
||
" predicted_class = torch.argmax(probabilities, dim=1).item()\n",
|
||
" confidence_score = probabilities[0][predicted_class].item()\n",
|
||
" raw_score = probabilities[0][1].item() # Score de la classe positive\n",
|
||
"\n",
|
||
" # Convertir en étiquette lisible\n",
|
||
" sentiment = \"Positif\" if predicted_class == 1 else \"Négatif\"\n",
|
||
"\n",
|
||
" # Résultat\n",
|
||
" result = {\n",
|
||
" 'sentiment': sentiment,\n",
|
||
" 'confidence': confidence_score,\n",
|
||
" 'raw_score': raw_score\n",
|
||
" }\n",
|
||
"\n",
|
||
" return result"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"id": "_tNu9-3tT76h"
|
||
},
|
||
"source": [
|
||
"## Test sur un ensemble de tweets"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"id": "ZFMlwStUT76h"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# FONCTION DE TEST SUR ENSEMBLE DE TWEETS\n",
|
||
"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",
|
||
" # Sauvegarder les résultats dans un fichier CSV\n",
|
||
" os.makedirs('content/bert-model', exist_ok=True)\n",
|
||
" df_predictions.to_csv(\"content/bert-model/predictions_results.csv\", index=False)\n",
|
||
"\n",
|
||
" # Retourner le DataFrame\n",
|
||
" return df_predictions"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"colab": {
|
||
"base_uri": "https://localhost:8080/"
|
||
},
|
||
"executionInfo": {
|
||
"elapsed": 1102,
|
||
"status": "ok",
|
||
"timestamp": 1752355022988,
|
||
"user": {
|
||
"displayName": "Grégoire",
|
||
"userId": "01249298206117462766"
|
||
},
|
||
"user_tz": -120
|
||
},
|
||
"id": "Tkb9WDu-T76h",
|
||
"outputId": "0f07d599-7592-4f49-a40f-eb8b22ec0359"
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Modèle chargé avec succès depuis 'content/bert-model/model'\n",
|
||
"Tokenizer chargé avec succès depuis 'content/bert-model/tokenizer'\n",
|
||
"Fonction 'preprocess_tweet_for_bert' chargée avec succès depuis 'content/bert-model/preprocessor/preprocessor.pkl'\n",
|
||
"\n",
|
||
"Test du modèle sur les exemples:\n",
|
||
"==================================================\n",
|
||
"Résumé: 15 tweets analysés\n",
|
||
"Tweets positifs: 7 (46.7%)\n",
|
||
"Tweets négatifs: 8 (53.3%)\n",
|
||
"Analyse de sentiment terminée! Résultats disponibles dans content/bert-model/predictions_results.csv\n"
|
||
]
|
||
}
|
||
],
|
||
"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 exceptional and the staff is always so friendly :) #bestairline #travel\",\n",
|
||
" \"I just landed after an amazing flight... The crew was truly fantastic and the food was delicious! Can't wait to fly with them again :D\",\n",
|
||
" \"Wow! You have to try @AirParadis. Best. Flight. Ever. Their new seats are incredibly comfortable. http://airparadis.com/newseats #travel #happy #AirParadis\",\n",
|
||
" \"It was my first time flying business class, and I’m completely blown away!!! The service is definitely worth it... @AirParadis never lets me down :)\",\n",
|
||
" \"What an incredible flight experience with @AirParadis! Everything was perfect from takeoff to landing. Would do it again in a heartbeat! #travel #satisfaction\",\n",
|
||
"\n",
|
||
" # Tweets négatifs avec différentes caractéristiques\n",
|
||
" \"Honestly, my last flight with @AirParadis was disappointing. The flight was delayed without any notice. #disappointment\",\n",
|
||
" \"I had high hopes for @AirParadis, but the seat was uncomfortable and the staff seemed overwhelmed during the flight. Not the best experience.\",\n",
|
||
" \"So frustrated with @AirParadis this time. The staff was unresponsive and it ruined our trip. #nothappy\",\n",
|
||
" \"The flight I booked with @AirParadis was canceled at the last minute. Very disappointing and no adequate communication!\",\n",
|
||
" \"The quality of service with @AirParadis has declined. I expected better. It left a sour taste. #disappointed\",\n",
|
||
"\n",
|
||
" # Tweets mixtes et nuancés\n",
|
||
" \"To be honest, @AirParadis has significantly improved their service since last year! Not perfect yet, but they are making an effort... #progress\",\n",
|
||
" \"We were really looking forward to our trip, but our flight was delayed... at least the team was very apologetic and provided us with complimentary drinks! @AirParadis\",\n",
|
||
" \"The flight with @AirParadis had great moments, but the delay somewhat tarnished the experience. I'll give them another chance!\",\n",
|
||
" \"Overall, @AirParadis has good service, but I had a few minor issues with the check-in process. It could be better! #mixedfeelings\",\n",
|
||
" \"While our flight was pleasant, the lack of communication regarding the schedule was a bit frustrating. @AirParadis can do better. #nuanced\"\n",
|
||
"]\n",
|
||
"\n",
|
||
"# Charger le modèle entraîné\n",
|
||
"model_pack = load_bert_model()\n",
|
||
"\n",
|
||
"# Tester le modèle sur les exemples\n",
|
||
"df_results = test_model_on_examples(model_pack, test_tweets_improved)\n",
|
||
"\n",
|
||
"print(\"Analyse de sentiment terminée! Résultats disponibles dans content/bert-model/predictions_results.csv\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"colab": {
|
||
"base_uri": "https://localhost:8080/",
|
||
"height": 519
|
||
},
|
||
"executionInfo": {
|
||
"elapsed": 69,
|
||
"status": "ok",
|
||
"timestamp": 1752355023061,
|
||
"user": {
|
||
"displayName": "Grégoire",
|
||
"userId": "01249298206117462766"
|
||
},
|
||
"user_tz": -120
|
||
},
|
||
"id": "XIHAcDH3E1rH",
|
||
"outputId": "9982e8d8-6530-4b66-9a4c-1ac8f158b260"
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"application/vnd.google.colaboratory.intrinsic+json": {
|
||
"summary": "{\n \"name\": \"df_results\",\n \"rows\": 15,\n \"fields\": [\n {\n \"column\": \"Tweet\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 15,\n \"samples\": [\n \"The quality of service with @AirParadis has declined. I expected better. It left a sour taste. #disappointed\",\n \"We were really looking forward to our trip, but our flight was delayed... at least the team was very apologetic and provided us with complimentary drinks! @AirParadis\",\n \"I absolutely love flying with @AirParadis! Their service is exceptional and the staff is always so friendly :) #bestairline #travel\"\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.14419873334810537,\n \"min\": 0.5295969843864441,\n \"max\": 0.9885379076004028,\n \"num_unique_values\": 15,\n \"samples\": [\n 0.9871659874916077,\n 0.5295969843864441\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Score brut\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.4223161774401945,\n \"min\": 0.011462084017693996,\n \"max\": 0.9652082920074463,\n \"num_unique_values\": 15,\n \"samples\": [\n 0.012833991087973118,\n 0.4704030156135559\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Index\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 4,\n \"min\": 1,\n \"max\": 15,\n \"num_unique_values\": 15,\n \"samples\": [\n 10,\n 12\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}",
|
||
"type": "dataframe",
|
||
"variable_name": "df_results"
|
||
},
|
||
"text/html": [
|
||
"\n",
|
||
" <div id=\"df-c9131374-544c-4203-8f76-5641fc25fa68\" class=\"colab-df-container\">\n",
|
||
" <div>\n",
|
||
"<style scoped>\n",
|
||
" .dataframe tbody tr th:only-of-type {\n",
|
||
" vertical-align: middle;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe tbody tr th {\n",
|
||
" vertical-align: top;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe thead th {\n",
|
||
" text-align: right;\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"<table border=\"1\" class=\"dataframe\">\n",
|
||
" <thead>\n",
|
||
" <tr style=\"text-align: right;\">\n",
|
||
" <th></th>\n",
|
||
" <th>Tweet</th>\n",
|
||
" <th>Sentiment</th>\n",
|
||
" <th>Emoji</th>\n",
|
||
" <th>Score de confiance</th>\n",
|
||
" <th>Score brut</th>\n",
|
||
" <th>Index</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <th>0</th>\n",
|
||
" <td>I absolutely love flying with @AirParadis! The...</td>\n",
|
||
" <td>Positif</td>\n",
|
||
" <td>💚</td>\n",
|
||
" <td>0.941539</td>\n",
|
||
" <td>0.941539</td>\n",
|
||
" <td>1</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>1</th>\n",
|
||
" <td>I just landed after an amazing flight... The c...</td>\n",
|
||
" <td>Positif</td>\n",
|
||
" <td>💚</td>\n",
|
||
" <td>0.949552</td>\n",
|
||
" <td>0.949552</td>\n",
|
||
" <td>2</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>2</th>\n",
|
||
" <td>Wow! You have to try @AirParadis. Best. Flight...</td>\n",
|
||
" <td>Positif</td>\n",
|
||
" <td>💚</td>\n",
|
||
" <td>0.960181</td>\n",
|
||
" <td>0.960181</td>\n",
|
||
" <td>3</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>3</th>\n",
|
||
" <td>It was my first time flying business class, an...</td>\n",
|
||
" <td>Négatif</td>\n",
|
||
" <td>❌</td>\n",
|
||
" <td>0.950030</td>\n",
|
||
" <td>0.049970</td>\n",
|
||
" <td>4</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>4</th>\n",
|
||
" <td>What an incredible flight experience with @Air...</td>\n",
|
||
" <td>Positif</td>\n",
|
||
" <td>💚</td>\n",
|
||
" <td>0.965208</td>\n",
|
||
" <td>0.965208</td>\n",
|
||
" <td>5</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>5</th>\n",
|
||
" <td>Honestly, my last flight with @AirParadis was ...</td>\n",
|
||
" <td>Négatif</td>\n",
|
||
" <td>❌</td>\n",
|
||
" <td>0.987460</td>\n",
|
||
" <td>0.012539</td>\n",
|
||
" <td>6</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>6</th>\n",
|
||
" <td>I had high hopes for @AirParadis, but the seat...</td>\n",
|
||
" <td>Négatif</td>\n",
|
||
" <td>❌</td>\n",
|
||
" <td>0.984469</td>\n",
|
||
" <td>0.015531</td>\n",
|
||
" <td>7</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>7</th>\n",
|
||
" <td>So frustrated with @AirParadis this time. The ...</td>\n",
|
||
" <td>Négatif</td>\n",
|
||
" <td>❌</td>\n",
|
||
" <td>0.975684</td>\n",
|
||
" <td>0.024316</td>\n",
|
||
" <td>8</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>8</th>\n",
|
||
" <td>The flight I booked with @AirParadis was cance...</td>\n",
|
||
" <td>Négatif</td>\n",
|
||
" <td>❌</td>\n",
|
||
" <td>0.988538</td>\n",
|
||
" <td>0.011462</td>\n",
|
||
" <td>9</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>9</th>\n",
|
||
" <td>The quality of service with @AirParadis has de...</td>\n",
|
||
" <td>Négatif</td>\n",
|
||
" <td>❌</td>\n",
|
||
" <td>0.987166</td>\n",
|
||
" <td>0.012834</td>\n",
|
||
" <td>10</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>10</th>\n",
|
||
" <td>To be honest, @AirParadis has significantly im...</td>\n",
|
||
" <td>Positif</td>\n",
|
||
" <td>💚</td>\n",
|
||
" <td>0.908642</td>\n",
|
||
" <td>0.908642</td>\n",
|
||
" <td>11</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>11</th>\n",
|
||
" <td>We were really looking forward to our trip, bu...</td>\n",
|
||
" <td>Négatif</td>\n",
|
||
" <td>❌</td>\n",
|
||
" <td>0.529597</td>\n",
|
||
" <td>0.470403</td>\n",
|
||
" <td>12</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>12</th>\n",
|
||
" <td>The flight with @AirParadis had great moments,...</td>\n",
|
||
" <td>Négatif</td>\n",
|
||
" <td>❌</td>\n",
|
||
" <td>0.682678</td>\n",
|
||
" <td>0.317322</td>\n",
|
||
" <td>13</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>13</th>\n",
|
||
" <td>Overall, @AirParadis has good service, but I h...</td>\n",
|
||
" <td>Positif</td>\n",
|
||
" <td>💚</td>\n",
|
||
" <td>0.712999</td>\n",
|
||
" <td>0.712999</td>\n",
|
||
" <td>14</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>14</th>\n",
|
||
" <td>While our flight was pleasant, the lack of com...</td>\n",
|
||
" <td>Positif</td>\n",
|
||
" <td>💚</td>\n",
|
||
" <td>0.742626</td>\n",
|
||
" <td>0.742626</td>\n",
|
||
" <td>15</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"</div>\n",
|
||
" <div class=\"colab-df-buttons\">\n",
|
||
"\n",
|
||
" <div class=\"colab-df-container\">\n",
|
||
" <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-c9131374-544c-4203-8f76-5641fc25fa68')\"\n",
|
||
" title=\"Convert this dataframe to an interactive table.\"\n",
|
||
" style=\"display:none;\">\n",
|
||
"\n",
|
||
" <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\">\n",
|
||
" <path d=\"M120-120v-720h720v720H120Zm60-500h600v-160H180v160Zm220 220h160v-160H400v160Zm0 220h160v-160H400v160ZM180-400h160v-160H180v160Zm440 0h160v-160H620v160ZM180-180h160v-160H180v160Zm440 0h160v-160H620v160Z\"/>\n",
|
||
" </svg>\n",
|
||
" </button>\n",
|
||
"\n",
|
||
" <style>\n",
|
||
" .colab-df-container {\n",
|
||
" display:flex;\n",
|
||
" gap: 12px;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .colab-df-convert {\n",
|
||
" background-color: #E8F0FE;\n",
|
||
" border: none;\n",
|
||
" border-radius: 50%;\n",
|
||
" cursor: pointer;\n",
|
||
" display: none;\n",
|
||
" fill: #1967D2;\n",
|
||
" height: 32px;\n",
|
||
" padding: 0 0 0 0;\n",
|
||
" width: 32px;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .colab-df-convert:hover {\n",
|
||
" background-color: #E2EBFA;\n",
|
||
" box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
|
||
" fill: #174EA6;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .colab-df-buttons div {\n",
|
||
" margin-bottom: 4px;\n",
|
||
" }\n",
|
||
"\n",
|
||
" [theme=dark] .colab-df-convert {\n",
|
||
" background-color: #3B4455;\n",
|
||
" fill: #D2E3FC;\n",
|
||
" }\n",
|
||
"\n",
|
||
" [theme=dark] .colab-df-convert:hover {\n",
|
||
" background-color: #434B5C;\n",
|
||
" box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
|
||
" filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
|
||
" fill: #FFFFFF;\n",
|
||
" }\n",
|
||
" </style>\n",
|
||
"\n",
|
||
" <script>\n",
|
||
" const buttonEl =\n",
|
||
" document.querySelector('#df-c9131374-544c-4203-8f76-5641fc25fa68 button.colab-df-convert');\n",
|
||
" buttonEl.style.display =\n",
|
||
" google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
|
||
"\n",
|
||
" async function convertToInteractive(key) {\n",
|
||
" const element = document.querySelector('#df-c9131374-544c-4203-8f76-5641fc25fa68');\n",
|
||
" const dataTable =\n",
|
||
" await google.colab.kernel.invokeFunction('convertToInteractive',\n",
|
||
" [key], {});\n",
|
||
" if (!dataTable) return;\n",
|
||
"\n",
|
||
" const docLinkHtml = 'Like what you see? Visit the ' +\n",
|
||
" '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
|
||
" + ' to learn more about interactive tables.';\n",
|
||
" element.innerHTML = '';\n",
|
||
" dataTable['output_type'] = 'display_data';\n",
|
||
" await google.colab.output.renderOutput(dataTable, element);\n",
|
||
" const docLink = document.createElement('div');\n",
|
||
" docLink.innerHTML = docLinkHtml;\n",
|
||
" element.appendChild(docLink);\n",
|
||
" }\n",
|
||
" </script>\n",
|
||
" </div>\n",
|
||
"\n",
|
||
"\n",
|
||
" <div id=\"df-6ae068c6-134c-47c5-8d5b-f1acdf173a7a\">\n",
|
||
" <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-6ae068c6-134c-47c5-8d5b-f1acdf173a7a')\"\n",
|
||
" title=\"Suggest charts\"\n",
|
||
" style=\"display:none;\">\n",
|
||
"\n",
|
||
"<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
|
||
" width=\"24px\">\n",
|
||
" <g>\n",
|
||
" <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
|
||
" </g>\n",
|
||
"</svg>\n",
|
||
" </button>\n",
|
||
"\n",
|
||
"<style>\n",
|
||
" .colab-df-quickchart {\n",
|
||
" --bg-color: #E8F0FE;\n",
|
||
" --fill-color: #1967D2;\n",
|
||
" --hover-bg-color: #E2EBFA;\n",
|
||
" --hover-fill-color: #174EA6;\n",
|
||
" --disabled-fill-color: #AAA;\n",
|
||
" --disabled-bg-color: #DDD;\n",
|
||
" }\n",
|
||
"\n",
|
||
" [theme=dark] .colab-df-quickchart {\n",
|
||
" --bg-color: #3B4455;\n",
|
||
" --fill-color: #D2E3FC;\n",
|
||
" --hover-bg-color: #434B5C;\n",
|
||
" --hover-fill-color: #FFFFFF;\n",
|
||
" --disabled-bg-color: #3B4455;\n",
|
||
" --disabled-fill-color: #666;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .colab-df-quickchart {\n",
|
||
" background-color: var(--bg-color);\n",
|
||
" border: none;\n",
|
||
" border-radius: 50%;\n",
|
||
" cursor: pointer;\n",
|
||
" display: none;\n",
|
||
" fill: var(--fill-color);\n",
|
||
" height: 32px;\n",
|
||
" padding: 0;\n",
|
||
" width: 32px;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .colab-df-quickchart:hover {\n",
|
||
" background-color: var(--hover-bg-color);\n",
|
||
" box-shadow: 0 1px 2px rgba(60, 64, 67, 0.3), 0 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
|
||
" fill: var(--button-hover-fill-color);\n",
|
||
" }\n",
|
||
"\n",
|
||
" .colab-df-quickchart-complete:disabled,\n",
|
||
" .colab-df-quickchart-complete:disabled:hover {\n",
|
||
" background-color: var(--disabled-bg-color);\n",
|
||
" fill: var(--disabled-fill-color);\n",
|
||
" box-shadow: none;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .colab-df-spinner {\n",
|
||
" border: 2px solid var(--fill-color);\n",
|
||
" border-color: transparent;\n",
|
||
" border-bottom-color: var(--fill-color);\n",
|
||
" animation:\n",
|
||
" spin 1s steps(1) infinite;\n",
|
||
" }\n",
|
||
"\n",
|
||
" @keyframes spin {\n",
|
||
" 0% {\n",
|
||
" border-color: transparent;\n",
|
||
" border-bottom-color: var(--fill-color);\n",
|
||
" border-left-color: var(--fill-color);\n",
|
||
" }\n",
|
||
" 20% {\n",
|
||
" border-color: transparent;\n",
|
||
" border-left-color: var(--fill-color);\n",
|
||
" border-top-color: var(--fill-color);\n",
|
||
" }\n",
|
||
" 30% {\n",
|
||
" border-color: transparent;\n",
|
||
" border-left-color: var(--fill-color);\n",
|
||
" border-top-color: var(--fill-color);\n",
|
||
" border-right-color: var(--fill-color);\n",
|
||
" }\n",
|
||
" 40% {\n",
|
||
" border-color: transparent;\n",
|
||
" border-right-color: var(--fill-color);\n",
|
||
" border-top-color: var(--fill-color);\n",
|
||
" }\n",
|
||
" 60% {\n",
|
||
" border-color: transparent;\n",
|
||
" border-right-color: var(--fill-color);\n",
|
||
" }\n",
|
||
" 80% {\n",
|
||
" border-color: transparent;\n",
|
||
" border-right-color: var(--fill-color);\n",
|
||
" border-bottom-color: var(--fill-color);\n",
|
||
" }\n",
|
||
" 90% {\n",
|
||
" border-color: transparent;\n",
|
||
" border-bottom-color: var(--fill-color);\n",
|
||
" }\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"\n",
|
||
" <script>\n",
|
||
" async function quickchart(key) {\n",
|
||
" const quickchartButtonEl =\n",
|
||
" document.querySelector('#' + key + ' button');\n",
|
||
" quickchartButtonEl.disabled = true; // To prevent multiple clicks.\n",
|
||
" quickchartButtonEl.classList.add('colab-df-spinner');\n",
|
||
" try {\n",
|
||
" const charts = await google.colab.kernel.invokeFunction(\n",
|
||
" 'suggestCharts', [key], {});\n",
|
||
" } catch (error) {\n",
|
||
" console.error('Error during call to suggestCharts:', error);\n",
|
||
" }\n",
|
||
" quickchartButtonEl.classList.remove('colab-df-spinner');\n",
|
||
" quickchartButtonEl.classList.add('colab-df-quickchart-complete');\n",
|
||
" }\n",
|
||
" (() => {\n",
|
||
" let quickchartButtonEl =\n",
|
||
" document.querySelector('#df-6ae068c6-134c-47c5-8d5b-f1acdf173a7a button');\n",
|
||
" quickchartButtonEl.style.display =\n",
|
||
" google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
|
||
" })();\n",
|
||
" </script>\n",
|
||
" </div>\n",
|
||
"\n",
|
||
" <div id=\"id_802ea4e3-49a6-46a2-b84f-7e23171d454d\">\n",
|
||
" <style>\n",
|
||
" .colab-df-generate {\n",
|
||
" background-color: #E8F0FE;\n",
|
||
" border: none;\n",
|
||
" border-radius: 50%;\n",
|
||
" cursor: pointer;\n",
|
||
" display: none;\n",
|
||
" fill: #1967D2;\n",
|
||
" height: 32px;\n",
|
||
" padding: 0 0 0 0;\n",
|
||
" width: 32px;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .colab-df-generate:hover {\n",
|
||
" background-color: #E2EBFA;\n",
|
||
" box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
|
||
" fill: #174EA6;\n",
|
||
" }\n",
|
||
"\n",
|
||
" [theme=dark] .colab-df-generate {\n",
|
||
" background-color: #3B4455;\n",
|
||
" fill: #D2E3FC;\n",
|
||
" }\n",
|
||
"\n",
|
||
" [theme=dark] .colab-df-generate:hover {\n",
|
||
" background-color: #434B5C;\n",
|
||
" box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
|
||
" filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
|
||
" fill: #FFFFFF;\n",
|
||
" }\n",
|
||
" </style>\n",
|
||
" <button class=\"colab-df-generate\" onclick=\"generateWithVariable('df_results')\"\n",
|
||
" title=\"Generate code using this dataframe.\"\n",
|
||
" style=\"display:none;\">\n",
|
||
"\n",
|
||
" <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
|
||
" width=\"24px\">\n",
|
||
" <path d=\"M7,19H8.4L18.45,9,17,7.55,7,17.6ZM5,21V16.75L18.45,3.32a2,2,0,0,1,2.83,0l1.4,1.43a1.91,1.91,0,0,1,.58,1.4,1.91,1.91,0,0,1-.58,1.4L9.25,21ZM18.45,9,17,7.55Zm-12,3A5.31,5.31,0,0,0,4.9,8.1,5.31,5.31,0,0,0,1,6.5,5.31,5.31,0,0,0,4.9,4.9,5.31,5.31,0,0,0,6.5,1,5.31,5.31,0,0,0,8.1,4.9,5.31,5.31,0,0,0,12,6.5,5.46,5.46,0,0,0,6.5,12Z\"/>\n",
|
||
" </svg>\n",
|
||
" </button>\n",
|
||
" <script>\n",
|
||
" (() => {\n",
|
||
" const buttonEl =\n",
|
||
" document.querySelector('#id_802ea4e3-49a6-46a2-b84f-7e23171d454d button.colab-df-generate');\n",
|
||
" buttonEl.style.display =\n",
|
||
" google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
|
||
"\n",
|
||
" buttonEl.onclick = () => {\n",
|
||
" google.colab.notebook.generateWithVariable('df_results');\n",
|
||
" }\n",
|
||
" })();\n",
|
||
" </script>\n",
|
||
" </div>\n",
|
||
"\n",
|
||
" </div>\n",
|
||
" </div>\n"
|
||
],
|
||
"text/plain": [
|
||
" Tweet Sentiment Emoji \\\n",
|
||
"0 I absolutely love flying with @AirParadis! The... Positif 💚 \n",
|
||
"1 I just landed after an amazing flight... The c... Positif 💚 \n",
|
||
"2 Wow! You have to try @AirParadis. Best. Flight... Positif 💚 \n",
|
||
"3 It was my first time flying business class, an... Négatif ❌ \n",
|
||
"4 What an incredible flight experience with @Air... Positif 💚 \n",
|
||
"5 Honestly, my last flight with @AirParadis was ... Négatif ❌ \n",
|
||
"6 I had high hopes for @AirParadis, but the seat... Négatif ❌ \n",
|
||
"7 So frustrated with @AirParadis this time. The ... Négatif ❌ \n",
|
||
"8 The flight I booked with @AirParadis was cance... Négatif ❌ \n",
|
||
"9 The quality of service with @AirParadis has de... Négatif ❌ \n",
|
||
"10 To be honest, @AirParadis has significantly im... Positif 💚 \n",
|
||
"11 We were really looking forward to our trip, bu... Négatif ❌ \n",
|
||
"12 The flight with @AirParadis had great moments,... Négatif ❌ \n",
|
||
"13 Overall, @AirParadis has good service, but I h... Positif 💚 \n",
|
||
"14 While our flight was pleasant, the lack of com... Positif 💚 \n",
|
||
"\n",
|
||
" Score de confiance Score brut Index \n",
|
||
"0 0.941539 0.941539 1 \n",
|
||
"1 0.949552 0.949552 2 \n",
|
||
"2 0.960181 0.960181 3 \n",
|
||
"3 0.950030 0.049970 4 \n",
|
||
"4 0.965208 0.965208 5 \n",
|
||
"5 0.987460 0.012539 6 \n",
|
||
"6 0.984469 0.015531 7 \n",
|
||
"7 0.975684 0.024316 8 \n",
|
||
"8 0.988538 0.011462 9 \n",
|
||
"9 0.987166 0.012834 10 \n",
|
||
"10 0.908642 0.908642 11 \n",
|
||
"11 0.529597 0.470403 12 \n",
|
||
"12 0.682678 0.317322 13 \n",
|
||
"13 0.712999 0.712999 14 \n",
|
||
"14 0.742626 0.742626 15 "
|
||
]
|
||
},
|
||
"execution_count": 24,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"df_results"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"colab": {
|
||
"base_uri": "https://localhost:8080/",
|
||
"height": 536
|
||
},
|
||
"executionInfo": {
|
||
"elapsed": 607,
|
||
"status": "ok",
|
||
"timestamp": 1752355023660,
|
||
"user": {
|
||
"displayName": "Grégoire",
|
||
"userId": "01249298206117462766"
|
||
},
|
||
"user_tz": -120
|
||
},
|
||
"id": "-mJxfVLiGfTL",
|
||
"outputId": "94c492a5-6077-461e-90a8-45097869c7d6"
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Modèle chargé avec succès depuis 'content/bert-model/model'\n",
|
||
"Tokenizer chargé avec succès depuis 'content/bert-model/tokenizer'\n",
|
||
"Fonction 'preprocess_tweet_for_bert' chargée avec succès depuis 'content/bert-model/preprocessor/preprocessor.pkl'\n",
|
||
"\n",
|
||
"Test du modèle sur les exemples:\n",
|
||
"==================================================\n",
|
||
"Résumé: 10 tweets analysés\n",
|
||
"Tweets positifs: 5 (50.0%)\n",
|
||
"Tweets négatifs: 5 (50.0%)\n",
|
||
"Analyse de sentiment terminée! Vérifiez si les résultats sont dans content/bert-model/predictions_results.csv\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"application/vnd.google.colaboratory.intrinsic+json": {
|
||
"summary": "{\n \"name\": \"df_results\",\n \"rows\": 10,\n \"fields\": [\n {\n \"column\": \"Tweet\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 10,\n \"samples\": [\n \"@AirParadis let me down. Flight canceled for no valid reason, no solution offered. Zero service. I'm disgusted. \\ud83d\\ude24 #Abandoned\",\n \"PERFECT flight with @AirParadis today. Amazing staff, clean plane, arrived early. What more could you ask for? \\u2b50\\u2b50\\u2b50\\u2b50\\u2b50 #HappyCustomer\",\n \"AVOID @AirParadis! The worst customer service I've ever seen. Rude, incompetent, and they lost my luggage! An absolute disgrace. \\ud83d\\ude20 #AirlineToAvoid\"\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.10672469983360551,\n \"min\": 0.6343077421188354,\n \"max\": 0.9860053062438965,\n \"num_unique_values\": 10,\n \"samples\": [\n 0.9860053062438965,\n 0.9353708624839783\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Score brut\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0.46612804191093277,\n \"min\": 0.01399463601410389,\n \"max\": 0.9763770699501038,\n \"num_unique_values\": 10,\n \"samples\": [\n 0.01399463601410389,\n 0.9353708624839783\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Index\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 3,\n \"min\": 1,\n \"max\": 10,\n \"num_unique_values\": 10,\n \"samples\": [\n 9,\n 2\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}",
|
||
"type": "dataframe",
|
||
"variable_name": "df_results"
|
||
},
|
||
"text/html": [
|
||
"\n",
|
||
" <div id=\"df-18e21748-f52d-45cf-8fa3-b7253024aa72\" class=\"colab-df-container\">\n",
|
||
" <div>\n",
|
||
"<style scoped>\n",
|
||
" .dataframe tbody tr th:only-of-type {\n",
|
||
" vertical-align: middle;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe tbody tr th {\n",
|
||
" vertical-align: top;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe thead th {\n",
|
||
" text-align: right;\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"<table border=\"1\" class=\"dataframe\">\n",
|
||
" <thead>\n",
|
||
" <tr style=\"text-align: right;\">\n",
|
||
" <th></th>\n",
|
||
" <th>Tweet</th>\n",
|
||
" <th>Sentiment</th>\n",
|
||
" <th>Emoji</th>\n",
|
||
" <th>Score de confiance</th>\n",
|
||
" <th>Score brut</th>\n",
|
||
" <th>Index</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <th>0</th>\n",
|
||
" <td>@AirParadis offers absolutely FLAWLESS service...</td>\n",
|
||
" <td>Positif</td>\n",
|
||
" <td>💚</td>\n",
|
||
" <td>0.964295</td>\n",
|
||
" <td>0.964295</td>\n",
|
||
" <td>1</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>1</th>\n",
|
||
" <td>PERFECT flight with @AirParadis today. Amazing...</td>\n",
|
||
" <td>Positif</td>\n",
|
||
" <td>💚</td>\n",
|
||
" <td>0.935371</td>\n",
|
||
" <td>0.935371</td>\n",
|
||
" <td>2</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>2</th>\n",
|
||
" <td>I'm totally a fan of @AirParadis! Every flight...</td>\n",
|
||
" <td>Positif</td>\n",
|
||
" <td>💚</td>\n",
|
||
" <td>0.976377</td>\n",
|
||
" <td>0.976377</td>\n",
|
||
" <td>3</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>3</th>\n",
|
||
" <td>Extraordinary experience in business class on ...</td>\n",
|
||
" <td>Positif</td>\n",
|
||
" <td>💚</td>\n",
|
||
" <td>0.969083</td>\n",
|
||
" <td>0.969083</td>\n",
|
||
" <td>4</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>4</th>\n",
|
||
" <td>@AirParadis saved my vacation! After a cancell...</td>\n",
|
||
" <td>Positif</td>\n",
|
||
" <td>💚</td>\n",
|
||
" <td>0.911861</td>\n",
|
||
" <td>0.911861</td>\n",
|
||
" <td>5</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>5</th>\n",
|
||
" <td>AVOID @AirParadis! The worst customer service ...</td>\n",
|
||
" <td>Négatif</td>\n",
|
||
" <td>❌</td>\n",
|
||
" <td>0.978022</td>\n",
|
||
" <td>0.021978</td>\n",
|
||
" <td>6</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>6</th>\n",
|
||
" <td>DISASTROUS flight with @AirParadis. 5-hour del...</td>\n",
|
||
" <td>Négatif</td>\n",
|
||
" <td>❌</td>\n",
|
||
" <td>0.976990</td>\n",
|
||
" <td>0.023010</td>\n",
|
||
" <td>7</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>7</th>\n",
|
||
" <td>How can @AirParadis dare to charge for seats t...</td>\n",
|
||
" <td>Négatif</td>\n",
|
||
" <td>❌</td>\n",
|
||
" <td>0.977153</td>\n",
|
||
" <td>0.022847</td>\n",
|
||
" <td>8</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>8</th>\n",
|
||
" <td>@AirParadis let me down. Flight canceled for n...</td>\n",
|
||
" <td>Négatif</td>\n",
|
||
" <td>❌</td>\n",
|
||
" <td>0.986005</td>\n",
|
||
" <td>0.013995</td>\n",
|
||
" <td>9</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>9</th>\n",
|
||
" <td>The food served on @AirParadis was simply ined...</td>\n",
|
||
" <td>Négatif</td>\n",
|
||
" <td>❌</td>\n",
|
||
" <td>0.634308</td>\n",
|
||
" <td>0.365692</td>\n",
|
||
" <td>10</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"</div>\n",
|
||
" <div class=\"colab-df-buttons\">\n",
|
||
"\n",
|
||
" <div class=\"colab-df-container\">\n",
|
||
" <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-18e21748-f52d-45cf-8fa3-b7253024aa72')\"\n",
|
||
" title=\"Convert this dataframe to an interactive table.\"\n",
|
||
" style=\"display:none;\">\n",
|
||
"\n",
|
||
" <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\">\n",
|
||
" <path d=\"M120-120v-720h720v720H120Zm60-500h600v-160H180v160Zm220 220h160v-160H400v160Zm0 220h160v-160H400v160ZM180-400h160v-160H180v160Zm440 0h160v-160H620v160ZM180-180h160v-160H180v160Zm440 0h160v-160H620v160Z\"/>\n",
|
||
" </svg>\n",
|
||
" </button>\n",
|
||
"\n",
|
||
" <style>\n",
|
||
" .colab-df-container {\n",
|
||
" display:flex;\n",
|
||
" gap: 12px;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .colab-df-convert {\n",
|
||
" background-color: #E8F0FE;\n",
|
||
" border: none;\n",
|
||
" border-radius: 50%;\n",
|
||
" cursor: pointer;\n",
|
||
" display: none;\n",
|
||
" fill: #1967D2;\n",
|
||
" height: 32px;\n",
|
||
" padding: 0 0 0 0;\n",
|
||
" width: 32px;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .colab-df-convert:hover {\n",
|
||
" background-color: #E2EBFA;\n",
|
||
" box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
|
||
" fill: #174EA6;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .colab-df-buttons div {\n",
|
||
" margin-bottom: 4px;\n",
|
||
" }\n",
|
||
"\n",
|
||
" [theme=dark] .colab-df-convert {\n",
|
||
" background-color: #3B4455;\n",
|
||
" fill: #D2E3FC;\n",
|
||
" }\n",
|
||
"\n",
|
||
" [theme=dark] .colab-df-convert:hover {\n",
|
||
" background-color: #434B5C;\n",
|
||
" box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
|
||
" filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
|
||
" fill: #FFFFFF;\n",
|
||
" }\n",
|
||
" </style>\n",
|
||
"\n",
|
||
" <script>\n",
|
||
" const buttonEl =\n",
|
||
" document.querySelector('#df-18e21748-f52d-45cf-8fa3-b7253024aa72 button.colab-df-convert');\n",
|
||
" buttonEl.style.display =\n",
|
||
" google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
|
||
"\n",
|
||
" async function convertToInteractive(key) {\n",
|
||
" const element = document.querySelector('#df-18e21748-f52d-45cf-8fa3-b7253024aa72');\n",
|
||
" const dataTable =\n",
|
||
" await google.colab.kernel.invokeFunction('convertToInteractive',\n",
|
||
" [key], {});\n",
|
||
" if (!dataTable) return;\n",
|
||
"\n",
|
||
" const docLinkHtml = 'Like what you see? Visit the ' +\n",
|
||
" '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
|
||
" + ' to learn more about interactive tables.';\n",
|
||
" element.innerHTML = '';\n",
|
||
" dataTable['output_type'] = 'display_data';\n",
|
||
" await google.colab.output.renderOutput(dataTable, element);\n",
|
||
" const docLink = document.createElement('div');\n",
|
||
" docLink.innerHTML = docLinkHtml;\n",
|
||
" element.appendChild(docLink);\n",
|
||
" }\n",
|
||
" </script>\n",
|
||
" </div>\n",
|
||
"\n",
|
||
"\n",
|
||
" <div id=\"df-32ea5292-bebe-4ded-8930-5c4d2cebf7e8\">\n",
|
||
" <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-32ea5292-bebe-4ded-8930-5c4d2cebf7e8')\"\n",
|
||
" title=\"Suggest charts\"\n",
|
||
" style=\"display:none;\">\n",
|
||
"\n",
|
||
"<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
|
||
" width=\"24px\">\n",
|
||
" <g>\n",
|
||
" <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
|
||
" </g>\n",
|
||
"</svg>\n",
|
||
" </button>\n",
|
||
"\n",
|
||
"<style>\n",
|
||
" .colab-df-quickchart {\n",
|
||
" --bg-color: #E8F0FE;\n",
|
||
" --fill-color: #1967D2;\n",
|
||
" --hover-bg-color: #E2EBFA;\n",
|
||
" --hover-fill-color: #174EA6;\n",
|
||
" --disabled-fill-color: #AAA;\n",
|
||
" --disabled-bg-color: #DDD;\n",
|
||
" }\n",
|
||
"\n",
|
||
" [theme=dark] .colab-df-quickchart {\n",
|
||
" --bg-color: #3B4455;\n",
|
||
" --fill-color: #D2E3FC;\n",
|
||
" --hover-bg-color: #434B5C;\n",
|
||
" --hover-fill-color: #FFFFFF;\n",
|
||
" --disabled-bg-color: #3B4455;\n",
|
||
" --disabled-fill-color: #666;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .colab-df-quickchart {\n",
|
||
" background-color: var(--bg-color);\n",
|
||
" border: none;\n",
|
||
" border-radius: 50%;\n",
|
||
" cursor: pointer;\n",
|
||
" display: none;\n",
|
||
" fill: var(--fill-color);\n",
|
||
" height: 32px;\n",
|
||
" padding: 0;\n",
|
||
" width: 32px;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .colab-df-quickchart:hover {\n",
|
||
" background-color: var(--hover-bg-color);\n",
|
||
" box-shadow: 0 1px 2px rgba(60, 64, 67, 0.3), 0 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
|
||
" fill: var(--button-hover-fill-color);\n",
|
||
" }\n",
|
||
"\n",
|
||
" .colab-df-quickchart-complete:disabled,\n",
|
||
" .colab-df-quickchart-complete:disabled:hover {\n",
|
||
" background-color: var(--disabled-bg-color);\n",
|
||
" fill: var(--disabled-fill-color);\n",
|
||
" box-shadow: none;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .colab-df-spinner {\n",
|
||
" border: 2px solid var(--fill-color);\n",
|
||
" border-color: transparent;\n",
|
||
" border-bottom-color: var(--fill-color);\n",
|
||
" animation:\n",
|
||
" spin 1s steps(1) infinite;\n",
|
||
" }\n",
|
||
"\n",
|
||
" @keyframes spin {\n",
|
||
" 0% {\n",
|
||
" border-color: transparent;\n",
|
||
" border-bottom-color: var(--fill-color);\n",
|
||
" border-left-color: var(--fill-color);\n",
|
||
" }\n",
|
||
" 20% {\n",
|
||
" border-color: transparent;\n",
|
||
" border-left-color: var(--fill-color);\n",
|
||
" border-top-color: var(--fill-color);\n",
|
||
" }\n",
|
||
" 30% {\n",
|
||
" border-color: transparent;\n",
|
||
" border-left-color: var(--fill-color);\n",
|
||
" border-top-color: var(--fill-color);\n",
|
||
" border-right-color: var(--fill-color);\n",
|
||
" }\n",
|
||
" 40% {\n",
|
||
" border-color: transparent;\n",
|
||
" border-right-color: var(--fill-color);\n",
|
||
" border-top-color: var(--fill-color);\n",
|
||
" }\n",
|
||
" 60% {\n",
|
||
" border-color: transparent;\n",
|
||
" border-right-color: var(--fill-color);\n",
|
||
" }\n",
|
||
" 80% {\n",
|
||
" border-color: transparent;\n",
|
||
" border-right-color: var(--fill-color);\n",
|
||
" border-bottom-color: var(--fill-color);\n",
|
||
" }\n",
|
||
" 90% {\n",
|
||
" border-color: transparent;\n",
|
||
" border-bottom-color: var(--fill-color);\n",
|
||
" }\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"\n",
|
||
" <script>\n",
|
||
" async function quickchart(key) {\n",
|
||
" const quickchartButtonEl =\n",
|
||
" document.querySelector('#' + key + ' button');\n",
|
||
" quickchartButtonEl.disabled = true; // To prevent multiple clicks.\n",
|
||
" quickchartButtonEl.classList.add('colab-df-spinner');\n",
|
||
" try {\n",
|
||
" const charts = await google.colab.kernel.invokeFunction(\n",
|
||
" 'suggestCharts', [key], {});\n",
|
||
" } catch (error) {\n",
|
||
" console.error('Error during call to suggestCharts:', error);\n",
|
||
" }\n",
|
||
" quickchartButtonEl.classList.remove('colab-df-spinner');\n",
|
||
" quickchartButtonEl.classList.add('colab-df-quickchart-complete');\n",
|
||
" }\n",
|
||
" (() => {\n",
|
||
" let quickchartButtonEl =\n",
|
||
" document.querySelector('#df-32ea5292-bebe-4ded-8930-5c4d2cebf7e8 button');\n",
|
||
" quickchartButtonEl.style.display =\n",
|
||
" google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
|
||
" })();\n",
|
||
" </script>\n",
|
||
" </div>\n",
|
||
"\n",
|
||
" <div id=\"id_0803b4a1-59be-4dbd-9a24-5f2b33a34300\">\n",
|
||
" <style>\n",
|
||
" .colab-df-generate {\n",
|
||
" background-color: #E8F0FE;\n",
|
||
" border: none;\n",
|
||
" border-radius: 50%;\n",
|
||
" cursor: pointer;\n",
|
||
" display: none;\n",
|
||
" fill: #1967D2;\n",
|
||
" height: 32px;\n",
|
||
" padding: 0 0 0 0;\n",
|
||
" width: 32px;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .colab-df-generate:hover {\n",
|
||
" background-color: #E2EBFA;\n",
|
||
" box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
|
||
" fill: #174EA6;\n",
|
||
" }\n",
|
||
"\n",
|
||
" [theme=dark] .colab-df-generate {\n",
|
||
" background-color: #3B4455;\n",
|
||
" fill: #D2E3FC;\n",
|
||
" }\n",
|
||
"\n",
|
||
" [theme=dark] .colab-df-generate:hover {\n",
|
||
" background-color: #434B5C;\n",
|
||
" box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
|
||
" filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
|
||
" fill: #FFFFFF;\n",
|
||
" }\n",
|
||
" </style>\n",
|
||
" <button class=\"colab-df-generate\" onclick=\"generateWithVariable('df_results')\"\n",
|
||
" title=\"Generate code using this dataframe.\"\n",
|
||
" style=\"display:none;\">\n",
|
||
"\n",
|
||
" <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
|
||
" width=\"24px\">\n",
|
||
" <path d=\"M7,19H8.4L18.45,9,17,7.55,7,17.6ZM5,21V16.75L18.45,3.32a2,2,0,0,1,2.83,0l1.4,1.43a1.91,1.91,0,0,1,.58,1.4,1.91,1.91,0,0,1-.58,1.4L9.25,21ZM18.45,9,17,7.55Zm-12,3A5.31,5.31,0,0,0,4.9,8.1,5.31,5.31,0,0,0,1,6.5,5.31,5.31,0,0,0,4.9,4.9,5.31,5.31,0,0,0,6.5,1,5.31,5.31,0,0,0,8.1,4.9,5.31,5.31,0,0,0,12,6.5,5.46,5.46,0,0,0,6.5,12Z\"/>\n",
|
||
" </svg>\n",
|
||
" </button>\n",
|
||
" <script>\n",
|
||
" (() => {\n",
|
||
" const buttonEl =\n",
|
||
" document.querySelector('#id_0803b4a1-59be-4dbd-9a24-5f2b33a34300 button.colab-df-generate');\n",
|
||
" buttonEl.style.display =\n",
|
||
" google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
|
||
"\n",
|
||
" buttonEl.onclick = () => {\n",
|
||
" google.colab.notebook.generateWithVariable('df_results');\n",
|
||
" }\n",
|
||
" })();\n",
|
||
" </script>\n",
|
||
" </div>\n",
|
||
"\n",
|
||
" </div>\n",
|
||
" </div>\n"
|
||
],
|
||
"text/plain": [
|
||
" Tweet Sentiment Emoji \\\n",
|
||
"0 @AirParadis offers absolutely FLAWLESS service... Positif 💚 \n",
|
||
"1 PERFECT flight with @AirParadis today. Amazing... Positif 💚 \n",
|
||
"2 I'm totally a fan of @AirParadis! Every flight... Positif 💚 \n",
|
||
"3 Extraordinary experience in business class on ... Positif 💚 \n",
|
||
"4 @AirParadis saved my vacation! After a cancell... Positif 💚 \n",
|
||
"5 AVOID @AirParadis! The worst customer service ... Négatif ❌ \n",
|
||
"6 DISASTROUS flight with @AirParadis. 5-hour del... Négatif ❌ \n",
|
||
"7 How can @AirParadis dare to charge for seats t... Négatif ❌ \n",
|
||
"8 @AirParadis let me down. Flight canceled for n... Négatif ❌ \n",
|
||
"9 The food served on @AirParadis was simply ined... Négatif ❌ \n",
|
||
"\n",
|
||
" Score de confiance Score brut Index \n",
|
||
"0 0.964295 0.964295 1 \n",
|
||
"1 0.935371 0.935371 2 \n",
|
||
"2 0.976377 0.976377 3 \n",
|
||
"3 0.969083 0.969083 4 \n",
|
||
"4 0.911861 0.911861 5 \n",
|
||
"5 0.978022 0.021978 6 \n",
|
||
"6 0.976990 0.023010 7 \n",
|
||
"7 0.977153 0.022847 8 \n",
|
||
"8 0.986005 0.013995 9 \n",
|
||
"9 0.634308 0.365692 10 "
|
||
]
|
||
},
|
||
"execution_count": 25,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"# Liste améliorée de tweets pour tester le modèle\n",
|
||
"unambiguous_tweets = [\n",
|
||
" # --- Strongly Positive ---\n",
|
||
" \"@AirParadis offers absolutely FLAWLESS service! Best airline, period. I recommend it 1000%! 😍 #DreamTrip\",\n",
|
||
" \"PERFECT flight with @AirParadis today. Amazing staff, clean plane, arrived early. What more could you ask for? ⭐⭐⭐⭐⭐ #HappyCustomer\",\n",
|
||
" \"I'm totally a fan of @AirParadis! Every flight is a pleasure. Comfort, kindness, punctuality... they have it all! Thank you! 😊✈️\",\n",
|
||
" \"Extraordinary experience in business class on @AirParadis. Worth every penny. Luxury and attention to detail. WELL DONE! 👏 #LuxuryTravel\",\n",
|
||
" \"@AirParadis saved my vacation! After a cancellation with another airline, they immediately found me a seat. Top-notch customer service! 🙏 #Saved\",\n",
|
||
"\n",
|
||
" # --- Strongly Negative ---\n",
|
||
" \"AVOID @AirParadis! The worst customer service I've ever seen. Rude, incompetent, and they lost my luggage! An absolute disgrace. 😠 #AirlineToAvoid\",\n",
|
||
" \"DISASTROUS flight with @AirParadis. 5-hour delay, no information, unfriendly staff. NEVER flying with them again. 🤬 #TripRuined\",\n",
|
||
" \"How can @AirParadis dare to charge for seats that are so dirty and uncomfortable? It's outright theft. Horrible airline. 👎 #Scam\",\n",
|
||
" \"@AirParadis let me down. Flight canceled for no valid reason, no solution offered. Zero service. I'm disgusted. 😤 #Abandoned\",\n",
|
||
" \"The food served on @AirParadis was simply inedible. Cold, tasteless... I've never eaten anything so bad on a flight. 🤢 #AirplaneFood\"\n",
|
||
"]\n",
|
||
"\n",
|
||
"# Charger le modèle entraîné\n",
|
||
"# Assurez-vous que la fonction load_bert_model est définie et fonctionnelle\n",
|
||
"model_pack = load_bert_model()\n",
|
||
"\n",
|
||
"# Tester le modèle sur les exemples\n",
|
||
"# Assurez-vous que la fonction test_model_on_examples est définie,\n",
|
||
"# prend le model_pack et la liste de tweets, et renvoie un DataFrame\n",
|
||
"df_results = test_model_on_examples(model_pack, unambiguous_tweets)\n",
|
||
"\n",
|
||
"# Afficher un message indiquant où trouver les résultats (si sauvegardés par la fonction)\n",
|
||
"print(\"Analyse de sentiment terminée! Vérifiez si les résultats sont dans content/bert-model/predictions_results.csv\")\n",
|
||
"\n",
|
||
"# Optionnel : Afficher les premières lignes du DataFrame résultant\n",
|
||
"df_results"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {
|
||
"id": "hkxoyNm_t6YG"
|
||
},
|
||
"source": [
|
||
"# Enregistrement de dépendances"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"id": "HjaFxsm3t9eP"
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!pip freeze > requirements_bert.txt"
|
||
]
|
||
}
|
||
],
|
||
"metadata": {
|
||
"accelerator": "GPU",
|
||
"colab": {
|
||
"gpuType": "T4",
|
||
"provenance": []
|
||
},
|
||
"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"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 0
|
||
}
|