{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "cf479cb3" }, "source": [ "# 🤗 Fine-Tuning de Transformers\n", "\n", "Comparamos modelos de lenguaje pre-entrenados (Transformers) fine-tuneados\n", "en nuestro dataset contra el modelo LR+TF-IDF que ya teníamos.\n", "\n", "Los modelos como DistilBERT o RoBERTa ya fueron entrenados en **millones de páginas**\n", "de internet. Ya 'saben' inglés. Nosotros solo tenemos que enseñarles a distinguir\n", "comentarios tóxicos de los que no lo son — y para eso, 700 muestras son suficientes.\n", "\n", "Es la diferencia entre contratar a un experto en inglés y enseñarle hate speech\n", "(Transformer) vs enseñar hate speech a alguien que no sabe inglés (TF-IDF).\n", "\n", "### Modelos que comparamos\n", "\n", "| # | Modelo | Tipo | Especialización |\n", "|---|---|---|---|\n", "| 1 | **LR + TF-IDF** | Referencia | Entrenado por nosotros |\n", "| 2 | **DistilBERT base** | Transformer general | Ninguna — aprende de cero nuestra tarea |\n", "| 3 | **toxic-comment-model** | DistilBERT especializado | Ya fine-tuneado en toxicidad |\n", "| 4 | **RoBERTa Hate** | RoBERTa especializado | Ya fine-tuneado en hate speech de Twitter |\n", "\n", "Los modelos 3 y 4 ya saben detectar toxicidad — solo los adaptamos a nuestro dominio.\n", "\n", "### ¿Qué es zero-shot?\n", "Evaluamos los modelos especializados (3 y 4) **sin ningún fine-tuning** para ver\n", "cuánto saben ya. Esto nos da la referencia mínima antes de entrenar.\n", "\n", "### Output\n", "- Tabla comparativa completa: LR vs 3 transformers\n", "- Modelo ganador guardado en `models/finetuned_hf/` (listo para Streamlit)\n", "- Experimento registrado en MLflow" ] }, { "cell_type": "markdown", "metadata": { "id": "9af8d5ef" }, "source": [ "## 0. Imports y configuración\n", "\n", "Instalación necesaria (ejecutar una sola vez en tu entorno):\n", "```bash\n", "pip install transformers datasets accelerate torch sentencepiece\n", "```" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "id": "6724909b" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/under/miniconda3/envs/py310/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", " from .autonotebook import tqdm as notebook_tqdm\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "=======================================================\n", "Torch version : 2.12.0+cu132\n", "Device : cuda\n", "GPU : NVIDIA GeForce RTX 2060\n", "VRAM : 6.4 GB\n", "=======================================================\n" ] } ], "source": [ "import os\n", "import sys\n", "import yaml\n", "import json\n", "import joblib\n", "import random\n", "import warnings\n", "import numpy as np\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "import torch\n", "import mlflow\n", "import mlflow.pytorch\n", "\n", "from pathlib import Path\n", "from datasets import Dataset\n", "from sklearn.model_selection import train_test_split\n", "from sklearn.metrics import (\n", " classification_report, confusion_matrix,\n", " f1_score, precision_score, recall_score,\n", " accuracy_score, roc_auc_score,\n", ")\n", "from transformers import (\n", " AutoTokenizer, AutoModelForSequenceClassification,\n", " DataCollatorWithPadding, TrainingArguments,\n", " Trainer, EarlyStoppingCallback, pipeline,\n", ")\n", "\n", "warnings.filterwarnings('ignore')\n", "\n", "PROJECT_ROOT = Path.cwd().parent\n", "sys.path.insert(0, str(PROJECT_ROOT))\n", "\n", "# Cargar config\n", "with open(PROJECT_ROOT / 'configs' / 'pipeline.yaml') as f:\n", " pipe_cfg = yaml.safe_load(f)\n", "\n", "TARGET = pipe_cfg['data']['target_binary']\n", "RAND = pipe_cfg['pipeline']['random_state']\n", "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n", "\n", "print('=' * 55)\n", "print(f'Torch version : {torch.__version__}')\n", "print(f'Device : {device}')\n", "if torch.cuda.is_available():\n", " print(f'GPU : {torch.cuda.get_device_name(0)}')\n", " print(f'VRAM : {torch.cuda.get_device_properties(0).total_memory / 1e9:.1f} GB')\n", "else:\n", " print('GPU : No detectada — el entrenamiento será más lento')\n", "print('=' * 55)" ] }, { "cell_type": "markdown", "metadata": { "id": "e5a223a1" }, "source": [ "## 1. Reproducibilidad\n", "\n", "### ¿Por qué es importante?\n", "Los modelos de deep learning tienen inicialización aleatoria de pesos.\n", "Si no fijamos la semilla, el mismo código puede dar resultados distintos en\n", "cada ejecución, haciendo imposible comparar experimentos de forma justa.\n", "\n", "Fijamos la semilla en 4 lugares:\n", "- `random` → shuffle de datos en Python\n", "- `numpy` → operaciones numéricas\n", "- `torch` → la red neuronal\n", "- `cuda` → operaciones en GPU" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "id": "e067a346" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Semilla fijada: 42\n" ] } ], "source": [ "def set_seed(seed: int = 42):\n", " random.seed(seed)\n", " np.random.seed(seed)\n", " torch.manual_seed(seed)\n", " if torch.cuda.is_available():\n", " torch.cuda.manual_seed_all(seed)\n", " torch.backends.cudnn.deterministic = True\n", " torch.backends.cudnn.benchmark = False\n", "\n", "set_seed(RAND)\n", "print(f'Semilla fijada: {RAND}')" ] }, { "cell_type": "markdown", "metadata": { "id": "135efbba" }, "source": [ "## 2. Carga de datos\n", "\n", "### ¡IMPORTANTE! Usamos `Text` crudo, NO `clean_text`\n", "\n", "En los notebooks anteriores preprocesamos el texto (stopwords, lematización).\n", "Para transformers eso es **contraproducente**:\n", "\n", "- DistilBERT y RoBERTa tienen su propio tokenizador interno\n", "- Entienden contexto: 'running' y 'run' significan cosas distintas según la frase\n", "- Lematizar destruye información que los modelos de atención pueden aprovechar\n", "- Eliminar stopwords como 'not' puede cambiar el sentido de 'not toxic' → 'toxic'\n", "\n", "**Regla:** sklearn necesita texto limpio. Transformers necesitan texto crudo." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "id": "b1bdccf5" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Dataset: (1000, 9)\n", "Columna texto: Text\n", "Toxicos: 462 (46.2%)\n", "\n", "Muestra de texto crudo (lo que ven los transformers):\n", " → You call yourself an anarchist but defend a cop shooting an unarmed civilian. I'm highly disappointe\n", " → My mother told me the same thing.  God Bless this woman.\n", " → Love it I same the saem thing Go Peggy! #stupid  \n", "Ya Killing ya selves more quicker than  STLPD cou\n" ] } ], "source": [ "DATA_PATH = PROJECT_ROOT / 'data' / 'processed' / 'v2' / 'comments_preprocessed.csv'\n", "\n", "df = pd.read_csv(DATA_PATH)\n", "\n", "# Usamos Text (crudo), no clean_text\n", "TEXT_COL = 'Text'\n", "df[TEXT_COL] = df[TEXT_COL].fillna('').astype(str).str.strip()\n", "df = df[df[TEXT_COL] != ''].copy()\n", "df[TARGET] = df[TARGET].astype(int)\n", "\n", "print(f'Dataset: {df.shape}')\n", "print(f'Columna texto: {TEXT_COL}')\n", "print(f'Toxicos: {df[TARGET].sum()} ({df[TARGET].mean()*100:.1f}%)')\n", "print()\n", "print('Muestra de texto crudo (lo que ven los transformers):')\n", "for t in df[TEXT_COL].sample(3, random_state=42):\n", " print(f' → {t[:100]}')" ] }, { "cell_type": "markdown", "metadata": { "id": "134e3c1f" }, "source": [ "## 3. Split train / validation / test\n", "\n", "### ¿Por qué 3 conjuntos en vez de 2+CV?\n", "\n", "En los notebooks de sklearn usamos **StratifiedKFold** porque entrenar\n", "Logistic Regression 5 veces tarda segundos.\n", "\n", "Con transformers, **una sola epoch** puede tardar 2-5 minutos.\n", "Hacer 5-fold CV significaría 15+ epochs de entrenamiento por modelo — inviable.\n", "\n", "La solución es el split de 3 vías:\n", "```\n", "TOTAL (1000)\n", "├── TRAIN (700) → el modelo aprende aquí\n", "├── VALIDATION (150) → EarlyStoppingCallback mira esto para no sobreajustar\n", "└── TEST (150) → evaluación final, se toca UNA sola vez\n", "```\n", "\n", "El validation set hace el trabajo que hacía el CV: detecta cuándo el modelo\n", "empieza a memorizar en vez de aprender." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "id": "f727c42b" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "SPLITS\n", " Train : 699 (70%)\n", " Validation: 151 (15%)\n", " Test : 150 (15%)\n", "\n", "Toxicos en cada split:\n", " Train: 323 / 699 (46.2%)\n", " Val: 70 / 151 (46.4%)\n", " Test: 69 / 150 (46.0%)\n" ] } ], "source": [ "X = df[TEXT_COL]\n", "y = df[TARGET]\n", "\n", "# Separar test final (15%)\n", "X_temp, X_test, y_temp, y_test = train_test_split(\n", " X, y, test_size=0.15, stratify=y, random_state=RAND\n", ")\n", "\n", "# Separar validation del train restante\n", "# 0.1765 del 85% ≈ 15% del total\n", "X_train, X_valid, y_train, y_valid = train_test_split(\n", " X_temp, y_temp, test_size=0.1765, stratify=y_temp, random_state=RAND\n", ")\n", "\n", "print('SPLITS')\n", "print(f' Train : {len(X_train):>4} ({len(X_train)/len(X)*100:.0f}%)')\n", "print(f' Validation: {len(X_valid):>4} ({len(X_valid)/len(X)*100:.0f}%)')\n", "print(f' Test : {len(X_test):>4} ({len(X_test)/len(X)*100:.0f}%)')\n", "print()\n", "print('Toxicos en cada split:')\n", "for name, yy in [('Train', y_train), ('Val', y_valid), ('Test', y_test)]:\n", " print(f' {name}: {yy.sum()} / {len(yy)} ({yy.mean()*100:.1f}%)')" ] }, { "cell_type": "markdown", "metadata": { "id": "19d8abe9" }, "source": [ "## 4. Referencia — LR + TF-IDF\n", "\n", "Cargamos el modelo del notebook 06 y lo evaluamos sobre el **mismo test set**\n", "para tener una comparación justa.\n", "\n", "**Atención:** el LR fue entrenado con `clean_text`, no con `Text`.\n", "Aquí aplicamos el preprocesador de scikit-learn que viene embebido en el pipeline." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "id": "09ee2e07" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Modelo LR cargado: final_model.joblib\n", "LR F1=0.6944 | ROC-AUC=0.7794\n", "LR FP=15 | FN=30\n" ] } ], "source": [ "# Cargar el pipeline sklearn completo (incluye TF-IDF + LR)\n", "lr_path = PROJECT_ROOT / 'models' / 'final_model.joblib'\n", "\n", "if lr_path.exists():\n", " lr_pipeline = joblib.load(lr_path)\n", " print(f'Modelo LR cargado: {lr_path.name}')\n", "\n", " # El pipeline sklearn usa clean_text internamente\n", " # Lo evaluamos sobre el texto crudo — el preprocesador está dentro\n", " # Si el modelo fue guardado con texto ya limpio, cargar el preprocessor\n", " try:\n", " from src.features.text_preprocessor import TextPreprocessor\n", " prep = TextPreprocessor(\n", " config_path=str(PROJECT_ROOT / 'configs' / 'features.yaml')\n", " )\n", " X_test_clean = prep.transform(X_test)\n", " lr_preds = lr_pipeline.predict(X_test_clean)\n", " lr_probs = lr_pipeline.predict_proba(X_test_clean)[:, 1]\n", " except Exception:\n", " # Fallback: el pipeline ya maneja el texto crudo\n", " lr_preds = lr_pipeline.predict(X_test)\n", " lr_probs = lr_pipeline.predict_proba(X_test)[:, 1]\n", "\n", " lr_ref = {\n", " 'f1' : f1_score(y_test, lr_preds, average='weighted'),\n", " 'precision': precision_score(y_test, lr_preds, average='weighted'),\n", " 'recall' : recall_score(y_test, lr_preds, average='weighted'),\n", " 'roc_auc' : roc_auc_score(y_test, lr_probs),\n", " 'fp' : int(((y_test==0)&(lr_preds==1)).sum()),\n", " 'fn' : int(((y_test==1)&(lr_preds==0)).sum()),\n", " }\n", " print(f\"LR F1={lr_ref['f1']:.4f} | ROC-AUC={lr_ref['roc_auc']:.4f}\")\n", " print(f\"LR FP={lr_ref['fp']} | FN={lr_ref['fn']}\")\n", "else:\n", " print('Modelo LR no encontrado. Ejecuta el notebook 06 primero.')\n", " lr_ref = None" ] }, { "cell_type": "markdown", "metadata": { "id": "8c6042e6" }, "source": [ "## 5. Funciones auxiliares\n", "\n", "Creamos funciones reutilizables para no repetir código en cada modelo.\n", "El patrón es siempre el mismo:\n", "1. Convertir pandas DataFrame a HuggingFace Dataset\n", "2. Tokenizar (convertir texto a números)\n", "3. Entrenar con Trainer\n", "4. Evaluar y comparar" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "id": "4349c7fa" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Funciones auxiliares definidas\n" ] } ], "source": [ "# ── Dataset ──────────────────────────────────────────────────────────────\n", "def build_hf_dataset(X, y) -> Dataset:\n", " \"\"\"\n", " Convierte pandas Series a HuggingFace Dataset.\n", " HuggingFace Dataset es el formato que acepta el Trainer.\n", " \"\"\"\n", " return Dataset.from_pandas(pd.DataFrame({\n", " 'text' : X.values,\n", " 'label': y.astype(int).values,\n", " }))\n", "\n", "# ── Tokenización ─────────────────────────────────────────────────────────\n", "def tokenize_dataset(dataset: Dataset, tokenizer, max_len: int = 128) -> Dataset:\n", " \"\"\"\n", " Tokeniza el texto: convierte palabras a IDs numéricos que el modelo entiende.\n", "\n", " Ejemplo: 'you are stupid' → [101, 2017, 2024, 5236, 102]\n", " donde 101=[CLS] y 102=[SEP] son tokens especiales de BERT.\n", "\n", " max_len=128: comentarios de YouTube son cortos, 128 tokens es suficiente.\n", " truncation=True: si un comentario es más largo, lo cortamos.\n", " \"\"\"\n", " def _tokenize(batch):\n", " return tokenizer(batch['text'], truncation=True, max_length=max_len)\n", "\n", " dataset = dataset.map(_tokenize, batched=True)\n", " dataset = dataset.remove_columns(['text'])\n", " dataset.set_format('torch')\n", " return dataset\n", "\n", "# ── Métricas ─────────────────────────────────────────────────────────────\n", "def compute_metrics(eval_pred):\n", " \"\"\"\n", " El Trainer llama a esta función al final de cada epoch de validación.\n", " Usamos F1 de la clase tóxica como métrica principal para:\n", " 1. Elegir el mejor epoch (metric_for_best_model)\n", " 2. Activar early stopping cuando deja de mejorar\n", " \"\"\"\n", " logits, labels = eval_pred\n", " # logits: puntuaciones crudas del modelo → softmax → probabilidades\n", " probs = torch.softmax(torch.tensor(logits), dim=1)[:, 1].numpy()\n", " preds = np.argmax(logits, axis=1)\n", " return {\n", " 'f1_toxic' : f1_score(labels, preds, pos_label=1),\n", " 'f1_weighted': f1_score(labels, preds, average='weighted'),\n", " 'precision' : precision_score(labels, preds, pos_label=1, zero_division=0),\n", " 'recall' : recall_score(labels, preds, pos_label=1, zero_division=0),\n", " 'roc_auc' : roc_auc_score(labels, probs),\n", " }\n", "\n", "# ── Evaluación final ─────────────────────────────────────────────────────\n", "def evaluate_on_test(trainer, hf_test, y_test_arr, model_name: str) -> dict:\n", " \"\"\"\n", " Evaluación final sobre el test set.\n", " Solo se llama UNA vez, después de que el modelo ya está entrenado.\n", " \"\"\"\n", " output = trainer.predict(hf_test)\n", " probs = torch.softmax(torch.tensor(output.predictions), dim=1)[:, 1].numpy()\n", " preds = np.argmax(output.predictions, axis=1)\n", "\n", " print(f'\\n{\"=\"*55}')\n", " print(f'{model_name}')\n", " print(f'{\"=\"*55}')\n", " print(classification_report(\n", " y_test_arr, preds,\n", " target_names=['No tóxico', 'Tóxico']\n", " ))\n", "\n", " # Matriz de confusión\n", " fig, ax = plt.subplots(figsize=(5, 4))\n", " sns.heatmap(\n", " confusion_matrix(y_test_arr, preds),\n", " annot=True, fmt='d', cmap='Blues', ax=ax,\n", " xticklabels=['No tóxico','Tóxico'],\n", " yticklabels=['No tóxico','Tóxico'],\n", " )\n", " ax.set_title(f'{model_name} — Confusion Matrix')\n", " ax.set_xlabel('Predicción'); ax.set_ylabel('Real')\n", " plt.tight_layout()\n", " safe_name = model_name.lower().replace(' ','_').replace('/','_')\n", " plt.savefig(\n", " PROJECT_ROOT / 'reports' / 'v2' / f'nb08_{safe_name}_cm.png',\n", " dpi=150, bbox_inches='tight'\n", " )\n", " plt.show()\n", "\n", " return {\n", " 'model' : model_name,\n", " 'f1' : round(f1_score(y_test_arr, preds, average='weighted'), 4),\n", " 'f1_toxic' : round(f1_score(y_test_arr, preds, pos_label=1), 4),\n", " 'precision': round(precision_score(y_test_arr, preds, average='weighted'), 4),\n", " 'recall' : round(recall_score(y_test_arr, preds, average='weighted'), 4),\n", " 'roc_auc' : round(roc_auc_score(y_test_arr, probs), 4),\n", " 'fp' : int(((y_test_arr==0)&(preds==1)).sum()),\n", " 'fn' : int(((y_test_arr==1)&(preds==0)).sum()),\n", " 'preds' : preds,\n", " 'probs' : probs,\n", " }\n", "\n", "print('Funciones auxiliares definidas')" ] }, { "cell_type": "markdown", "metadata": { "id": "48bc309c" }, "source": [ "## 6. Función de fine-tuning\n", "\n", "Encapsulamos todo el proceso de entrenamiento en una función reutilizable.\n", "Así no repetimos código para cada modelo." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "id": "52595391" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Función fine_tune definida\n" ] } ], "source": [ "def fine_tune(\n", " model_id: str,\n", " hf_train, hf_valid, hf_test,\n", " y_test_arr,\n", " model_name: str,\n", " output_dir: Path,\n", " freeze_backbone: bool = False,\n", " unfreeze_last_n: int = 0, # ← AÑADIR\n", " epochs: int = 5,\n", " lr: float = 2e-5,\n", " batch_size: int = 8,\n", " max_len: int = 128,\n", ") -> dict:\n", " \"\"\"\n", " Entrena (fine-tune) un modelo de HuggingFace y lo evalúa.\n", "\n", " Parámetros:\n", " model_id : nombre del modelo en HuggingFace Hub\n", " freeze_backbone: Si True, congela el encoder — solo entrena la cabeza\n", " clasificadora. Recomendado para modelos ya especializados\n", " o cuando el dataset es muy pequeño.\n", " epochs : máximo de epochs (early stopping puede parar antes)\n", " lr : tasa de aprendizaje. 2e-5 es el estándar para BERT\n", " batch_size : muestras por paso. Más pequeño = más updates, más robusto\n", " \"\"\"\n", " print(f'\\nCargando {model_id}...')\n", " set_seed(RAND)\n", "\n", " # Tokenizador\n", " tokenizer = AutoTokenizer.from_pretrained(model_id)\n", "\n", " # Tokenizar datasets\n", " tok_train = tokenize_dataset(hf_train, tokenizer, max_len)\n", " tok_valid = tokenize_dataset(hf_valid, tokenizer, max_len)\n", " tok_test = tokenize_dataset(hf_test, tokenizer, max_len)\n", "\n", " # Modelo de clasificación binaria (num_labels=2: no tóxico / tóxico)\n", " model = AutoModelForSequenceClassification.from_pretrained(\n", " model_id, num_labels=2, ignore_mismatched_sizes=True\n", " )\n", " model.to(device)\n", "\n", " # ── Congelar el backbone (opcional) ──────────────────────────────────\n", " if freeze_backbone:\n", "\n", " # Paso 1: congelar TODOS los parámetros del encoder\n", " for param in model.base_model.parameters():\n", " param.requires_grad = False\n", "\n", " # Paso 2: descongelar las últimas N capas transformer (si se pide)\n", " # Funciona con DistilBERT (6 capas) y RoBERTa (12 capas)\n", " if unfreeze_last_n > 0:\n", " layers = None\n", " # Detecta automáticamente la arquitectura del modelo\n", " for attr_path in ['transformer.layer', 'encoder.layer']:\n", " try:\n", " obj = model.base_model\n", " for part in attr_path.split('.'):\n", " obj = getattr(obj, part)\n", " layers = list(obj)\n", " break\n", " except AttributeError:\n", " continue\n", "\n", " if layers:\n", " for layer in layers[-unfreeze_last_n:]:\n", " for param in layer.parameters():\n", " param.requires_grad = True\n", " print(f' Últimas {unfreeze_last_n}/{len(layers)} capas descongeladas')\n", " else:\n", " print(' ⚠️ No se encontraron capas — solo cabeza entrenará')\n", "\n", " # Paso 3: siempre descongelar la cabeza clasificadora\n", " for name, param in model.named_parameters():\n", " if 'classifier' in name or 'pre_classifier' in name:\n", " param.requires_grad = True\n", "\n", " trainable = sum(p.numel() for p in model.parameters() if p.requires_grad)\n", " total = sum(p.numel() for p in model.parameters())\n", " print(f' Entrenando {trainable:,}/{total:,} params ({trainable/total*100:.1f}%)')\n", "\n", " else:\n", " trainable = sum(p.numel() for p in model.parameters() if p.requires_grad)\n", " print(f' Full fine-tuning — {trainable:,} params')\n", "\n", " # ── TrainingArguments ────────────────────────────────────────────────\n", " args = TrainingArguments(\n", " output_dir = str(output_dir),\n", " learning_rate = lr,\n", " num_train_epochs = epochs,\n", " per_device_train_batch_size = batch_size,\n", " per_device_eval_batch_size = batch_size,\n", " weight_decay = 0.01, # Regularización L2 en los pesos\n", " eval_strategy = 'epoch', # Evaluar al final de cada epoch\n", " save_strategy = 'epoch',\n", " load_best_model_at_end = True, # Al terminar, cargar el mejor checkpoint\n", " metric_for_best_model = 'f1_toxic',# Optimizar F1 de la clase tóxica\n", " greater_is_better = True,\n", " warmup_ratio = 0.1, # 10% primeros pasos con LR creciente\n", " logging_steps = 20,\n", " fp16 = torch.cuda.is_available(),\n", " report_to = 'none',\n", " seed = RAND,\n", " )\n", "\n", " # ── Trainer ──────────────────────────────────────────────────────────\n", " trainer = Trainer(\n", " model = model,\n", " args = args,\n", " train_dataset = tok_train,\n", " eval_dataset = tok_valid,\n", " data_collator = DataCollatorWithPadding(tokenizer),\n", " compute_metrics = compute_metrics,\n", " callbacks = [EarlyStoppingCallback(early_stopping_patience=2)],\n", " )\n", "\n", " # ── Entrenamiento ────────────────────────────────────────────────────\n", " print(f' Entrenando (max {epochs} epochs, early stopping patience=2)...')\n", " trainer.train()\n", "\n", " # ── Evaluación en test ───────────────────────────────────────────────\n", " results = evaluate_on_test(trainer, tok_test, y_test_arr, model_name)\n", " results['trainer'] = trainer\n", " results['tokenizer'] = tokenizer\n", "\n", " return results\n", "\n", "print('Función fine_tune definida')" ] }, { "cell_type": "markdown", "metadata": { "id": "698c2d19" }, "source": [ "## 7. Crear HuggingFace Datasets\n", "\n", "Convertimos los pandas DataFrames al formato que usa la librería `transformers`." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "id": "09b7138c" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Train dataset : Dataset({\n", " features: ['text', 'label'],\n", " num_rows: 699\n", "})\n", "Valid dataset : Dataset({\n", " features: ['text', 'label'],\n", " num_rows: 151\n", "})\n", "Test dataset : Dataset({\n", " features: ['text', 'label'],\n", " num_rows: 150\n", "})\n" ] } ], "source": [ "hf_train_raw = build_hf_dataset(X_train, y_train)\n", "hf_valid_raw = build_hf_dataset(X_valid, y_valid)\n", "hf_test_raw = build_hf_dataset(X_test, y_test)\n", "\n", "print(f'Train dataset : {hf_train_raw}')\n", "print(f'Valid dataset : {hf_valid_raw}')\n", "print(f'Test dataset : {hf_test_raw}')" ] }, { "cell_type": "markdown", "metadata": { "id": "514de245" }, "source": [ "## 8. Evaluación zero-shot (sin fine-tuning)\n", "\n", "### ¿Qué es zero-shot?\n", "Evaluamos los modelos pre-especializados tal como están, **sin ningún entrenamiento**\n", "adicional sobre nuestros datos.\n", "\n", "Esto nos dice:\n", "- ¿Cuánto saben ya estos modelos sobre toxicidad?\n", "- ¿Merece la pena fine-tunearlos o ya son suficientemente buenos?\n", "- Nos da el límite inferior antes de entrenar\n", "\n", "Si zero-shot ya supera al LR, el fine-tuning lo mejorará aún más." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "id": "db8d4cd9" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Evaluando zero-shot: martin-ha/toxic-comment-model\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.\n", "WARNING:huggingface_hub.utils._http:Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.\n", "Loading weights: 100%|██████████| 104/104 [00:00<00:00, 7896.16it/s]\n", "[transformers] You seem to be using the pipelines sequentially on GPU. In order to maximize efficiency please use a dataset\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ " F1=0.6670 | ROC-AUC=0.8048 | FP=12 | FN=36\n", "\n", "Evaluando zero-shot: cardiffnlp/twitter-roberta-base-hate\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Loading weights: 100%|██████████| 201/201 [00:00<00:00, 11339.62it/s]\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ " F1=0.4320 | ROC-AUC=0.7500 | FP=1 | FN=65\n" ] } ], "source": [ "ZERO_SHOT_MODELS = [\n", " ('martin-ha/toxic-comment-model', 'ZeroShot-DistilBERT-Toxic'),\n", " ('cardiffnlp/twitter-roberta-base-hate', 'ZeroShot-RoBERTa-Hate'),\n", "]\n", "\n", "zero_shot_results = []\n", "y_test_arr = y_test.values\n", "\n", "for model_id, name in ZERO_SHOT_MODELS:\n", " print(f'\\nEvaluando zero-shot: {model_id}')\n", " try:\n", " clf = pipeline(\n", " 'text-classification',\n", " model=model_id,\n", " top_k=None, # reemplaza return_all_scores=True (deprecado)\n", " truncation=True,\n", " max_length=128,\n", " device=0 if torch.cuda.is_available() else -1,\n", " )\n", "\n", " probs_all, preds = [], []\n", "\n", " for text in X_test:\n", " out = clf(text[:512])\n", "\n", " # ── Fix: normalizar formato de salida ──────────────────────────\n", " # Dependiendo de la versión de transformers, el formato varía:\n", " # Versión nueva: [{label, score}, {label, score}] → lista de dicts\n", " # Versión vieja: [[{label, score}, {label, score}]] → lista de listas\n", " if isinstance(out[0], list):\n", " raw_scores = out[0] # formato antiguo: desenvuelve un nivel\n", " elif isinstance(out[0], dict):\n", " raw_scores = out # formato nuevo: ya es lista de dicts\n", " else:\n", " raw_scores = []\n", "\n", " scores = {s['label'].lower(): s['score'] for s in raw_scores}\n", "\n", " # Buscar la probabilidad de la clase tóxica\n", " # Cada modelo usa nombres distintos para sus etiquetas\n", " prob_toxic = (\n", " scores.get('label_1') or # formato genérico LABEL_1\n", " scores.get('hate') or # cardiffnlp usa 'hate'\n", " scores.get('toxic') or # martin-ha usa 'toxic'\n", " scores.get('offensive') or # algunos usan 'offensive'\n", " max(scores.values()) # fallback: tomar el mayor\n", " )\n", "\n", " probs_all.append(prob_toxic)\n", " preds.append(1 if prob_toxic >= 0.5 else 0)\n", "\n", " probs_all = np.array(probs_all)\n", " preds = np.array(preds)\n", "\n", " res = {\n", " 'model' : name,\n", " 'f1' : round(f1_score(y_test_arr, preds, average='weighted'), 4),\n", " 'f1_toxic' : round(f1_score(y_test_arr, preds, pos_label=1), 4),\n", " 'precision': round(precision_score(y_test_arr, preds, average='weighted'), 4),\n", " 'recall' : round(recall_score(y_test_arr, preds, average='weighted'), 4),\n", " 'roc_auc' : round(roc_auc_score(y_test_arr, probs_all), 4),\n", " 'fp' : int(((y_test_arr==0)&(preds==1)).sum()),\n", " 'fn' : int(((y_test_arr==1)&(preds==0)).sum()),\n", " }\n", " zero_shot_results.append(res)\n", " print(f\" F1={res['f1']:.4f} | ROC-AUC={res['roc_auc']:.4f} | FP={res['fp']} | FN={res['fn']}\")\n", "\n", " except Exception as e:\n", " print(f' Error: {e}')\n", " zero_shot_results.append({'model': name, 'f1': None, 'error': str(e)})" ] }, { "cell_type": "markdown", "metadata": { "id": "ddc914ee" }, "source": [ "## 9. Fine-tuning — DistilBERT base (modelo general)\n", "\n", "### ¿Qué es DistilBERT?\n", "DistilBERT es una versión comprimida de BERT:\n", "- 40% menos parámetros que BERT-base\n", "- 60% más rápido\n", "- Mantiene el 97% de la capacidad de BERT\n", "\n", "Es el punto de partida **generalista**: no sabe nada de toxicidad,\n", "aprende todo desde los datos nuestros.\n", "\n", "### ¿Por qué full fine-tuning aquí?\n", "Como no tiene conocimiento previo de toxicidad, necesita actualizar\n", "más parámetros para aprender. Usamos `freeze_backbone=False`." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "id": "b56e5519" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Cargando distilbert-base-uncased...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Map: 100%|██████████| 699/699 [00:00<00:00, 6473.06 examples/s]\n", "Map: 100%|██████████| 151/151 [00:00<00:00, 8816.71 examples/s]\n", "Map: 100%|██████████| 150/150 [00:00<00:00, 9874.68 examples/s]\n", "Loading weights: 100%|██████████| 100/100 [00:00<00:00, 906.94it/s]\n", "[transformers] \u001b[1mDistilBertForSequenceClassification LOAD REPORT\u001b[0m from: distilbert-base-uncased\n", "Key | Status | \n", "------------------------+------------+-\n", "vocab_layer_norm.bias | UNEXPECTED | \n", "vocab_layer_norm.weight | UNEXPECTED | \n", "vocab_transform.weight | UNEXPECTED | \n", "vocab_projector.bias | UNEXPECTED | \n", "vocab_transform.bias | UNEXPECTED | \n", "pre_classifier.weight | MISSING | \n", "pre_classifier.bias | MISSING | \n", "classifier.weight | MISSING | \n", "classifier.bias | MISSING | \n", "\n", "Notes:\n", "- UNEXPECTED:\tcan be ignored when loading from different task/architecture; not ok if you expect identical arch.\n", "- MISSING:\tthose params were newly initialized because missing from the checkpoint. Consider training on your downstream task.\n", "[transformers] warmup_ratio is deprecated and will be removed in v5.2. Use `warmup_steps` instead.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ " Full fine-tuning — 66,955,010 params\n", " Entrenando (max 5 epochs, early stopping patience=2)...\n" ] }, { "data": { "text/html": [ "\n", "
\n", " \n", " \n", " [352/440 00:59 < 00:14, 5.88 it/s, Epoch 4/5]\n", "
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
EpochTraining LossValidation LossF1 ToxicF1 WeightedPrecisionRecallRoc Auc
10.6026720.5423500.6771650.7246650.7543860.6142860.805820
20.4291050.5514170.7435900.7341690.6744190.8285710.833598
30.2635300.7355740.7375890.7550750.7323940.7428570.814991
40.1671360.9231130.7435900.7341690.6744190.8285710.819136

" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stderr", "output_type": "stream", "text": [ "Writing model shards: 100%|██████████| 1/1 [00:03<00:00, 3.27s/it]\n", "Writing model shards: 100%|██████████| 1/1 [00:02<00:00, 2.27s/it]\n", "Writing model shards: 100%|██████████| 1/1 [00:02<00:00, 2.37s/it]\n", "Writing model shards: 100%|██████████| 1/1 [00:03<00:00, 3.64s/it]\n" ] }, { "data": { "text/html": [], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "=======================================================\n", "DistilBERT base\n", "=======================================================\n", " precision recall f1-score support\n", "\n", " No tóxico 0.83 0.73 0.78 81\n", " Tóxico 0.72 0.83 0.77 69\n", "\n", " accuracy 0.77 150\n", " macro avg 0.78 0.78 0.77 150\n", "weighted avg 0.78 0.77 0.77 150\n", "\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAdQAAAGGCAYAAADCYXCQAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAR1hJREFUeJzt3XdYFFf7N/Dv0hakLCXU2MUCKpKQqIhdlBiNGLHGqCgx9oLGQnxie2Kw16hRo2A31qgxRrEnRn0Uu2JBjSUUUQREZGnn/cPX/bkCCsvA4PL95Jrrcs+cmbl3s3BznzkzoxBCCBAREVGRGMgdABERkT5gQiUiIpIAEyoREZEEmFCJiIgkwIRKREQkASZUIiIiCTChEhERSYAJlYiISAJMqERERBJgQi0hkydPhkKhkGx/gYGBqFy5slabQqHA5MmTJTuG3CpXroz27dvLHQYByMrKwtixY1GhQgUYGBigY8eOkh+jefPmaN68ueT7fVeFh4dDoVDgn3/+kTsUKiAmVB28/KK/XExNTeHi4gI/Pz8sXLgQT58+leQ4MTExmDx5Ms6fPy9JnAqFAg4ODmjRogX27t2bq//rfV9dBg4cqOkXGBiotU6pVKJGjRqYOHEi0tPTAbxIhm/a38slPDxcp/dWFqWnp2PevHlo0KABVCoVTE1NUaNGDQwdOhQ3btwo1mOvWrUKs2bNQufOnbF69WoEBwcX6/FK0pEjRzTfx3Xr1uXZx8fHBwqFAnXq1NHpGEuWLOF3vQwwkjuAd9nUqVNRpUoVZGZmIi4uDkeOHMHIkSMxd+5c7Nq1Cx4eHpq+//nPfzB+/PhC7T8mJgZTpkxB5cqV4enpqbVuxYoVyMnJKVScQgjEx8cjPDwcn376KXbv3p2rAmzdujV69+6dax81atTQeq1UKvHzzz8DAJKTk7Fz507897//xa1bt7B+/XrMnz8fqampmv6///47Nm7ciHnz5uG9997TtDdq1KhA76Gse/ToET755BNERkaiffv2+OKLL2BhYYHr169j06ZNWL58OTIyMort+IcOHcL777+PefPmFdsx9u/fX2z7LghTU1Ns2LABX375pVb7P//8g7///humpqY673vJkiV47733EBgYWOBtevXqhe7du0OpVOp8XCpZTKhF0LZtW3z00Uea1yEhITh06BDat2+PDh06ICoqCmZmZgAAIyMjGBlJ93EbGxvrHGdQUBAcHR2xcePGXAm1Ro0auX6h5MXIyEir3+DBg9GoUSNs3LgRc+fOzTUkGBcXh40bN6Jjx465hqrp7QIDA3Hu3Dls3boVAQEBWuv++9//YsKECcV6/IcPH8La2rpYj2FiYlKs+3+bTz/9FLt27cKjR4+0/ujbsGEDHB0dUb16dTx58qTY43j27BnMzc1haGgIQ0PDYj8eSYdDvhJr2bIlvvvuO9y9e1dr+Civc6gRERFo3LgxrK2tYWFhgZo1a+Lbb78F8GIY6uOPPwYA9O3bN9cQaV7nUAvK2toaZmZmkiZ4hUKBxo0bQwiB27dvS7Zf4EXl4unpCVNTU7i7u2P79u1a6xMTE/HNN9+gbt26sLCwgJWVFdq2bYsLFy7k2teiRYtQu3ZtlCtXDjY2Nvjoo4+wYcMGrT7//vsv+vXrB0dHRyiVStSuXRurVq2S9D0VxqlTp7Bnzx4EBQXlSqbAi9GC2bNna7UdOnQITZo0gbm5OaytreHv74+oqCitPi+/k9HR0QgMDIS1tTVUKhX69u2LtLQ0AC+qM4VCgcOHD+PKlSua7+GRI0c0Q6VHjhzR2u/LbV4d4oyLi0Pfvn1Rvnx5KJVKODs7w9/fX+v8YF7nUB8+fKj5A9DU1BT16tXD6tWr8zze7NmzsXz5clSrVg1KpRIff/wxTp8+XcBPGfD394dSqcSWLVu02jds2ICuXbvmmdzCwsLQsmVLODg4QKlUwt3dHUuXLtXqU7lyZVy5cgVHjx7VfH4v3+fL0zJHjx7F4MGD4eDggPLly2ute/kZHTp0CAYGBpg4cWKu+BQKRa7jUsljhVoMevXqhW+//Rb79+9H//798+xz5coVtG/fHh4eHpg6dSqUSiWio6Nx/PhxAICbmxumTp2KiRMn4uuvv0aTJk0A6DZEmpycjEePHkEIgYcPH2LRokVITU3NsxJNT0/Ho0ePcrVbWVm9tYJ4+YNvY2NT6Bjzc/PmTXTr1g0DBw5Enz59EBYWhi5duuCPP/5A69atAQC3b9/Gr7/+ii5duqBKlSqIj4/HsmXL0KxZM1y9ehUuLi4AXgyTDx8+HJ07d8aIESOQnp6Oixcv4tSpU/jiiy8AAPHx8WjYsCEUCgWGDh0Ke3t77N27F0FBQUhJScHIkSMle28FtWvXLgAvvlcFceDAAbRt2xZVq1bF5MmT8fz5cyxatAg+Pj44e/Zsrj/EunbtiipVqiA0NBRnz57Fzz//DAcHB8yYMQP29vZYu3Ytpk2bhtTUVISGhgJ48f18PUG/SUBAAK5cuYJhw4ahcuXKePjwISIiInDv3r18/zB8/vw5mjdvjujoaAwdOhRVqlTBli1bEBgYiKSkJIwYMUKr/4YNG/D06VMMGDAACoUCM2fORKdOnXD79u0CjeiUK1cO/v7+2LhxIwYNGgQAuHDhAq5cuYKff/4ZFy9ezLXN0qVLUbt2bXTo0AFGRkbYvXs3Bg8ejJycHAwZMgQAMH/+fAwbNgwWFhaakQRHR0et/QwePBj29vaYOHEinj17lmd8LVu2xODBgxEaGoqOHTviww8/RGxsLIYNGwZfX1+teQ4kE0GFFhYWJgCI06dP59tHpVKJDz74QPN60qRJ4tWPe968eQKASEhIyHcfp0+fFgBEWFhYrnV9+vQRlSpV0moDICZNmpQrztcXpVIpwsPDc+0zr74vl40bN2od29zcXCQkJIiEhAQRHR0tZs+eLRQKhahTp47IycnJte9Zs2YJAOLOnTv5vt/XVapUSQAQ27Zt07QlJycLZ2dnrc82PT1dZGdna217584doVQqxdSpUzVt/v7+onbt2m88ZlBQkHB2dhaPHj3Sau/evbtQqVQiLS2twPFL5fPPPxcAxJMnTwrU39PTUzg4OIjHjx9r2i5cuCAMDAxE7969NW0vv5P9+vXLdTw7OzuttmbNmuX67A4fPiwAiMOHD2u137lzR+t7++TJEwFAzJo1641xN2vWTDRr1kzzev78+QKAWLdunaYtIyNDeHt7CwsLC5GSkqJ1PDs7O5GYmKjpu3PnTgFA7N69+43Hffk+tmzZIn777TehUCjEvXv3hBBCjBkzRlStWjXfzyCv74Ofn59mm5dq166t9d5eevkz2rhxY5GVlZXnuld/Zp49eyZcXV1F7dq1RXp6umjXrp2wsrISd+/efeN7pJLBId9iYmFh8cbZvi/PR+3cubPAk4t0tXjxYkRERCAiIgLr1q1DixYt8NVXX+UaOgVeDHu97Pvq0qJFC61+z549g729Pezt7eHq6opvvvkGPj4+2Llzp6SXB7m4uODzzz/XvLayskLv3r1x7tw5xMXFAXgx5Glg8OKrnJ2djcePH2uG0M+ePavZ1traGg8ePMh3GFAIgW3btuGzzz6DEAKPHj3SLH5+fkhOTtbaX0lJSUkBAFhaWr61b2xsLM6fP4/AwEDY2tpq2j08PNC6dWv8/vvvubZ5vbJp0qQJHj9+rDluUZmZmcHExARHjhwp1DnI33//HU5OTujRo4emzdjYGMOHD0dqaiqOHj2q1b9bt25aoyMvR3UKcwqiTZs2sLW1xaZNmyCEwKZNm7SO/7qXcySA/xsJatasGW7fvo3k5OQCH7d///4FOl9arlw5hIeHIyoqCk2bNsWePXswb948VKxYscDHouLDId9ikpqaCgcHh3zXd+vWDT///DO++uorjB8/Hq1atUKnTp3QuXNnTXKQSv369bUmJfXo0QMffPABhg4divbt22sN5ZYvXx6+vr5v3aepqSl2794NAHjw4AFmzpyJhw8fav2CkYKrq2uuBP1yxvE///wDJycn5OTkYMGCBViyZAnu3LmD7OxsTV87OzvNv8eNG4cDBw6gfv36cHV1RZs2bfDFF1/Ax8cHAJCQkICkpCQsX74cy5cvzzOehw8f5htrYmKizjNtbW1t8x1St7KyAgA8ffr0rROD7t69CwCoWbNmrnVubm7Yt2+fZtLLS6//Mn6ZlJ48eaI5dlEolUrMmDEDo0ePhqOjIxo2bIj27dujd+/ecHJyeuN7qV69eq6fBzc3N836V73pfRSUsbExunTpgg0bNqB+/fq4f/++5nRAXo4fP45JkybhxIkTmvPOLyUnJ0OlUhXouFWqVClwjD4+Phg0aBAWL14MPz8/9OvXr8DbUvFihVoMHjx4gOTkZLi6uubbx8zMDMeOHcOBAwfQq1cvXLx4Ed26dUPr1q21EkJxMDAwQIsWLRAbG4ubN2/qtA9DQ0P4+vrC19cXgYGBOHjwIOLi4jBgwACJo327H374AaNGjULTpk2xbt067Nu3DxEREahdu7ZW9e/m5qa5zKRx48bYtm0bGjdujEmTJgGApu+XX36ZZ5UeERGhSb556dSpE5ydnXVa/v7773z3W6tWLQDApUuXpPi4csmvMhJCvHG7/EYi8vr+jhw5Ejdu3EBoaChMTU3x3Xffwc3NDefOnSt8wPnQ9X287osvvsD58+cxefJk1KtXD+7u7nn2u3XrFlq1aoVHjx5h7ty52LNnDyIiIjTX6BZm5Kkwf4iq1WrNRLBbt27lSuQkH1aoxWDt2rUAAD8/vzf2MzAwQKtWrdCqVSvMnTsXP/zwAyZMmIDDhw/D19dX0qHT12VlZQGA1rWiReHs7Izg4GBMmTIFJ0+eRMOGDSXZb3R0NIQQWp/Fy5sYvJzMsnXrVrRo0QIrV67U2jYpKUnr8gcAMDc3R7du3dCtWzdkZGSgU6dOmDZtGkJCQmBvbw9LS0tkZ2cXqEp/3Zw5c3S+rKJevXr5rvvss88QGhqKdevWaYYx81OpUiUAwPXr13Otu3btGt577z2t6rQoXlaASUlJWu2vV44vVatWDaNHj8bo0aNx8+ZNeHp6Ys6cOfneTKFSpUq4ePEicnJytKrUa9euadYXh8aNG6NixYo4cuQIZsyYkW+/3bt3Q61WY9euXVrV8eHDh3P1lfJnedKkSYiKisLs2bMxbtw4jB8/HgsXLpRs/6Q7JlSJHTp0CP/9739RpUoV9OzZM99+iYmJWue4AGhu3qBWqwFA84vv9V9YRZWZmYn9+/fDxMREM3wmhWHDhmHWrFmYPn06fv31V0n2GRMTgx07dqBTp04AXpxPXLNmDTw9PTXDhYaGhrmqkC1btuDff//VGiV4/Pix1hCwiYkJ3N3dsXfvXmRmZsLU1BQBAQHYsGEDLl++nOuuOAkJCbC3t883Vi8vryK/37x4e3vjk08+wc8//4y2bdvmusY3IyMD3377LWbPng1nZ2d4enpi9erVCAkJ0QwRX758Gfv37y/QNcYFValSJRgaGuLYsWNaMS1ZskSrX1paGgwMDLRujFCtWjVYWlpqvut5+fTTT7F//3788ssvmvOYWVlZWLRoESwsLNCsWTPJ3surFAoFFi5ciHPnzr1xZvXLivjV715ycjLCwsJy9TU3N5fk5/jUqVOYPXs2Ro4cidGjR+PRo0eYMWMGAgICiu3zoIJjQi2CvXv34tq1a8jKykJ8fDwOHTqEiIgIVKpUCbt27XrjnVWmTp2KY8eOoV27dqhUqRIePnyIJUuWoHz58mjcuDGAF790rK2t8dNPP8HS0hLm5uZo0KBBoc63vBon8OIc4IYNG3Dz5k2MHz8+1zmyGzdu5FkxODo6ai5TyY+dnR369u2LJUuWICoqSpJkXaNGDQQFBeH06dNwdHTEqlWrEB8fr/VLq3379pg6dSr69u2LRo0a4dKlS1i/fj2qVq2qta82bdrAyckJPj4+cHR0RFRUFH788Ue0a9dOM+Fn+vTpOHz4MBo0aID+/fvD3d0diYmJOHv2LA4cOIDExMQivyddrFmzBm3atEGnTp3w2WefoVWrVjA3N8fNmzexadMmxMbGaq5FnTVrFtq2bQtvb28EBQVpLptRqVSS3utZpVKhS5cuWLRoERQKBapVq4bffvst13nmGzduoFWrVujatSvc3d1hZGSEHTt2ID4+Ht27d893/19//TWWLVuGwMBAREZGonLlyti6dSuOHz+O+fPnF2iSlq78/f3h7+//xj5t2rSBiYkJPvvsMwwYMACpqalYsWIFHBwcEBsbq9XXy8sLS5cuxffffw9XV1c4ODigZcuWhYopPT0dffr0QfXq1TFt2jQAwJQpU7B792707dsXly5dkmz0gXQk3wTjd9frl6OYmJgIJycn0bp1a7FgwQLNdP5XvX7ZzMGDB4W/v79wcXERJiYmwsXFRfTo0UPcuHFDa7udO3cKd3d3YWRkpHUpgq6XzZiamgpPT0+xdOnSXJe3vN731eXVKf8vL5vJy61bt4ShoaHo06ePVruul820a9dO7Nu3T3h4eAilUilq1aoltmzZotUvPT1djB49Wjg7OwszMzPh4+MjTpw4kesyjGXLlommTZsKOzs7oVQqRbVq1cSYMWNEcnKy1v7i4+PFkCFDRIUKFYSxsbFwcnISrVq1EsuXLy9w7MUhLS1NzJ49W3z88cfCwsJCmJiYiOrVq4thw4aJ6Ohorb4HDhwQPj4+wszMTFhZWYnPPvtMXL16VavPy+/k65du5XW5Rl6XjAghREJCgggICBDlypUTNjY2YsCAAeLy5cta39VHjx6JIUOGiFq1aglzc3OhUqlEgwYNxObNm7X29fr/LyFe/L/o27eveO+994SJiYmoW7dursvIXl42k9dlOa//TOTl1ctm3iSvz2DXrl3Cw8NDmJqaisqVK4sZM2aIVatW5fr84uLiRLt27YSlpaXWz9ObLsF7/f9DcHCwMDQ0FKdOndLqd+bMGWFkZCQGDRr0xvip+CmEKOQZeyIiIsqFs3yJiIgkwIRKREQkASZUIiIiCTChEhERSYAJlYiISAJMqERERBJgQiUiIpKAXt4pyeyDoXKHQFQgx3/9Qe4QiArkw0pFf/LQ64ryu/r5uR8ljEQarFCJiIgkoJcVKhERvQMU+lXTMaESEZE8ivERlXJgQiUiInmwQiUiIpIAK1QiIiIJsEIlIiKSgJ5VqPr15wEREZFMWKESEZE8OORLREQkAT0b8mVCJSIiebBCJSIikgArVCIiIgnoWYWqX++GiIhIJqxQiYhIHhzyJSIikoCeDfkyoRIRkTyYUImIiCRgwCFfIiKiotOzClW/3g0REZFMWKESEZE8OMuXiIhIAno25MuESkRE8mCFSkREJAFWqERERBJghUpERCQBPatQ9evdEBERyYQVKhERyYNDvkRERBLQsyFfJlQiIpIHK1QiIiIJsEIlIiKSgJ4lVP16N0RERDJhhUpERPLgOVQiIiIJ6NmQLxMqERHJgxUqERGRBFihEhERSUDPKlT9+vOAiIhIJqxQiYhIFgo9q1CZUImISBZMqERERFLQr3zKhEpERPJghUpERCQBJtRikpCQgOvXrwMAatasCXt7e5kjIiIiKjjZL5t59uwZ+vXrBxcXFzRt2hRNmzaFi4sLgoKCkJaWJnd4RERUTBQKhc5LaSR7Qh01ahSOHj2KXbt2ISkpCUlJSdi5cyeOHj2K0aNHyx0eEREVE31LqLIP+W7btg1bt25F8+bNNW2ffvopzMzM0LVrVyxdulS+4IiIqPiUzryoM9kTalpaGhwdHXO1Ozg4cMiXiEiPldZKU1eyD/l6e3tj0qRJSE9P17Q9f/4cU6ZMgbe3t4yRERFRceKQr8QWLFgAPz8/lC9fHvXq1QMAXLhwAaampti3b5/M0RERUXEprYlRV7In1Dp16uDmzZtYv349rl27BgDo0aMHevbsCTMzM5mjIyIiKhjZEyoAlCtXDv3795c7DCIiKkH6VqHKfg41NDQUq1atytW+atUqzJgxQ4aIiIioRCiKsBTC5MmTc52DrVWrlmZ9eno6hgwZAjs7O1hYWCAgIADx8fGFfjuyJ9Rly5ZpvbGXateujZ9++kmGiIiIqCSU5KSk2rVrIzY2VrP89ddfmnXBwcHYvXs3tmzZgqNHjyImJgadOnUq9DFkH/KNi4uDs7NzrnZ7e3vExsbKEBEREZWEkhzyNTIygpOTU6725ORkrFy5Ehs2bEDLli0BAGFhYXBzc8PJkyfRsGHDAh9D9gq1QoUKOH78eK7248ePw8XFRYaIiIioJJRkhXrz5k24uLigatWq6NmzJ+7duwcAiIyMRGZmJnx9fTV9a9WqhYoVK+LEiROFOobsFWr//v0xcuRIZGZmav46OHjwIMaOHctbDxIRUZ7UajXUarVWm1KphFKpzNW3QYMGCA8PR82aNREbG4spU6agSZMmuHz5MuLi4mBiYgJra2utbRwdHREXF1eomGRPqGPGjMHjx48xePBgZGRkAABMTU0xbtw4hISEyBwdEREVmyKM+IaGhmLKlClabZMmTcLkyZNz9W3btq3m3x4eHmjQoAEqVaqEzZs3S3p5puwJVaFQYMaMGfjuu+8QFRUFMzMzVK9ePc+/MoiISH8U5RxqSEgIRo0apdVW0LxhbW2NGjVqIDo6Gq1bt0ZGRgaSkpK0qtT4+Pg8z7m+ieznUF+ysLDAxx9/jDp16jCZEhGVAUU5h6pUKmFlZaW1FDR3pKam4tatW3B2doaXlxeMjY1x8OBBzfrr16/j3r17hb79rSwVaqdOnRAeHg4rK6u3Tk3evn17CUVFREQlqaRm+X7zzTf47LPPUKlSJcTExGDSpEkwNDREjx49oFKpEBQUhFGjRsHW1hZWVlYYNmwYvL29CzXDF5ApoapUKs0HqVKp5AiBiIhkVlIJ9cGDB+jRowceP34Me3t7NG7cGCdPnoS9vT0AYN68eTAwMEBAQADUajX8/PywZMmSQh9HIYQQUgcvN7MPhsodAlGBHP/1B7lDICqQDytZSb5PlwG6j0DGLCv8jReKm+znUF/eED8vfNoMEZEeK6FbD5YU2RPqhx9+iMWLF2u1qdVqDB06FP7+/jJFRURExY3PQ5VYeHg4Bg0ahD179iAsLAyxsbH44osvkJOTgz///FPu8IiIqJiU1sSoK9kr1K5du+LChQvIzMxE7dq14e3tjWbNmuHs2bP4+OOP5Q6PiIiKCSvUYpKRkYHs7GxkZ2fD2dkZpqamcodERETFqXTmRZ3JnlA3bdqEQYMGoUmTJrhx4wbOnz+Pvn37Yt++fVi7di2qVq0qd4hlxoQBn+I/Az/Vart+Jw6enb4HAFQp/x6mB38O7w+qQmlshIi/ozBqxhY8THwqR7hUhv26MQynjx9GzP27MDFRooa7B3p8NRQuFSoDAFJTkrFl7XJcijyJRw/jYaWyxkeNmqNr4ECUM7eQN3jSKK2Vpq5kT6hBQUGYPXs2Bg0aBABo3bo1Ll68iIEDB8LT0xMpKSkyR1i2XImOQbuBizSvs7JzAADlTE3w25IhuHTjX7T9+sX6SYPbYduCAWjaew708OorKsWiLp1Fmw5dULWGO3Kys7EpbAlCQ4Zh1orNMDUzw5PHCUh6nICe/UegfKWqSIiPxcqF0/HkcQKCJ86QO3zSU7In1LNnz6JmzZpabba2tti8eTPWrl0rU1RlV1Z2DuIf5644vT2ropKLHRr2mIGnz9IBAF9NXIvYozPRvH4NHD51vaRDpTIs5IdFWq8HfTMJA7q2wZ2bUXDz+BAVqrgieOJMzXpHl/Lo1ncQFs+YiOzsLBgayv6rj8AKVXIvk2lkZCSioqIAAO7u7vjwww/Rq1cvOUMrk1wr2uP2/mlIV2fi1MU7mLhoF+7HPYHSxAhCCKgzsjR909VZyMkRaORZjQmVZJX2LBUAYGGZ/80H0p6lwqycOZNpKcKEWkRqtVrrBsYPHz5E9+7dceTIEc2d/pOSktCiRQts2rRJc2soKn6nL/+Dryeuw4278XB6T4UJA9riwKpgeHWehv9d+gfPnmdg2gh/TPxxFxRQ4PsR/jAyMoTTe9LfQYWooHJycrDmp7moWbseKlRxzbNPSnISdqxfiVaffl7C0dGb6FtCLfHLZubOnYs1a9ZoXg8bNgxPnz7FlStXkJiYiMTERFy+fBkpKSkYPnz4W/enVquRkpKitYic7OJ8C3pr//Gr2H7gHC7fjMGBE1HoOHQpVBZmCGjzIR49SUXPsSvxadM6eHR8DuL/nAWVhRnOXr2HHJ4/JRmF/TgT9/+5hWHfTstzfdqzVMz8z0i8X7EKAnp9XcLR0Rvp2Z2SSrxC7dq1Kzp37oy7d+/iu+++wx9//IEDBw7Azc1N08fd3R2LFy9GmzZt3rq/vB4ya+j4MYyd60see1mTnPoc0fceolqFF6MEB09eQ+0OU2BnbY6srBwkpz7HnYgf8M++SJkjpbIq7MeZOHvyT0yasxx29o651j9Pe4bpE4bDrFw5jJo8C0ZGHO4tTVihFlG1atVw4sQJ3L9/H8CL4RpjY+Nc/YyNjZGTk/PW/YWEhCA5OVlrMXL0kjzussjczARVyr+HuEfJWu2Pk54hOfU5mn1cAw62Fvjt6CWZIqSySgiBsB9n4vTxI/jPrKVwcH4/V5+0Z6kIDRkGIyNjfDNlLkxM+JxlKl6y/LlmamqK5cuXAwBatmyJESNGYOPGjXBxcQEA/PvvvwgODkarVq3eui+lUpnrobIKA0Ppgy4DQoM/x55jl3AvJhEuDir8Z2A7ZOfkYPMfLyrQXh0a4vqdOCQ8SUUDjyqYPaYzFq0/jJt3H8ocOZU1qxbNwN+H92H0lNkwMyuHpMRHAIBy5hYwUZpqkqlanY7R46bieVoqnqe9mLhkpbKBgSF/R5QG+lahyj7+8eOPP6JDhw6oXLkyKlSoAAC4f/8+6tSpg3Xr1skcXdnyvqM11oT2ha2qHB49ScXf52+jWe85ePTkxS+iGpUdMHVYB9iqyuFuTCJmrtyHhesOyRw1lUUHftsGAPjvNwO12gd+MxHN2nyGf6KvI/raZQDAyEDtiUgL1+yEvZNLyQRKb6Rn+bR0PA9VCIEDBw5oHuXm5uYGX19fnffH56HSu4LPQ6V3RXE8D7X6mD903vbmrE8kjEQasleoa9asQbdu3dC6dWu0bt1a056RkYFNmzahd+/eMkZHRETFRd8qVNmfNtO3b18kJyfnan/69Cn69u0rQ0RERFQS9O1pM7InVCFEnh/OgwcPoFKpZIiIiIio8GQb8v3ggw80f2m0atVK6/qw7Oxs3LlzB598UvrGyImISBqltNDUmWwJtWPHjgCA8+fPw8/PDxYW//dIJRMTE1SuXBkBAQEyRUdERMXNwEC/MqpsCXXSpEkAgMqVK6Nbt258oDgRURnDClViffr0kTsEIiKSQWmdXKQr2RMqERGVTXqWT+Wf5UtERKQPWKESEZEsOORbjF7eBVHfPmQiIspN337Xl4oh3zVr1qBu3bowMzODmZkZPDw8sHbtWrnDIiKiYqRQ6L6URrJXqHPnzsV3332HoUOHwsfHBwDw119/YeDAgXj06BGCg4NljpCIiIqDvlWosifURYsWYenSpVo3we/QoQNq166NyZMnM6ESEekpPcun8ifU2NhYNGrUKFd7o0aNEBsbK0NERERUEvStQpX9HKqrqys2b96cq/2XX35B9erVZYiIiIio8GSvUKdMmYJu3brh2LFjmnOox48fx8GDB/NMtEREpB/0rECVP6EGBATg1KlTmDdvHn799VcAgJubG/73v//hgw8+kDc4IiIqNvo25Ct7QgUALy8vrFu3Tu4wiIioBOlZPi0dCZWIiMoeVqgSMTAweOuHqVAokJWVVUIRERFRSdKzfCpfQt2xY0e+606cOIGFCxciJyenBCMiIiLSnWwJ1d/fP1fb9evXMX78eOzevRs9e/bE1KlTZYiMiIhKgr4N+cp+HSoAxMTEoH///qhbty6ysrJw/vx5rF69GpUqVZI7NCIiKib6di9fWRNqcnIyxo0bB1dXV1y5cgUHDx7E7t27UadOHTnDIiKiEqBQKHReSiPZhnxnzpyJGTNmwMnJCRs3bsxzCJiIiPRXKc2LOpMtoY4fPx5mZmZwdXXF6tWrsXr16jz7bd++vYQjIyKiklBaK01dyZZQe/furXcfJhERlV2yJdTw8HC5Dk1ERKWAvhVVvFMSERHJQs/yKRMqERHJgxUqERGRBPQsnzKhEhGRPFihEhERSUDP8mnpuPUgERHRu44VKhERycJAz0pUJlQiIpKFnuVTJlQiIpKHvk1K4jlUIiKShYFC96Uopk+fDoVCgZEjR2ra0tPTMWTIENjZ2cHCwgIBAQGIj48v3PspWlhERES6kePxbadPn8ayZcvg4eGh1R4cHIzdu3djy5YtOHr0KGJiYtCpU6dC7ZsJlYiIyoTU1FT07NkTK1asgI2NjaY9OTkZK1euxNy5c9GyZUt4eXkhLCwMf//9N06ePFng/TOhEhGRLBQK3Re1Wo2UlBStRa1Wv/F4Q4YMQbt27eDr66vVHhkZiczMTK32WrVqoWLFijhx4kSB3w8TKhERyUJRhP9CQ0OhUqm0ltDQ0HyPtWnTJpw9ezbPPnFxcTAxMYG1tbVWu6OjI+Li4gr8fjjLl4iIZFGUyUUhISEYNWqUVptSqcyz7/379zFixAhERETA1NRU94O+BRMqERHJoiiTi5RKZb4J9HWRkZF4+PAhPvzwQ01bdnY2jh07hh9//BH79u1DRkYGkpKStKrU+Ph4ODk5FTgmJlQiIpJFSV2G2qpVK1y6dEmrrW/fvqhVqxbGjRuHChUqwNjYGAcPHkRAQAAA4Pr167h37x68vb0LfBwmVCIi0muWlpaoU6eOVpu5uTns7Ow07UFBQRg1ahRsbW1hZWWFYcOGwdvbGw0bNizwcZhQiYhIFqXpXr7z5s2DgYEBAgICoFar4efnhyVLlhRqH0yoREQkCznz6ZEjR7Rem5qaYvHixVi8eLHO+2RCJSIiWejbvXyZUImISBZ6lk+ZUImISB6l6RyqFHinJCIiIgmwQiUiIlnoV33KhEpERDLhpCQiIiIJFPVB4aUNEyoREcmCFSoREZEE9CyfMqESEZE89K1C5WUzREREEmCFSkREsiizk5I6depU4J1u375dp2CIiKjs0Lch3wInVJVKVZxxEBFRGaNf6bQQCTUsLKw44yAiojJG3+7ly3OoREQkCz3Lp7on1K1bt2Lz5s24d+8eMjIytNadPXu2yIERERG9S3S6bGbhwoXo27cvHB0dce7cOdSvXx92dna4ffs22rZtK3WMRESkhxQKhc5LaaRTQl2yZAmWL1+ORYsWwcTEBGPHjkVERASGDx+O5ORkqWMkIiI9pFDovpRGOiXUe/fuoVGjRgAAMzMzPH36FADQq1cvbNy4UbroiIhIbxkoFDovpZFOCdXJyQmJiYkAgIoVK+LkyZMAgDt37kAIIV10RESkt1ihAmjZsiV27doFAOjbty+Cg4PRunVrdOvWDZ9//rmkARIRkX7St3OoOs3yXb58OXJycgAAQ4YMgZ2dHf7++2906NABAwYMkDRAIiKid4FC6OEYbXqW3BEQFYxNswlyh0BUIM+PT5N8n8N2ROm87aLP3SSMRBo6P23mzz//xJdffglvb2/8+++/AIC1a9fir7/+kiw4IiLSX/o25KtTQt22bRv8/PxgZmaGc+fOQa1WAwCSk5Pxww8/SBogERHpJwOF7ktppFNC/f777/HTTz9hxYoVMDY21rT7+PjwLklERFQg+pZQdZqUdP36dTRt2jRXu0qlQlJSUlFjIiKiMqC0Dt3qSufrUKOjo3O1//XXX6hatWqRgyIiIv2nbxWqTgm1f//+GDFiBE6dOgWFQoGYmBisX78eo0ePxqBBg6SOkYiIqNTTach3/PjxyMnJQatWrZCWloamTZtCqVRizJgx+Oqrr6SOkYiI9JCejfjqVqEqFApMmDABiYmJuHz5Mk6ePImEhASoVCpUqVJF6hiJiEgPlel7+arVaoSEhOCjjz6Cj48Pfv/9d7i7u+PKlSuoWbMmFixYgODg4OKKlYiI9IhBEZbSqFBDvhMnTsSyZcvg6+uLv//+G126dEHfvn1x8uRJzJkzB126dIGhoWFxxUpERHqklBaaOitUQt2yZQvWrFmDDh064PLly/Dw8EBWVhYuXLigd9OfiYioeJXWoVtdFapyfvDgAby8vAAAderUgVKpRHBwMJMpERGVeYWqULOzs2FiYvJ/GxsZwcLCQvKgiIhI/+lbLVaohCqEQGBgIJRKJQAgPT0dAwcOhLm5uVa/7du3SxchERHppdJ6gwZdFSqh9unTR+v1l19+KWkwRERUdujbOdRCJdSwsLDiioOIiMoYPcunut0piYiIqKj0bci3tF4fS0RE9E5hhUpERLJQQL9KVCZUIiKShb4N+TKhEhGRLJhQiYiIJKBvd9ljQiUiIlmwQiUiIpKAnhWovGyGiIhICqxQiYhIFmX61oNERERS4TlUIiIiCehZgcqESkRE8jDgnZKIiIiKTt8qVM7yJSIivbZ06VJ4eHjAysoKVlZW8Pb2xt69ezXr09PTMWTIENjZ2cHCwgIBAQGIj48v9HGYUImISBYGCt2XwihfvjymT5+OyMhInDlzBi1btoS/vz+uXLkCAAgODsbu3buxZcsWHD16FDExMejUqVOh349CCCEKvVUpl54ldwREBWPTbILcIRAVyPPj0yTf5/KTd3Xe9uuGlYp0bFtbW8yaNQudO3eGvb09NmzYgM6dOwMArl27Bjc3N5w4cQINGzYs8D5ZoRIRkSwUCt0XtVqNlJQUrUWtVr/1mNnZ2di0aROePXsGb29vREZGIjMzE76+vpo+tWrVQsWKFXHixIlCvR8mVCIikoWBQqHzEhoaCpVKpbWEhobme6xLly7BwsICSqUSAwcOxI4dO+Du7o64uDiYmJjA2tpaq7+joyPi4uIK9X44y5eIiGRRlFm+ISEhGDVqlFabUqnMt3/NmjVx/vx5JCcnY+vWrejTpw+OHj2qewB5YEIlIqJ3jlKpfGMCfZ2JiQlcXV0BAF5eXjh9+jQWLFiAbt26ISMjA0lJSVpVanx8PJycnAoVE4d8iYhIFgZFWIoqJycHarUaXl5eMDY2xsGDBzXrrl+/jnv37sHb27tQ+2SFSkREsiipB4yHhISgbdu2qFixIp4+fYoNGzbgyJEj2LdvH1QqFYKCgjBq1CjY2trCysoKw4YNg7e3d6Fm+AJMqEREJJOSulHSw4cP0bt3b8TGxkKlUsHDwwP79u1D69atAQDz5s2DgYEBAgICoFar4efnhyVLlhT6OLwOlUhGvA6V3hXFcR3qusgHOm/7pVd5CSORBitUIiKShZ7dypeTkoiIiKTACpWIiGShb0+bYUIlIiJZlNQs35LChEpERLLQt3OOTKhERCQLVqhEREQS0K90yoRKREQy0bcKVd+GsImIiGTBCpWIiGShbxUdEyoREclC34Z8mVCJiEgW+pVOmVCJiEgmelagMqESEZE8DPSsRi0VCTUpKQkrV65EVFQUAKB27dro168fVCqVzJEREREVjOyTrM6cOYNq1aph3rx5SExMRGJiIubOnYtq1arh7NmzcodHRETFRKHQfSmNZK9Qg4OD0aFDB6xYsQJGRi/CycrKwldffYWRI0fi2LFjMkdIRETFQcEhX2mdOXNGK5kCgJGREcaOHYuPPvpIxsiIiKg4ldZKU1eyD/laWVnh3r17udrv378PS0tLGSIiIqKSYACFzktpJHtC7datG4KCgvDLL7/g/v37uH//PjZt2oSvvvoKPXr0kDs8IiIqJjyHKrHZs2dDoVCgd+/eyMrKAgAYGxtj0KBBmD59uszRERERFYxCCCHkDgIA0tLScOvWLQBAtWrVUK5cOZ33lZ4lVVRExcum2QS5QyAqkOfHp0m+z/1RCTpv28bNXsJIpCF7hZqcnIzs7GzY2tqibt26mvbExEQYGRnByspKxuiIiKi46NssX9nPoXbv3h2bNm3K1b5582Z0795dhoiIiKgkGCh0X0oj2RPqqVOn0KJFi1ztzZs3x6lTp2SIiIiISoKiCP+VRrIP+arVas1kpFdlZmbi+fPnMkREREQlobTO1tWV7BVq/fr1sXz58lztP/30E7y8vGSIiIiISgIrVIl9//338PX1xYULF9CqVSsAwMGDB3H69Gns379f5uiIiIgKRvaE6uPjgxMnTmDWrFnYvHkzzMzM4OHhgZUrV6J69epyh1emRJ45jfBVKxF19TISEhIwb+FitGzlC+DFEPyPC+fjrz+P4cGD+7C0sEAD70YYETwaDg6OMkdOZc2Efi3xn6BWWm3X7ybA84v5qOhkjevbxuS5Xc//bMT2w5dLIkQqgNI6uUhXsidUAPD09MT69evlDqPMe/48DTVr1kTHTgEYNWKo1rr09HRci7qKrwcOQs2atZCSkoIZodMwYuggbNy8XaaIqSy7cjse7Uas0rzOys4BADx4mIzKn4Vq9e3n/zGCv2iCfSdvlGiM9GaldehWV7Ik1JSUFM31pSkpKW/sy+tQS07jJs3QuEmzPNdZWlpi2c9hWm0hE75Dz+5dEBsTA2cXl5IIkUgjKzsH8YmpudpzckSu9g5N3bHt4CU8e55RUuFRAejbpCRZEqqNjQ1iY2Ph4OAAa2trKPL4VIUQUCgUyM7OliFCKojU1FQoFApY8o8ekoFreTvc3jkO6eosnLpyDxN/2o/78cm5+n1Q0wWeNVwQPGe3DFHSm+hZPpUnoR46dAi2traaf+eVUKl0U6vVmD93Ntp+2g4WFhZyh0NlzOmrD/D1tG24cS8BTnaWmNCvJQ4s6Q+vXguRmqZdhfZp/xGi7jzEycu5n2pF8jLQs9/9siTUZs3+b1ixefPmRdqXWq2GWq3WahOGSiiVyiLtl/KXmZmJMaNGQAiBCROnyB0OlUH7XzkXevlWPE5ffYDr28YgoGVdrP4tUrPO1MQI3Vp7YHr4YTnCpDJG9utQJ0+ejJycnFztycnJBXp8W2hoKFQqldYya0boW7cj3WRmZmLM6JGIjYnBsp9XsTqlUiE5NR3R9x+hWnk7rfbPW9RBOVNjrP/jnEyR0ZsoirCURrIn1JUrV6Jx48a4ffu2pu3IkSOoW7eu5ukzbxISEoLk5GStZcy4kOIMucx6mUzv3b2LZSvDYW1tI3dIRAAAczMTVHnfFnGPnmq1B7b3wp6/ruFRUppMkdEb6VlGlT2hXrx4EeXLl4enpydWrFiBMWPGoE2bNujVqxf+/vvvt26vVCphZWWltXC4Vzdpz57hWlQUrkVFAQD+ffAA16KiEBsTg8zMTHwTPBxXr1xG6IzZyMnOxqOEBDxKSEBmBmdOUskKHfIJGntWRkUnazSsUxG/hPZEdrbA5gMXNH2qvm+Lxp6VEbb7jIyR0pvwTkkSs7GxwebNm/Htt99iwIABMDIywt69ezV3TaKSc+XKZXzVt7fm9eyZL4bOO/h/joFDhuLI4UMAgK4B/lrb/Ry2Bh/Xb1BygVKZ976DCmumdIOtVTk8SnqGvy/eRbMBP2lVon3ae+Hfhyk48L9oGSOlN9GzOUml4wHjixYtwvjx49GxY0dERkbC0NAQGzZsQL169XTaHx8wTu8KPmCc3hXF8YDx07dzX+ZUUB9XVUkYiTRkH/L95JNPMGXKFKxevRrr16/HuXPn0LRpUzRs2BAzZ86UOzwiIqICkT2hZmdn4+LFi+jcuTMAwMzMDEuXLsXWrVsxb948maMjIqJio2eTkmQ/hxoREZFne7t27XDp0qUSjoaIiEpKaZ1cpCvZEyoA3Lp1C/Pnz0fU/59d6u7ujpEjR6Jq1aoyR0ZERMVF3yYllfiQ79mzZ7Xuz7tv3z64u7vjf//7Hzw8PODh4YFTp07B3d093+qViIjefXo24lvyFerRo0fx7bffYtu2bTA3N8f48eMRHByM6dOna/UbP348xo0bh9atW5d0iEREVBJKa2bUUYlXqMHBwWjatKnmfr5RUVEICgrK1a9fv364evVqSYdHRESkE1nOoX777bdo0qQJAMDe3h7nz59H9erVtfqcP38eDg4OcoRHREQlgJOSJHL48GF4eXmhf//++Prrr3H79m00atQIAHD8+HHMmDEDo0aNkis8IiIqZvo2KUm2OyUZGhoiNjYW9vb2mD9/PubMmYOYmBgAgIuLC8aMGYPhw4fr9KxU3imJ3hW8UxK9K4rjTkkX7j19e6d81KtoKWEk0pCtQn2ZxxUKBYKDgxEcHIynT198uJaWpe+DIiIiielZhSrrdaivV59MpEREZQfPoUqoRo0abx3STUxMLKFoiIioJOnbOVRZE+qUKVOgUpW+JwYQEREVlqwJtXv37rw0hoiojCqpAjU0NBTbt2/HtWvXYGZmhkaNGmHGjBmoWbOmpk96ejpGjx6NTZs2Qa1Ww8/PD0uWLIGjo2OBjyPb02Z0mb1LRER6pITuPXj06FEMGTIEJ0+eREREBDIzM9GmTRs8e/ZM0yc4OBi7d+/Gli1bcPToUcTExKBTp06FeztyXTZjYGCAuLi4YqlQedkMvSt42Qy9K4rjspkr/z57e6d81H7fXOdtExIS4ODggKNHj6Jp06ZITk6Gvb09NmzYoHmU6LVr1+Dm5oYTJ06gYcOGBdqvbBVqTk4Oh3uJiMowhUL3pSiSk5MBALa2tgCAyMhIZGZmwtfXV9OnVq1aqFixIk6cOFHg/ZaKx7cREVHZU5S8qFaroVartdqUSiWUSuUbt8vJycHIkSPh4+ODOnXqAADi4uJgYmICa2trrb6Ojo6Ii4srcEyyVahERES6Cg0NhUql0lpCQ0Pfut2QIUNw+fJlbNq0SfKYWKESEZE8ilCihoSE5Lrf+9uq06FDh+K3337DsWPHUL58eU27k5MTMjIykJSUpFWlxsfHw8nJqcAxsUIlIiJZKIrwn1KphJWVldaSX0IVQmDo0KHYsWMHDh06hCpVqmit9/LygrGxMQ4ePKhpu379Ou7duwdvb+8Cvx9WqEREJIuSunpyyJAh2LBhA3bu3AlLS0vNeVGVSgUzMzOoVCoEBQVh1KhRsLW1hZWVFYYNGwZvb+8Cz/AFmFCJiEgmJXU3gqVLlwIAmjdvrtUeFhaGwMBAAMC8efNgYGCAgIAArRs7FIZs16EWJ16HSu8KXodK74riuA71RnyaztvWcCwnYSTS4DlUIiIiCXDIl4iIZMHHtxEREUlA327pzoRKRESy0LN8yoRKREQy0bOMyoRKRESy4DlUIiIiCejbOVReNkNERCQBVqhERCQLPStQmVCJiEgmepZRmVCJiEgWnJREREQkAX2blMSESkREstCzfMpZvkRERFJghUpERLLgkC8REZEk9CujMqESEZEsWKESERFJQM/yKRMqERHJQ98qVM7yJSIikgArVCIikgXvlERERCQF/cqnTKhERCQPPcunTKhERCQPfZuUxIRKRESy0LdzqJzlS0REJAFWqEREJA/9KlCZUImISB56lk+ZUImISB6clERERCQBfZuUxIRKRESy0LcKlbN8iYiIJMCESkREJAEO+RIRkSz0bciXCZWIiGTBSUlEREQSYIVKREQkAT3Lp0yoREQkEz3LqJzlS0REJAFWqEREJAtOSiIiIpIAJyURERFJQM/yKRMqERHJRM8yKhMqERHJQt/OoXKWLxERkQRYoRIRkSz0bVKSQggh5A6CSj+1Wo3Q0FCEhIRAqVTKHQ5Rnvg9JTkxoVKBpKSkQKVSITk5GVZWVnKHQ5Qnfk9JTjyHSkREJAEmVCIiIgkwoRIREUmACZUKRKlUYtKkSZzoQaUav6ckJ05KIiIikgArVCIiIgkwoVKBRUdH44cffsDz58/lDoXKGCEE5s6dizNnzsgdClG+mFCpQNLT09G5c2e4uLjAzMyswNsFBgaiY8eOxRcYlQmhoaH4448/UK9evQJvc+TIESgUCiQlJRVfYESvYEJ9hwQGBkKhUGD69Ola7b/++isURbyH1+TJk+Hp6Znv+mHDhqFjx44IDAws1H4XLFiA8PDwIsVG+kuhULxxmTx5Mo4dO4atW7di69atMDY2LvC+GzVqhNjYWKhUqmJ8B0T/h/fyfceYmppixowZGDBgAGxsbErsuCtWrNBpO/4yozeJjY3V/PuXX37BxIkTcf36dU2bhYUFLCwscPbs2ULv28TEBE5OTpLESVQQrFDfMb6+vnByckJoaOgb+23btg21a9eGUqlE5cqVMWfOnHz7hoeHY8qUKbhw4YKmMnhZVd67dw/+/v6wsLCAlZUVunbtivj4eADAtWvXUK5cOWzYsEGzr82bN8PMzAxXr14FkHvINycnBzNnzoSrqyuUSiUqVqyIadOmadZfunQJLVu2hJmZGezs7PD1118jNTW1sB8TvSOcnJw0i0qlgkKh0Lx2cHDA3LlzUb58eSiVSnh6euKPP/4A8OKcqq+vL/z8/PDyQoXExESUL18eEydOBJD3kO/x48fRvHlzlCtXDjY2NvDz88OTJ08AvLgP8PDhw+Hg4ABTU1M0btwYp0+fLtkPhN5tgt4Zffr0Ef7+/mL79u3C1NRU3L9/XwghxI4dO8Sr/yvPnDkjDAwMxNSpU8X169dFWFiYMDMzE2FhYXnuNy0tTYwePVrUrl1bxMbGitjYWJGWliays7OFp6enaNy4sThz5ow4efKk8PLyEs2aNdNsu3jxYqFSqcTdu3fF/fv3hY2NjViwYEGumF8aO3assLGxEeHh4SI6Olr8+eefYsWKFUIIIVJTU4Wzs7Po1KmTuHTpkjh48KCoUqWK6NOnj2SfIZVeYWFhQqVSaV7PnTtXWFlZiY0bN4pr166JsWPHCmNjY3Hjxg0hhBAPHjwQNjY2Yv78+UIIIbp06SLq168vMjMzhRBCHD58WAAQT548EUIIce7cOaFUKsWgQYPE+fPnxeXLl8WiRYtEQkKCEEKI4cOHCxcXF/H777+LK1euiD59+ggbGxvx+PHjkvsQ6J3GhPoOeTU5NWzYUPTr108IkTuhfvHFF6J169Za244ZM0a4u7vnu+9JkyaJevXqabXt379fGBoainv37mnarly5IgCI//3vf5q2du3aiSZNmohWrVqJNm3aiJycnDxjTklJEUqlUpNAX7d8+XJhY2MjUlNTNW179uwRBgYGIi4uLt/YST+8nlBdXFzEtGnTtPp8/PHHYvDgwZrXmzdvFqampmL8+PHC3Nxck2yFyJ1Qe/ToIXx8fPI8dmpqqjA2Nhbr16/XtGVkZAgXFxcxc+ZMCd4dlQUc8n1HzZgxA6tXr0ZUVFSudVFRUfDx8dFq8/Hxwc2bN5GdnV3gY0RFRaFChQqoUKGCps3d3R3W1tZax121ahUuXryIs2fPIjw8PN8JUlFRUVCr1WjVqlW+6+vVqwdzc3OtuHNycrTOq5H+S0lJQUxMTJ7f41e/e126dMHnn3+O6dOnY/bs2ahevXq++zx//ny+371bt24hMzNT63jGxsaoX79+nj9jRHlhQn1HNW3aFH5+fggJCZE7FFy4cAHPnj3Ds2fPtCaZvK4wl9sQFURaWhoiIyNhaGiImzdvvrEvv39U3JhQ32HTp0/H7t27ceLECa12Nzc3HD9+XKvt+PHjqFGjBgwNDfPcl4mJSa7q1c3NDffv38f9+/c1bVevXkVSUhLc3d0BvJgIEhgYiAkTJiAwMBA9e/bM98YP1atXh5mZGQ4ePJjnejc3N01yfjVuAwMD1KxZM59PgfSRlZUVXFxc8vwev/zuAcDo0aNhYGCAvXv3YuHChTh06FC++/Tw8Mj3u1etWjWYmJhoHS8zMxOnT5/WOh7RG8k95kwF9/oEHyGE6NWrlzA1NdU6hxoZGak1KSk8PPyNk5KEEGL9+vXC3NxcnDt3TiQkJIj09HSRk5MjPD09RZMmTURkZKQ4depUrklJXbp0EQ0aNBCZmZkiNTVVVK9eXesc1+sxT548WdjY2IjVq1eL6OhoceLECfHzzz8LIYR49uyZcHZ2FgEBAeLSpUvi0KFDomrVqpyUVEa8fg513rx5wsrKSmzatElcu3ZNjBs3TmtS0m+//SZMTExEZGSkEEKIkJAQUb58eZGYmCiEyH0O9fr168LExEQMGjRIXLhwQURFRYklS5ZoJiWNGDFCuLi4iL1792pNSnq5P6K3YUJ9h+SVUO/cuSNMTEzE638bbd26Vbi7uwtjY2NRsWJFMWvWrDfuOz09XQQEBAhra2sBQJN87969Kzp06CDMzc2FpaWl6NKli2aC0OrVq3NNBDl16pQwNjYWv//+e54xZ2dni++//15UqlRJE9sPP/ygWX/x4kXRokULYWpqKmxtbUX//v3F06dPC/tR0Tvo9YSanZ0tJk+eLN5//31hbGws6tWrJ/bu3SuEEOLhw4fC0dFR67uTkZEhvLy8RNeuXYUQuROqEEIcOXJENGrUSCiVSmFtbS38/Pw0658/fy6GDRsm3nvvPaFUKoWPj4/W5Duit+HTZoiIiCTAc6hEREQSYEIlIiKSABMqERGRBJhQiYiIJMCESkREJAEmVCIiIgkwoRIREUmACZVID6Wnp2PatGmIjo6WOxSiMoMJlagYvf6A9ebNm2PkyJHFsu9XDR8+HNHR0XB1dZXkWET0dkZyB0Akh8DAQKxevRrAi8d0VaxYEb1798a3334LI6Pi+7HYvn07jI2NJdnXggULkNeNztavX49//vkHe/bskeQ4RFQwTKhUZn3yyScICwuDWq3G77//jiFDhsDY2DjXI/EyMjJgYmIiyTFtbW0l2Q8AqFSqPNt79uyJnj17SnYcIioYDvlSmaVUKuHk5IRKlSph0KBB8PX1xa5duzRDqdOmTYOLi4vm0XH3799H165dYW1tDVtbW/j7++Off/7R7C87OxujRo2CtbU17OzsMHbs2FwV5OtDvmq1GuPGjUOFChWgVCrh6uqKlStXatZfuXIF7du3h5WVFSwtLdGkSRPcunULQO4hX7VajeHDh8PBwQGmpqZo3LgxTp8+rVl/5MgRKBQKHDx4EB999BHKlSuHRo0a8eHtRBJhQiX6/8zMzJCRkQEAOHjwIK5fv46IiAj89ttvyMzMhJ+fHywtLfHnn3/i+PHjsLCwwCeffKLZZs6cOQgPD8eqVavw119/ITExETt27HjjMXv37o2NGzdi4cKFiIqKwrJly2BhYQEA+Pfff9G0aVMolUocOnQIkZGR6NevH7KysvLc19ixY7Ft2zasXr0aZ8+ehaurK/z8/JCYmKjVb8KECZgzZw7OnDkDIyMj9OvXr6gfHREBfB4qlU2vPlYuJydHRERECKVSKb755hvRp08f4ejoKNRqtab/2rVrRc2aNUVOTo6mTa1WCzMzM7Fv3z4hhBDOzs5i5syZmvWZmZmifPnyWo+va9asmRgxYoQQ4sXzOQGIiIiIPGMMCQkRVapUERkZGW99D6mpqcLY2FisX79esz4jI0O4uLhoYnr5OLMDBw5o+uzZs0cAEM+fP3/LJ0ZEb8MKlcqs3377DRYWFjA1NUXbtm3RrVs3TJ48GQBQt25drfOmFy5cQHR0NCwtLWFhYQELCwvY2toiPT0dt27dQnJyMmJjY9GgQQPNNkZGRvjoo4/yPf758+dhaGiIZs2a5bu+SZMmBZrEdOvWLWRmZsLHx0fTZmxsjPr16yMqKkqrr4eHh+bfzs7OAICHDx++9RhE9GaclERlVosWLbB06VKYmJjAxcVFa3avubm5Vt/U1FR4eXlh/fr1ufZjb2+v0/HNzMyKtF5XryZohUIBAMjJySmWYxGVJaxQqcwyNzeHq6srKlas+NZLZT788EPcvHkTDg4OcHV11VpUKhVUKhWcnZ1x6tQpzTZZWVmIjIzMd59169ZFTk4Ojh49mud6Dw8P/Pnnn8jMzHzre6lWrRpMTExw/PhxTVtmZiZOnz4Nd3f3t25PREXHhEpUAD179sR7770Hf39//Pnnn7hz5w6OHDmC4cOH48GDBwCAESNGYPr06fj1119x7do1DB48GElJSfnus3LlyujTpw/69euHX3/9VbPPzZs3AwCGDh2KlJQUdO/eHWfOnMHNmzexdu3aPGflmpubY9CgQRgzZgz++OMPXL16Ff3790daWhqCgoKK5TMhIm1MqEQFUK5cORw7dgwVK1ZEp06d4ObmhqCgIKSnp8PKygoAMHr0aPTq1Qt9+vSBt7c3LC0t8fnnn79xv0uXLkXnzp0xePBg1KpVC/3798ezZ88AAHZ2djh06BBSU1PRrFkzeHl5YcWKFfmeU50+fToCAgLQq1cvfPjhh4iOjsa+fftgY2Mj7YdBRHlSCJHHrVaIiIioUFihEhERSYAJlYiISAJMqERERBJgQiUiIpIAEyoREZEEmFCJiIgkwIRKREQkASZUIiIiCTChEhERSYAJlYiISAJMqERERBJgQiUiIpLA/wMQVJBqkp3lGwAAAABJRU5ErkJggg==", "text/plain": [ "

" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "DistilBERT — F1=0.7735 | ROC-AUC=0.8561\n" ] } ], "source": [ "results_distilbert = fine_tune(\n", " model_id = 'distilbert-base-uncased',\n", " hf_train = hf_train_raw,\n", " hf_valid = hf_valid_raw,\n", " hf_test = hf_test_raw,\n", " y_test_arr = y_test_arr,\n", " model_name = 'DistilBERT base',\n", " output_dir = PROJECT_ROOT / 'models' / 'nb08_distilbert',\n", " freeze_backbone = False, # General → fine-tuning completo\n", " epochs = 5,\n", " lr = 2e-5,\n", " batch_size = 8,\n", ")\n", "print(f\"DistilBERT — F1={results_distilbert['f1']:.4f} | ROC-AUC={results_distilbert['roc_auc']:.4f}\")" ] }, { "cell_type": "markdown", "metadata": { "id": "c3a8bbc8" }, "source": [ "## 10. Fine-tuning — DistilBERT especializado en toxicidad\n", "\n", "### ¿Qué es martin-ha/toxic-comment-model?\n", "Este modelo ES DistilBERT, pero ya fue fine-tuneado en el **dataset de Jigsaw**\n", "(Wikipedia comments de toxicidad). Ya sabe mucho sobre comentarios tóxicos.\n", "\n", "### ¿Por qué congelamos el backbone?\n", "Como ya sabe de toxicidad, si actualizamos todos sus pesos con solo 700 muestras,\n", "podemos 'desaprender' lo que ya sabe (fenómeno llamado *catastrophic forgetting*).\n", "\n", "Estrategia: congelar todo el encoder y solo entrenar la cabeza clasificadora.\n", "Esto es como contratar a un experto en toxicidad y solo enseñarle el\n", "vocabulario específico de videos de YouTube." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "id": "6165b9ef" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Cargando martin-ha/toxic-comment-model...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Map: 100%|██████████| 699/699 [00:00<00:00, 11327.11 examples/s]\n", "Map: 100%|██████████| 151/151 [00:00<00:00, 9320.26 examples/s]\n", "Map: 100%|██████████| 150/150 [00:00<00:00, 10061.34 examples/s]\n", "Loading weights: 100%|██████████| 104/104 [00:00<00:00, 5300.99it/s]\n", "[transformers] warmup_ratio is deprecated and will be removed in v5.2. Use `warmup_steps` instead.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ " Últimas 2/6 capas descongeladas\n", " Entrenando 14,767,874/66,955,010 params (22.1%)\n", " Entrenando (max 5 epochs, early stopping patience=2)...\n" ] }, { "data": { "text/html": [ "\n", "
\n", " \n", " \n", " [440/440 00:42, Epoch 5/5]\n", "
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
EpochTraining LossValidation LossF1 ToxicF1 WeightedPrecisionRecallRoc Auc
10.5783620.5812880.6324790.7049440.7872340.5285710.787478
20.6468630.5478620.6776860.7350000.8039220.5857140.793122
30.5939590.5478080.6720000.7236910.7636360.6000000.793651
40.5347870.5534170.6929130.7380960.7719300.6285710.793122
50.5330640.5529720.6929130.7380960.7719300.6285710.792769

" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stderr", "output_type": "stream", "text": [ "Writing model shards: 100%|██████████| 1/1 [00:04<00:00, 4.20s/it]\n", "Writing model shards: 100%|██████████| 1/1 [00:02<00:00, 2.62s/it]\n", "Writing model shards: 100%|██████████| 1/1 [00:02<00:00, 2.55s/it]\n", "Writing model shards: 100%|██████████| 1/1 [00:02<00:00, 2.62s/it]\n", "Writing model shards: 100%|██████████| 1/1 [00:02<00:00, 2.49s/it]\n" ] }, { "data": { "text/html": [], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "=======================================================\n", "DistilBERT Toxic (fine-tuned)\n", "=======================================================\n", " precision recall f1-score support\n", "\n", " No tóxico 0.70 0.81 0.75 81\n", " Tóxico 0.73 0.59 0.66 69\n", "\n", " accuracy 0.71 150\n", " macro avg 0.72 0.70 0.71 150\n", "weighted avg 0.72 0.71 0.71 150\n", "\n" ] }, { "data": { "image/png": "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HN55qcxHH32EqKgo2NjYwNnZWWNRKpVQKpWoVKkSLl68qH7M69evERYWlus2a9eujYyMDJw6dSrH9XXq1MGZM2eQlpb2zmNxcnKCXC7HuXPn1G1paWkIDQ2Fm5vbOx9PREXHhEqUD3369EGFChXQqVMnnDlzBnfu3MHJkycxZswYPHjwAAAwduxYzJ8/H3v37kVERARGjBiBhISEXLdZpUoV+Pn5YeDAgdi7d696mzt27AAAjBo1Cs+fP0evXr1w6dIlREVFYfPmzTnOyjUxMcHw4cMxceJEHD58GDdu3MCQIUOQnJyMQYMGFctzQkSamFCJ8qFcuXI4ffo0HBwc0LVrV9SoUQODBg1CSkoKzM3NAQATJkxA37594efnBw8PD5iZmaFLly55bnfNmjXo1q0bRowYgerVq2PIkCF4+fIlAKB8+fI4fvw4kpKS0KJFC7i7u2PDhg25nlOdP38+fH190bdvX3z00Ue4desWjhw5AktLS+0+GUSUI5kQOdxqhYiIiAqEFSoREZEWMKESERFpARMqERGRFjChEhERaQETKhERkRYwoRIREWkBEyoREZEWMKESERFpARMqERGRFjChEhERaQETKhERkRYwoRIREWnB/wNB6dPX/1PC0AAAAABJRU5ErkJggg==", "text/plain": [ "

" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Toxic-DistilBERT — F1=0.7091 | ROC-AUC=0.8077\n" ] } ], "source": [ "results_toxic_distil = fine_tune(\n", " model_id = 'martin-ha/toxic-comment-model',\n", " hf_train = hf_train_raw,\n", " hf_valid = hf_valid_raw,\n", " hf_test = hf_test_raw,\n", " y_test_arr = y_test_arr,\n", " model_name = 'DistilBERT Toxic (fine-tuned)',\n", " output_dir = PROJECT_ROOT / 'models' / 'nb08_toxic_distilbert',\n", " freeze_backbone = True, # Especializado → solo entrena la cabeza\n", " unfreeze_last_n = 2,\n", " epochs = 5,\n", " lr = 3e-5, # LR más alto porque solo entrenamos la cabeza\n", " batch_size = 8, # Batch más grande porque hay menos parámetros\n", ")\n", "print(f\"Toxic-DistilBERT — F1={results_toxic_distil['f1']:.4f} | ROC-AUC={results_toxic_distil['roc_auc']:.4f}\")" ] }, { "cell_type": "markdown", "metadata": { "id": "925368ea" }, "source": [ "## 11. Fine-tuning — RoBERTa especializado en hate speech\n", "\n", "### ¿Qué es cardiffnlp/twitter-roberta-base-hate?\n", "RoBERTa es una versión mejorada de BERT (mismo tamaño, mejor entrenado).\n", "Este modelo fue fine-tuneado específicamente en **tweets de hate speech**.\n", "\n", "### ¿Por qué es potencialmente el mejor para nuestro caso?\n", "- Twitter tiene comentarios cortos y agresivos — similar a YouTube\n", "- El vocabulario incluye insultos, racismo, amenazas — exactamente lo que buscamos\n", "- RoBERTa base > DistilBERT base en calidad\n", "\n", "### ¿Por qué congelamos?\n", "Misma razón que el anterior — no queremos destruir el conocimiento ya adquirido.\n", "\n", "> Spoiler: no supera al base." ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "id": "62e274fd" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Cargando cardiffnlp/twitter-roberta-base-hate...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Map: 100%|██████████| 699/699 [00:00<00:00, 14119.99 examples/s]\n", "Map: 100%|██████████| 151/151 [00:00<00:00, 9920.12 examples/s]\n", "Map: 100%|██████████| 150/150 [00:00<00:00, 8802.07 examples/s]\n", "Loading weights: 100%|██████████| 201/201 [00:00<00:00, 4534.87it/s]\n", "[transformers] warmup_ratio is deprecated and will be removed in v5.2. Use `warmup_steps` instead.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ " Últimas 2/12 capas descongeladas\n", " Entrenando 14,767,874/124,647,170 params (11.8%)\n", " Entrenando (max 5 epochs, early stopping patience=2)...\n" ] }, { "data": { "text/html": [ "\n", "
\n", " \n", " \n", " [352/440 01:03 < 00:16, 5.48 it/s, Epoch 4/5]\n", "
\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
EpochTraining LossValidation LossF1 ToxicF1 WeightedPrecisionRecallRoc Auc
10.4671390.4047800.7801420.7947920.7746480.7857140.894709
20.4750670.3940250.7922080.7876890.7261900.8714290.907231
30.4093430.3940460.7692310.7994590.8333330.7142860.908995
40.3145350.3942130.7862070.7949730.7600000.8142860.912169

" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stderr", "output_type": "stream", "text": [ "Writing model shards: 100%|██████████| 1/1 [00:07<00:00, 7.40s/it]\n", "Writing model shards: 100%|██████████| 1/1 [00:09<00:00, 9.23s/it]\n", "Writing model shards: 100%|██████████| 1/1 [00:06<00:00, 6.20s/it]\n", "Writing model shards: 100%|██████████| 1/1 [00:04<00:00, 4.93s/it]\n" ] }, { "data": { "text/html": [], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "=======================================================\n", "RoBERTa Hate\n", "=======================================================\n", " precision recall f1-score support\n", "\n", " No tóxico 0.74 0.70 0.72 81\n", " Tóxico 0.67 0.71 0.69 69\n", "\n", " accuracy 0.71 150\n", " macro avg 0.71 0.71 0.71 150\n", "weighted avg 0.71 0.71 0.71 150\n", "\n" ] }, { "data": { "image/png": "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", "text/plain": [ "

" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "RoBERTa Hate — F1=0.7071 | ROC-AUC=0.8456\n" ] } ], "source": [ "results_roberta = fine_tune(\n", " model_id = 'cardiffnlp/twitter-roberta-base-hate',\n", " hf_train = hf_train_raw,\n", " hf_valid = hf_valid_raw,\n", " hf_test = hf_test_raw,\n", " y_test_arr = y_test_arr,\n", " model_name = 'RoBERTa Hate',\n", " output_dir = PROJECT_ROOT / 'models' / 'nb08_roberta_hate',\n", " freeze_backbone = True, # Especializado → solo cabeza\n", " unfreeze_last_n = 2,\n", " epochs = 5,\n", " lr = 3e-5,\n", " batch_size = 8,\n", ")\n", "print(f\"RoBERTa Hate — F1={results_roberta['f1']:.4f} | ROC-AUC={results_roberta['roc_auc']:.4f}\")" ] }, { "cell_type": "markdown", "metadata": { "id": "bb521b08" }, "source": [ "## 12. Tabla comparativa completa\n", "\n", "Comparamos todos los modelos sobre el **mismo test set** para\n", "que la comparación sea justa.\n", "\n", "Se incluyen:\n", "- LR baseline (del notebook 06)\n", "- Zero-shot (sin fine-tuning)\n", "- Fine-tuned (con nuestros datos)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "id": "4fc23685" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "COMPARATIVA COMPLETA — todos los modelos\n", "================================================================================\n", "Modelo Tipo F1 ROC-AUC FP FN\n", "--------------------------------------------------------------------------------\n", " DistilBERT base Fine-tuned 0.7735 0.8561 22 12 ← GANADOR\n", " DistilBERT Toxic (fine-tuned) Fine-tuned 0.7091 0.8077 15 28\n", " RoBERTa Hate Fine-tuned 0.7071 0.8456 24 20\n", " LR + TF-IDF (nb06) Baseline sklearn 0.6944 0.7794 15 30\n", " ZeroShot-DistilBERT-Toxic Zero-shot 0.6670 0.8048 12 36\n", " ZeroShot-RoBERTa-Hate Zero-shot 0.4320 0.7500 1 65\n", "\n", "Ganador: DistilBERT base\n", "F1=0.7735 | ROC-AUC=0.8561\n", "Mejora sobre LR: +7.91pp\n" ] } ], "source": [ "# Construir tabla con todos los modelos\n", "all_results = []\n", "\n", "# LR referencia\n", "if lr_ref:\n", " all_results.append({\n", " 'Modelo' : 'LR + TF-IDF (nb06)',\n", " 'Tipo' : 'Baseline sklearn',\n", " 'F1 weighted': lr_ref['f1'],\n", " 'ROC-AUC' : lr_ref['roc_auc'],\n", " 'FP' : lr_ref['fp'],\n", " 'FN' : lr_ref['fn'],\n", " })\n", "\n", "# Zero-shot\n", "for r in zero_shot_results:\n", " if r.get('f1') is not None:\n", " all_results.append({\n", " 'Modelo' : r['model'],\n", " 'Tipo' : 'Zero-shot',\n", " 'F1 weighted': r['f1'],\n", " 'ROC-AUC' : r['roc_auc'],\n", " 'FP' : r['fp'],\n", " 'FN' : r['fn'],\n", " })\n", "\n", "# Fine-tuned\n", "for res, tipo in [\n", " (results_distilbert, 'Fine-tuned'),\n", " (results_toxic_distil, 'Fine-tuned'),\n", " (results_roberta, 'Fine-tuned'),\n", "]:\n", " all_results.append({\n", " 'Modelo' : res['model'],\n", " 'Tipo' : tipo,\n", " 'F1 weighted': res['f1'],\n", " 'ROC-AUC' : res['roc_auc'],\n", " 'FP' : res['fp'],\n", " 'FN' : res['fn'],\n", " })\n", "\n", "comp_df = pd.DataFrame(all_results).sort_values('F1 weighted', ascending=False)\n", "\n", "print('COMPARATIVA COMPLETA — todos los modelos')\n", "print('=' * 80)\n", "print(f\"{'Modelo':35} {'Tipo':20} {'F1':>8} {'ROC-AUC':>9} {'FP':>4} {'FN':>4}\")\n", "print('-' * 80)\n", "for _, row in comp_df.iterrows():\n", " marker = ' ← GANADOR' if row['F1 weighted'] == comp_df['F1 weighted'].max() else ''\n", " print(f\" {row['Modelo']:33} {row['Tipo']:20} {row['F1 weighted']:>8.4f} \"\n", " f\"{row['ROC-AUC']:>9.4f} {row['FP']:>4} {row['FN']:>4}{marker}\")\n", "\n", "best_row = comp_df.iloc[0]\n", "print(f\"\\nGanador: {best_row['Modelo']}\")\n", "print(f\"F1={best_row['F1 weighted']:.4f} | ROC-AUC={best_row['ROC-AUC']:.4f}\")\n", "\n", "# Mejora sobre LR baseline\n", "if lr_ref:\n", " delta = (best_row['F1 weighted'] - lr_ref['f1']) * 100\n", " print(f\"Mejora sobre LR: {delta:+.2f}pp\")" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "id": "c285fa40" }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAABW0AAAJWCAYAAAAjjaVTAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAugJJREFUeJzs3Xd4FOX+/vF7E1IhBQIkAQIJvRepAUTAeAARRbpwRDiAhyYl5yDSiwrYEEWKchCUL02kWFAUgyhSBANIFemgkNBMQksCyfz+4JcxSwpJCNmBvF/XNde1O/vMzGdmdrNP7kyesRmGYQgAAAAAAAAAYAlOji4AAAAAAAAAAPA3QlsAAAAAAAAAsBBCWwAAAAAAAACwEEJbAAAAAAAAALCQAo4uAACA/MQwDN28eVNJSUmOLgUAgGxxdnZWgQIFZLPZHF0KAAAPPEJbAADySGJios6ePatr1645uhQAAHLE09NTgYGBcnV1dXQpAAA80GyGYRiOLgIAgAddcnKyDh8+LGdnZxUrVkyurq5cqQQAuG8YhqHExESdP39eSUlJqlChgpycGG0PAIB7hSttAQDIA4mJiUpOTlZQUJA8PT0dXQ4AANnm4eEhFxcXnTx5UomJiXJ3d3d0SQAAPLD40ygAAHmIq5IAAPczvscAAMgbfOMCAAAAAAAAgIUQ2gIAAIfbuHGjfH19zedt2rTR7Nmz87SGEydOyGazKSYmJt3Xg4ODtWbNmjytCdbF++H+0b9/f40cOdLRZdwzMTExstlsOnHihKNLAQAAuYgxbQEAcKCJLx2799uYVjbLbZs3b66tW7fKxcVFNptNpUuX1sSJE9W5c+d7WGFaX3/9dZ5uD9LaLz6559to265LltotXrxY//73v9PMv379upo3b66IiIjcLi1PLVy4UDNmzNDu3buz3aZXr17y9fXVjBkzJEk2m00eHh52/7K+detW1ahR4x5Ubq/njiX3fBsf1++e5bapf36leP311zV37tx7UZrJZrNp165dql279j3dTk5NnDhRu3fvTvNHhubNm6t9+/YaNmyYTpw4oZCQEBUsWNCuzZ9//ikfH588rBYAAKTgSlsAAGDntdde05UrVxQXF6fXX39dPXr00MmTJx1d1gPLMAwlJSU5ugxL6dGjh65cuWI3ff3113Jzc9PYsWNztM4bN27kcpXWsWXLFrtjlReBrVWl/PxKmQYOHOjoku4rf/zxh93xI7AFAMBxCG0BAEC6bDab2rZtK19fXx06dEiSdOXKFT311FMqXry4fHx81KxZM/3666/mMjt37lSjRo3k7e2tokWLql27duZr586dU48ePRQYGKgSJUpo2LBhSkhISHfbzZs3N68kTBk64X//+5+CgoLk5+enF1980a79d999pwYNGsjX11fVqlXT559/nuF+rV+/XjVr1pSXl5f8/f01YMCAdNtt27ZNJUuW1KpVq9J9PbNtfvvtt6pXr558fHwUGBiogQMH6vr16+brwcHBmjp1qho1aiRPT08dOHBANptNc+fOVfXq1eXt7a0nn3xSsbGxGe5HfvLnn3+qc+fOmjJlilq0aGHOz+wc9OrVS3369FGXLl3k7e2tuXPn6vLly3r++ecVGBiowMBA9e/fX1evXs1wu8ePH1dYWJh8fHxUpEgRNWnSRNeuXTNf//3339WoUSN5eXnpkUce0enTp83Xjhw5olatWqlIkSIqV66c+X7etWuX+vfvr71796pQoUIqVKiQTp06lYtHC7fr1auXhg0bJunvYVAWLVqk8uXLy9fXV7169bIL9Xfu3KkWLVqoSJEiKl++vObNm5fhuhs0aCBJaty4sQoVKqQpU6akGe5Fktq3b6+JEydKuvufaQkJCRowYICKFCmikJAQffrpp3dxdAAAgFUR2gIAgHQlJyfrs88+0/Xr181/+01OTlb37t11/PhxRUdHq06dOurSpYsMw5AkDR48WO3atVNMTIz+/PNPjRgxQtKtq0mffPJJBQQE6OjRo9q7d69+/fVXvfLKK1mq5fLlyzpw4IAOHz6sn376SbNmzdLGjRslSXv27FHnzp01bdo0Xbp0Se+//76effZZM2i+3XPPPacRI0bo8uXLOnbsmJ599tk0bdauXasOHTpoyZIl6tChQ5rX77RNDw8PzZs3T5cuXdLmzZv1/fffa/r06XbrWLhwoT766CNduXJFlSpVkiR98skn2rBhg06dOqU//vhDb7/9dpaOz4MsMTFRnTp10mOPPWYGb1LWzvvSpUvVp08fxcTEqE+fPho6dKiOHDmiffv2ae/evfrtt980fPjwDLc9ZswYlS9fXhcuXFB0dLTeeOMNFSjw9+hi//d//6elS5fq/PnzKliwoMaNGydJunnzpp544gnVqlVLZ86c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gtk29XEsW7ZsmvYpvz+kyE7/LPX+3L7ulN830hMTE2PUqFEjw32YNWuW2fZu+1iOPubHjx8357/44osZriMgIMA4duyY2fa5557L8NimXieAOyO0BXJB6i/U9KaMOqM5DW0jIyPNZQYOHGgYhmG89tprduu6cOGCkZiYaAZcderUMZdPHer17NnTWLdunTFnzhyjUKFChiTDz8/PuHLlimEYGYdCoaGh5vwWLVoYX3zxhTFp0iS7jklGoa2Xl5cxd+5c4//+7//MDrQkY9++fUZ8fLyxadMmo02bNub8d99919i0aZOxadMmIyYmxvjjjz/MwNjLy8uYOXOm8c033xi9e/c2l+nfv7+57UaNGpnzw8LCjC+++MJ4+eWXDWdn53RrzUt79uwx3n33XbOONm3amPv6+++/G4ZhGK1btzZfb968ufH5558b06dPN9zd3c3527ZtMwzDMNatW2fO8/DwMGbMmGGsWbPGqFevXrrvtWXLlpnzChcubHzwwQfG6tWr7QLFlGO5d+9eu+O4bt0648svvzRmzpxptGnTxvj4448z3deMQtv+/fub82vUqGGsWrXK+N///mcULlzYnL9s2TLDMAxj5syZ5ryhQ4caERERxqeffmq88sorRr169YwjR45kWkPqX4wkGS+++KLx2WefGSVLljTnFShQwHjzzTeNJUuWmJ8fZ2dnIyYmxjAMwzh16pT5RwAnJydj7Nixxtq1a43OnTub66hatar5C2HqULxOnTrGmjVrjJkzZxqenp7pfrZy4/OZnffMf/7zH3PelClTjIiICGPZsmXG2LFjjapVqxo3b97M9JgCAJBd2ek7pxfaJicnG/v377f7Y3Lnzp0z3Wbfvn3Ntlu2bDHnly5d2vx+TUxMNAzDMPz8/AxJRpkyZYxPP/3U+Pbbb4358+cbPXv2NAYPHnzH/cvsj/KSfZCbum/StWtXo2vXroYko1q1akZycrIlQ1tnZ2fj9ddfN5YvX254eXmZ8wsVKmT873//M+bMmWPOK1q0qLmO7du3m/MDAwON+fPnG+vWrbPr+0ybNs1sn9XfHwwj+/2z29+DPXr0MNauXWt8/PHHZh88PYMGDTKXefzxx81lUv5Y7urqapw6dcowjLvvYzn6mKcErNu2bTPnubu7G2+++abx+eefGy1atDDnt27d2lxH6tBWkjFkyBBj3bp1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22/VoUMHcyzZhx56SAcOHLD7hSFlysp4u1mRF9sAAAB4EERGRio5OVlvvfWWGjVqpIoVK+rMmTN3XC6jvl6VKlW0efNmu7abN29WxYoVzTFiCxQooLCwML3++uvas2ePTpw4oQ0bNmS6vZCQEJUrV05eXl528zPaXtWqVc3nHh4eateund59911t3LhRW7du1d69e9PdjouLi5KSku64/z169NDixYv1xRdfyMnJyRy2614eg3uJ4REAAAByUWxsrN2wBZLk5+enoKCgdNsPHTpU1atX1y+//KJ69epluN4VK1aoXr16atq0qRYvXqzt27dr/vz5km6NWXbq1CktW7ZM9evX19q1a+2urLh+/bpGjBihTp06KSQkRH/88Yd27NhhjvE1cuRINWrUSIMHD1bfvn1VsGBBHThwQOvXr9d77713l0dEebYNAACAB0H58uV148YNzZw5U+3atdPmzZs1d+7cDNvfqa/3n//8R/Xr19fLL7+srl27auvWrXrvvffM8XG//PJLHTt2TM2aNVPhwoX11VdfKTk5WZUqVcpR/SNGjFCXLl1Up04dhYWF6YsvvtCqVav03XffSZIWLlyopKQkNWzYUJ6envq///s/eXh4qEyZMumuLzg4WBEREWrSpInc3NxUuHDhdNv16NFDEydO1KuvvqpOnTrJzc3NfC2vj0FuILQFAADIRRs3bkxz04I+ffrof//7X7rtq1atqn/84x8aP368vvrqqwzXO2nSJC1btkwDBw5UYGCgli5dal6t8OSTT2r48OEaPHiwEhIS1LZtW40bN04TJ06UdOvmDBcvXlTPnj0VHR2tokWLqkOHDpo0aZKkW2PR/vDDDxozZowefvhhGYahcuXKqWvXrrlwRJRn2wAAAEjN79X0+19WV6tWLU2fPl2vvfaaRo0apWbNmmnq1Knq2bNnuu3v1Nd76KGH9Mknn2j8+PF6+eWXFRgYqMmTJ6tXr16Sbt3ka9WqVZo4caLi4+NVoUIFLV26VNWqVctR/e3bt9c777yjN998U0OHDlVISIgWLFig5s2bm9ubNm2awsPDlZSUpBo1auiLL76Qn59fuut76623FB4ernnz5qlkyZI6ceJEuu3Kly+vBg0aaPv27ZoxY4bda3l9DHKDzTAMw2Fbz6K4uDj5+PgoNjbW7oYaAADgwRQfH6/jx48rJCRE7u7u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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Guardado en reports/v2/nb08_comparativa_final.png\n" ] } ], "source": [ "# Visualización comparativa\n", "fig, axes = plt.subplots(1, 2, figsize=(14, 6))\n", "\n", "colors = ['#7F77DD' if 'LR' in r['Modelo'] else\n", " '#B4B2A9' if 'Zero' in r['Tipo'] else\n", " '#5DCAA5'\n", " for r in all_results]\n", "\n", "models_short = [r['Modelo'].replace('(fine-tuned)','').replace('(nb06)','').strip()\n", " for r in all_results]\n", "\n", "axes[0].bar(range(len(all_results)),\n", " [r['F1 weighted'] for r in all_results],\n", " color=colors, width=0.6)\n", "axes[0].set_xticks(range(len(all_results)))\n", "axes[0].set_xticklabels(models_short, rotation=30, ha='right', fontsize=9)\n", "axes[0].set_title('F1 weighted — todos los modelos', fontweight='bold')\n", "axes[0].set_ylim(0.5, 1.0)\n", "axes[0].axhline(lr_ref['f1'] if lr_ref else 0.75,\n", " color='red', linestyle='--', alpha=0.5, label='LR baseline')\n", "axes[0].legend()\n", "\n", "# FP vs FN\n", "x = range(len(all_results))\n", "fps = [r['FP'] for r in all_results]\n", "fns = [r['FN'] for r in all_results]\n", "w = 0.35\n", "axes[1].bar([i-w/2 for i in x], fps, w, label='Falsos Positivos', color='#E8593C', alpha=0.8)\n", "axes[1].bar([i+w/2 for i in x], fns, w, label='Falsos Negativos', color='#5DCAA5', alpha=0.8)\n", "axes[1].set_xticks(list(x))\n", "axes[1].set_xticklabels(models_short, rotation=30, ha='right', fontsize=9)\n", "axes[1].set_title('FP vs FN — menor es mejor', fontweight='bold')\n", "axes[1].legend()\n", "\n", "from matplotlib.patches import Patch\n", "legend_els = [\n", " Patch(facecolor='#7F77DD', label='Baseline sklearn'),\n", " Patch(facecolor='#B4B2A9', label='Zero-shot HF'),\n", " Patch(facecolor='#5DCAA5', label='Fine-tuned HF'),\n", "]\n", "fig.legend(handles=legend_els, loc='upper center', ncol=3, fontsize=9)\n", "\n", "plt.tight_layout(rect=[0, 0, 1, 0.93])\n", "plt.savefig(PROJECT_ROOT / 'reports' / 'v2' / 'nb08_comparativa_final.png',\n", " dpi=150, bbox_inches='tight')\n", "plt.show()\n", "print('Guardado en reports/v2/nb08_comparativa_final.png')" ] }, { "cell_type": "markdown", "metadata": { "id": "682053d7" }, "source": [ "## 13. Análisis de errores del modelo ganador\n", "\n", "Analizamos qué tipos de comentarios el modelo ganador sigue fallando.\n", "Esto es importante porque nos dice si el problema es el modelo\n", "o el dataset." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "id": "7cae7a29" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Análisis de errores: DistilBERT base\n", "Total test : 150\n", "Errores : 34\n", "Falsos Pos : 22 (censuró comentarios OK)\n", "Falsos Neg : 12 (hate speech que se escapó)\n" ] } ], "source": [ "# Identificar el modelo ganador entre los fine-tuned\n", "ft_results = [results_distilbert, results_toxic_distil, results_roberta]\n", "best_ft = max(ft_results, key=lambda r: r['f1'])\n", "best_name = best_ft['model']\n", "best_preds = best_ft['preds']\n", "best_probs = best_ft['probs']\n", "\n", "print(f'Análisis de errores: {best_name}')\n", "\n", "error_df = pd.DataFrame({\n", " 'text' : X_test.values,\n", " 'real' : y_test_arr,\n", " 'pred' : best_preds,\n", " 'prob_toxic': best_probs,\n", "})\n", "error_df['error'] = error_df['real'] != error_df['pred']\n", "\n", "fp_df = error_df[(error_df['real']==0) & (error_df['pred']==1)]\n", "fn_df = error_df[(error_df['real']==1) & (error_df['pred']==0)]\n", "\n", "print(f'Total test : {len(error_df)}')\n", "print(f'Errores : {error_df[\"error\"].sum()}')\n", "print(f'Falsos Pos : {len(fp_df)} (censuró comentarios OK)')\n", "print(f'Falsos Neg : {len(fn_df)} (hate speech que se escapó)')" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "id": "223d5a8f" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "FALSOS NEGATIVOS — hate speech que NO detectó:\n", "----------------------------------------------------------------------\n", " Prob: 0.467 | They are protecting and serving us, from people like Michael Brown. The guy deserved to be killed, cry more about it...\n", "\n", " Prob: 0.452 | So the autopsy showed a number of wounds to the right arm making the scenario of him being shot with his hands raised a \n", "\n", " Prob: 0.233 | Let's get this straight and present the facts as the mass media should have from the beginning. 18 yr old (by all legal \n", "\n", " Prob: 0.071 | Ah, beautiful.\n", "\n", " Prob: 0.251 | Remember that time every other race rioted because someone of their race got shot by a white cop after attacking the off\n", "\n", " Prob: 0.368 | finally a black person with a unbiased opinion. An incredibly high percentage of black lives are lost among themselves a\n", "\n", "FALSOS POSITIVOS — comentarios OK mal censurados:\n", "----------------------------------------------------------------------\n", " Prob: 0.851 | Thats a real parent, a real mother. Nothing but real talk right there. She learned well from her mom.  A voice of truth \n", "\n", " Prob: 0.862 | Its funny doctors push drugs its legal, even tho prescription drugs are abused the most, whereas minorities get locked u\n", "\n", " Prob: 0.932 | Who the fuck has time to be on the freeway???\n", "\n", " Prob: 0.643 | police shot 1 black guy , & then the blacks riot ,!! when a black shoot a black , what happens ?? ,,,,,,,,,,,,,, ?\n", "\n", " Prob: 0.927 | You see if Blacks speak the truth and don't conform to the norm they are considered Uncle Tom's and sell outs\n", "\n", " Prob: 0.800 | In the point they almost set a person on fire\n", "\n" ] } ], "source": [ "print('FALSOS NEGATIVOS — hate speech que NO detectó:')\n", "print('-' * 70)\n", "for _, row in fn_df.head(6).iterrows():\n", " print(f' Prob: {row[\"prob_toxic\"]:.3f} | {row[\"text\"][:120]}')\n", " print()\n", "\n", "print('FALSOS POSITIVOS — comentarios OK mal censurados:')\n", "print('-' * 70)\n", "for _, row in fp_df.head(6).iterrows():\n", " print(f' Prob: {row[\"prob_toxic\"]:.3f} | {row[\"text\"][:120]}')\n", " print()" ] }, { "cell_type": "markdown", "metadata": { "id": "9e0cb6a2" }, "source": [ "## 14. Registro en MLflow\n", "\n", "Registramos todos los resultados en el mismo experimento del proyecto." ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "id": "5c141683" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " ✅ LR + TF-IDF (nb06)\n", " ✅ ZeroShot-DistilBERT-Toxic\n", " ✅ ZeroShot-RoBERTa-Hate\n", " ✅ DistilBERT base\n", " ✅ DistilBERT Toxic (fine-tuned)\n", " ✅ RoBERTa Hate\n", "MLflow actualizado\n" ] } ], "source": [ "MLFLOW_DIR = PROJECT_ROOT / 'mlruns'\n", "mlflow.set_tracking_uri(f'file://{MLFLOW_DIR}')\n", "mlflow.set_experiment('Youtube_project_experiment')\n", "\n", "for row in all_results:\n", " with mlflow.start_run(run_name=row['Modelo'].replace(' ','_')[:30]):\n", " mlflow.log_param('model', row['Modelo'])\n", " mlflow.log_param('type', row['Tipo'])\n", " mlflow.log_param('notebook', '08_transformers')\n", " mlflow.log_metric('f1_weighted', row['F1 weighted'])\n", " mlflow.log_metric('roc_auc', row['ROC-AUC'])\n", " mlflow.log_metric('fp', row['FP'])\n", " mlflow.log_metric('fn', row['FN'])\n", " print(f' ✅ {row[\"Modelo\"]}')\n", "\n", "mlflow.log_artifact(str(PROJECT_ROOT / 'reports' / 'v2' / 'nb08_comparativa_final.png'))\n", "print('MLflow actualizado')" ] }, { "cell_type": "markdown", "metadata": { "id": "e86e6d2d" }, "source": [ "## 15. Guardar el modelo ganador\n", "\n", "Guardamos en `models/finetuned_hf/` que es exactamente la ruta\n", "que espera `model_service.py` para el modelo 'Modelo fine-tuneado (local)'.\n", "\n", "Esto significa que una vez ejecutado este notebook, el Streamlit\n", "puede cargar y usar el modelo directamente." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "id": "bff0d4a6" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Guardando DistilBERT base en /mnt/c/Users/under/Documents/F5/3_Projects/Project_9_Equipo3/Project_YT/models/finetuned_hf...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Writing model shards: 100%|██████████| 1/1 [00:03<00:00, 3.21s/it]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "✅ Modelo guardado en: /mnt/c/Users/under/Documents/F5/3_Projects/Project_9_Equipo3/Project_YT/models/finetuned_hf\n", " El Streamlit lo carga como \"Modelo fine-tuneado (local)\"\n", " en Settings → selección de modelo\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "SAVE_PATH = PROJECT_ROOT / 'models' / 'finetuned_hf'\n", "\n", "print(f'Guardando {best_name} en {SAVE_PATH}...')\n", "\n", "best_ft['trainer'].save_model(str(SAVE_PATH))\n", "best_ft['tokenizer'].save_pretrained(str(SAVE_PATH))\n", "\n", "# Guardar metadata para saber qué modelo es\n", "meta = {\n", " 'model_name' : best_name,\n", " 'f1_weighted' : best_ft['f1'],\n", " 'roc_auc' : best_ft['roc_auc'],\n", " 'fp' : best_ft['fp'],\n", " 'fn' : best_ft['fn'],\n", " 'notebook' : '08_transformers_finetuning',\n", "}\n", "with open(SAVE_PATH / 'model_metadata.json', 'w') as f:\n", " json.dump(meta, f, indent=2)\n", "\n", "print(f'✅ Modelo guardado en: {SAVE_PATH}')\n", "print(f' El Streamlit lo carga como \"Modelo fine-tuneado (local)\"')\n", "print(f' en Settings → selección de modelo')" ] }, { "cell_type": "markdown", "metadata": { "id": "3b66bcef" }, "source": [ "## 16. Conclusiones y decisiones" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "id": "ef809e7a" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "CONCLUSIONES — TRANSFORMERS vs LR+TF-IDF\n", "=======================================================\n", "Modelos comparados: 6\n", "\n", "Referencia LR + TF-IDF (nb06): F1=0.6944\n", "\n", "Mejor modelo Transformer: DistilBERT base\n", " F1 weighted : 0.7735\n", " ROC-AUC : 0.8561\n", " FP / FN : 22 / 12\n", " Mejora vs LR : +7.91pp\n", "\n", "¿Por que Transformers mejoran?\n", " Los modelos pre-entrenados entienden el contexto:\n", " 'black thug' != 'black' + 'thug' por separado.\n", " TF-IDF trata cada palabra de forma independiente.\n", "\n", "Modelo guardado:\n", " models/finetuned_hf/ → listo para el Streamlit\n", " Cargar en Settings como 'Modelo fine-tuneado (local)'\n", "\n", "Limitación que persiste:\n", " Con 700 muestras de train de solo 8 videos,\n", " el gap de generalización sigue siendo un desafío.\n", " La solución real es mas datos de dominios diversos.\n", "\n" ] } ], "source": [ "lr_f1 = lr_ref['f1'] if lr_ref else 0.75\n", "delta = (best_ft['f1'] - lr_f1) * 100\n", "\n", "print(f\"\"\"\n", "CONCLUSIONES — TRANSFORMERS vs LR+TF-IDF\n", "{'='*55}\n", "Modelos comparados: {len(all_results)}\n", "\n", "Referencia LR + TF-IDF (nb06): F1={lr_f1:.4f}\n", "\n", "Mejor modelo Transformer: {best_name}\n", " F1 weighted : {best_ft['f1']:.4f}\n", " ROC-AUC : {best_ft['roc_auc']:.4f}\n", " FP / FN : {best_ft['fp']} / {best_ft['fn']}\n", " Mejora vs LR : {delta:+.2f}pp\n", "\n", "¿Por que Transformers mejoran?\n", " Los modelos pre-entrenados entienden el contexto:\n", " 'black thug' != 'black' + 'thug' por separado.\n", " TF-IDF trata cada palabra de forma independiente.\n", "\n", "Modelo guardado:\n", " models/finetuned_hf/ → listo para el Streamlit\n", " Cargar en Settings como 'Modelo fine-tuneado (local)'\n", "\n", "Limitación que persiste:\n", " Con 700 muestras de train de solo 8 videos,\n", " el gap de generalización sigue siendo un desafío.\n", " La solución real es mas datos de dominios diversos.\n", "\"\"\")" ] } ], "metadata": { "colab": { "provenance": [] }, "kernelspec": { "display_name": "py310", "language": "python", "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.20" } }, "nbformat": 4, "nbformat_minor": 0 }