diff --git "a/notebooks/08_transformers_v2.ipynb" "b/notebooks/08_transformers_v2.ipynb"
deleted file mode 100644--- "a/notebooks/08_transformers_v2.ipynb"
+++ /dev/null
@@ -1,1923 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "07aa1c3f",
- "metadata": {},
- "source": [
- "\n",
- "# Transformers Fine-Tuning\n",
- "\n",
- "---\n",
- "\n",
- "# Estructura\n",
- "\n",
- "0. Imports y configuración \n",
- "1. Reproducibilidad \n",
- "2. Carga de datos \n",
- "3. Split correcto \n",
- "4. EDA rápida \n",
- "5. Helper functions \n",
- "6. HuggingFace datasets \n",
- "7. Baseline — DistilBERT \n",
- "8. Evaluación DistilBERT \n",
- "9. Fine-tuning — RoBERTa Hate \n",
- "10. Evaluación RoBERTa Hate \n",
- "11. Comparación de modelos \n",
- "12. Error Analysis \n",
- "13. Guardado del mejor modelo \n"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "ab6cd7a5",
- "metadata": {},
- "source": [
- "## 0. Imports y configuración"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "072caf60",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "==================================================\n",
- "DEVICE INFO\n",
- "==================================================\n",
- "Torch version: 2.12.0+cu132\n",
- "Device: cuda\n",
- "GPU: NVIDIA GeForce RTX 2060\n"
- ]
- }
- ],
- "source": [
- "import os\n",
- "import sys\n",
- "import yaml\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",
- "\n",
- "from pathlib import Path\n",
- "from datasets import Dataset\n",
- "\n",
- "from sklearn.model_selection import train_test_split\n",
- "from sklearn.metrics import (\n",
- " classification_report,\n",
- " confusion_matrix,\n",
- " accuracy_score,\n",
- " precision_score,\n",
- " recall_score,\n",
- " f1_score,\n",
- " roc_auc_score,\n",
- ")\n",
- "\n",
- "from transformers import (\n",
- " AutoTokenizer,\n",
- " AutoModelForSequenceClassification,\n",
- " DataCollatorWithPadding,\n",
- " TrainingArguments,\n",
- " Trainer,\n",
- " EarlyStoppingCallback,\n",
- ")\n",
- "\n",
- "warnings.filterwarnings(\"ignore\")\n",
- "\n",
- "PROJECT_ROOT = Path.cwd().parent\n",
- "sys.path.insert(0, str(PROJECT_ROOT))\n",
- "\n",
- "CONFIG_PIPE = PROJECT_ROOT / \"configs\" / \"pipeline.yaml\"\n",
- "\n",
- "with open(CONFIG_PIPE) 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",
- "\n",
- "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
- "\n",
- "print(\"=\" * 50)\n",
- "print(\"DEVICE INFO\")\n",
- "print(\"=\" * 50)\n",
- "\n",
- "print(\"Torch version:\", torch.__version__)\n",
- "print(\"Device:\", device)\n",
- "\n",
- "if torch.cuda.is_available():\n",
- " print(\"GPU:\", torch.cuda.get_device_name(0))\n",
- "else:\n",
- " print(\"⚠️ GPU no detectada\")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "178bae13",
- "metadata": {},
- "source": [
- "## 1. Reproducibilidad"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "0b9084dc",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Seed configurado: 42\n"
- ]
- }
- ],
- "source": [
- "def set_seed(seed=42):\n",
- "\n",
- " random.seed(seed)\n",
- " np.random.seed(seed)\n",
- "\n",
- " torch.manual_seed(seed)\n",
- "\n",
- " if torch.cuda.is_available():\n",
- " torch.cuda.manual_seed_all(seed)\n",
- "\n",
- " torch.backends.cudnn.deterministic = True\n",
- " torch.backends.cudnn.benchmark = False\n",
- "\n",
- "\n",
- "set_seed(RAND)\n",
- "\n",
- "print(\"Seed configurado:\", RAND)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "e4800e74",
- "metadata": {},
- "source": [
- "## 2. Carga de datos"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "0fb40c48",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(1000, 9)\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "
"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "train_lengths = X_train.str.split().apply(len)\n",
- "\n",
- "print(train_lengths.describe())\n",
- "\n",
- "plt.figure(figsize=(10, 5))\n",
- "\n",
- "sns.histplot(train_lengths, bins=40)\n",
- "\n",
- "plt.title(\"Distribución de longitud de comentarios\")\n",
- "plt.xlabel(\"Número de palabras\")\n",
- "\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "ad7e7704",
- "metadata": {},
- "source": [
- "## 5. Helper Functions"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "836d5be7",
- "metadata": {},
- "outputs": [],
- "source": [
- "def build_hf_dataset(X, y):\n",
- "\n",
- " df_local = pd.DataFrame({\n",
- " \"text\": X.values,\n",
- " \"label\": y.astype(int).values,\n",
- " })\n",
- "\n",
- " return Dataset.from_pandas(df_local)\n",
- "\n",
- "\n",
- "def tokenize_dataset(dataset, tokenizer, max_len):\n",
- "\n",
- " def tokenize(batch):\n",
- "\n",
- " return tokenizer(\n",
- " batch[\"text\"],\n",
- " truncation=True,\n",
- " max_length=max_len,\n",
- " )\n",
- "\n",
- " dataset = dataset.map(tokenize, batched=True)\n",
- "\n",
- " dataset = dataset.remove_columns([\"text\"])\n",
- "\n",
- " dataset.set_format(\"torch\")\n",
- "\n",
- " return dataset\n",
- "\n",
- "\n",
- "def compute_metrics(eval_pred):\n",
- "\n",
- " logits, labels = eval_pred\n",
- "\n",
- " probs = torch.softmax(\n",
- " torch.tensor(logits),\n",
- " dim=1\n",
- " )[:, 1].numpy()\n",
- "\n",
- " preds = np.argmax(logits, axis=1)\n",
- "\n",
- " return {\n",
- "\n",
- " \"accuracy\": accuracy_score(labels, preds),\n",
- "\n",
- " \"precision_toxic\": precision_score(\n",
- " labels,\n",
- " preds,\n",
- " pos_label=1,\n",
- " ),\n",
- "\n",
- " \"recall_toxic\": recall_score(\n",
- " labels,\n",
- " preds,\n",
- " pos_label=1,\n",
- " ),\n",
- "\n",
- " \"f1_toxic\": f1_score(\n",
- " labels,\n",
- " preds,\n",
- " pos_label=1,\n",
- " ),\n",
- "\n",
- " \"roc_auc\": roc_auc_score(labels, probs),\n",
- " }\n",
- "\n",
- "\n",
- "def evaluate_model(trainer, hf_test, y_test, model_name):\n",
- "\n",
- " pred_output = trainer.predict(hf_test)\n",
- "\n",
- " logits = pred_output.predictions\n",
- "\n",
- " probs = torch.softmax(\n",
- " torch.tensor(logits),\n",
- " dim=1\n",
- " )[:, 1].numpy()\n",
- "\n",
- " preds = np.argmax(logits, axis=1)\n",
- "\n",
- " print(\"=\" * 60)\n",
- " print(model_name)\n",
- " print(\"=\" * 60)\n",
- "\n",
- " print(classification_report(\n",
- " y_test,\n",
- " preds,\n",
- " target_names=[\"No tóxico\", \"Tóxico\"]\n",
- " ))\n",
- "\n",
- " cm = confusion_matrix(y_test, preds)\n",
- "\n",
- " plt.figure(figsize=(6, 5))\n",
- "\n",
- " sns.heatmap(\n",
- " cm,\n",
- " annot=True,\n",
- " fmt=\"d\",\n",
- " cmap=\"Blues\",\n",
- " xticklabels=[\"No tóxico\", \"Tóxico\"],\n",
- " yticklabels=[\"No tóxico\", \"Tóxico\"],\n",
- " )\n",
- "\n",
- " plt.title(f\"{model_name} — Confusion Matrix\")\n",
- "\n",
- " plt.xlabel(\"Predicción\")\n",
- " plt.ylabel(\"Real\")\n",
- "\n",
- " plt.savefig(PROJECT_ROOT / 'reports' / 'v2' / f\"{model_name}_confusion.png\",\n",
- " dpi=150, bbox_inches='tight')\n",
- "\n",
- " plt.show()\n",
- "\n",
- " return {\n",
- " \"accuracy\": accuracy_score(y_test, preds),\n",
- " \"precision\": precision_score(y_test, preds),\n",
- " \"recall\": recall_score(y_test, preds),\n",
- " \"f1\": f1_score(y_test, preds),\n",
- " \"roc_auc\": roc_auc_score(y_test, probs),\n",
- " \"preds\": preds,\n",
- " \"probs\": probs,\n",
- " }"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "988496e6",
- "metadata": {},
- "source": [
- "## 6. HuggingFace Dataset"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "f6f76741",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Dataset({\n",
- " features: ['text', 'label'],\n",
- " num_rows: 699\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(hf_train_raw)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "7986014a",
- "metadata": {},
- "source": [
- "\n",
- "# 7. Baseline — DistilBERT\n",
- "\n",
- "DistilBERT será el baseline generalista.\n",
- "\n",
- "Ventajas:\n",
- "- más liviano\n",
- "- rápido\n",
- "- estable\n",
- "- ideal para datasets pequeños\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "1e8f8d34",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "distilbert-base-uncased\n"
- ]
- }
- ],
- "source": [
- "DISTIL_MODEL = \"distilbert-base-uncased\"\n",
- "\n",
- "MAX_LEN = 128\n",
- "BATCH_SIZE = 8\n",
- "EPOCHS = 3\n",
- "LR = 2e-5\n",
- "\n",
- "print(DISTIL_MODEL)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "b9ee6361",
- "metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "Map: 100%|██████████| 699/699 [00:00<00:00, 9167.52 examples/s]\n",
- "Map: 100%|██████████| 151/151 [00:00<00:00, 8833.19 examples/s]\n",
- "Map: 100%|██████████| 150/150 [00:00<00:00, 10128.07 examples/s]\n"
- ]
- }
- ],
- "source": [
- "distil_tokenizer = AutoTokenizer.from_pretrained(\n",
- " DISTIL_MODEL\n",
- ")\n",
- "\n",
- "distil_train = tokenize_dataset(\n",
- " hf_train_raw,\n",
- " distil_tokenizer,\n",
- " MAX_LEN,\n",
- ")\n",
- "\n",
- "distil_valid = tokenize_dataset(\n",
- " hf_valid_raw,\n",
- " distil_tokenizer,\n",
- " MAX_LEN,\n",
- ")\n",
- "\n",
- "distil_test = tokenize_dataset(\n",
- " hf_test_raw,\n",
- " distil_tokenizer,\n",
- " MAX_LEN,\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "8e867b40",
- "metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "Loading weights: 100%|██████████| 100/100 [00:00<00:00, 1192.80it/s]\n",
- "[transformers] \u001b[1mDistilBertForSequenceClassification LOAD REPORT\u001b[0m from: distilbert-base-uncased\n",
- "Key | Status | \n",
- "------------------------+------------+-\n",
- "vocab_transform.bias | UNEXPECTED | \n",
- "vocab_projector.bias | UNEXPECTED | \n",
- "vocab_layer_norm.weight | UNEXPECTED | \n",
- "vocab_transform.weight | UNEXPECTED | \n",
- "vocab_layer_norm.bias | UNEXPECTED | \n",
- "classifier.weight | MISSING | \n",
- "classifier.bias | MISSING | \n",
- "pre_classifier.bias | MISSING | \n",
- "pre_classifier.weight | 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"
- ]
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "DistilBertForSequenceClassification\n"
- ]
- }
- ],
- "source": [
- "distil_collator = DataCollatorWithPadding(tokenizer=distil_tokenizer)\n",
- "\n",
- "distil_model = AutoModelForSequenceClassification.from_pretrained(\n",
- " DISTIL_MODEL,\n",
- " num_labels=2,\n",
- ")\n",
- "\n",
- "distil_model.to(device)\n",
- "\n",
- "print(distil_model.__class__.__name__)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "ed09755c",
- "metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "[transformers] warmup_ratio is deprecated and will be removed in v5.2. Use `warmup_steps` instead.\n"
- ]
- }
- ],
- "source": [
- "distil_args = TrainingArguments(\n",
- "\n",
- " output_dir= PROJECT_ROOT / \"models\" / \"distilbert_results\",\n",
- "\n",
- " learning_rate=LR,\n",
- "\n",
- " num_train_epochs=EPOCHS,\n",
- "\n",
- " per_device_train_batch_size=BATCH_SIZE,\n",
- " per_device_eval_batch_size=BATCH_SIZE,\n",
- "\n",
- " weight_decay=0.01,\n",
- "\n",
- " eval_strategy=\"epoch\",\n",
- " save_strategy=\"epoch\",\n",
- "\n",
- " load_best_model_at_end=True,\n",
- "\n",
- " metric_for_best_model=\"f1_toxic\",\n",
- " greater_is_better=True,\n",
- "\n",
- " warmup_ratio=0.1,\n",
- "\n",
- " logging_steps=10,\n",
- "\n",
- " fp16=torch.cuda.is_available(),\n",
- "\n",
- " report_to=\"none\",\n",
- "\n",
- " seed=RAND,\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "827eed3d",
- "metadata": {},
- "outputs": [],
- "source": [
- "distil_early_stopping = EarlyStoppingCallback(early_stopping_patience=2)\n",
- "\n",
- "distil_trainer = Trainer(\n",
- "\n",
- " model=distil_model,\n",
- "\n",
- " args=distil_args,\n",
- "\n",
- " train_dataset=distil_train,\n",
- " eval_dataset=distil_valid,\n",
- "\n",
- " processing_class=distil_tokenizer,\n",
- "\n",
- " data_collator=distil_collator,\n",
- "\n",
- " compute_metrics=compute_metrics,\n",
- "\n",
- " callbacks=[distil_early_stopping],\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "eea8b514",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "==================================================\n",
- "TRAINING DISTILBERT\n",
- "==================================================\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "\n",
- " \n",
- " \n",
- "
\n",
- " [264/264 00:38, Epoch 3/3]\n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " Epoch \n",
- " Training Loss \n",
- " Validation Loss \n",
- " Accuracy \n",
- " Precision Toxic \n",
- " Recall Toxic \n",
- " F1 Toxic \n",
- " Roc Auc \n",
- " \n",
- " \n",
- " \n",
- " \n",
- " 1 \n",
- " 0.562122 \n",
- " 0.536817 \n",
- " 0.715232 \n",
- " 0.721311 \n",
- " 0.628571 \n",
- " 0.671756 \n",
- " 0.808818 \n",
- " \n",
- " \n",
- " 2 \n",
- " 0.417088 \n",
- " 0.541987 \n",
- " 0.754967 \n",
- " 0.698795 \n",
- " 0.828571 \n",
- " 0.758170 \n",
- " 0.833510 \n",
- " \n",
- " \n",
- " 3 \n",
- " 0.316711 \n",
- " 0.569083 \n",
- " 0.768212 \n",
- " 0.753623 \n",
- " 0.742857 \n",
- " 0.748201 \n",
- " 0.823986 \n",
- " \n",
- " \n",
- "
"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "Writing model shards: 100%|██████████| 1/1 [00:02<00:00, 2.02s/it]\n",
- "Writing model shards: 100%|██████████| 1/1 [00:02<00:00, 2.25s/it]\n",
- "Writing model shards: 100%|██████████| 1/1 [00:02<00:00, 2.22s/it]\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "TrainOutput(global_step=264, training_loss=0.44362344886317395, metrics={'train_runtime': 36.2928, 'train_samples_per_second': 57.78, 'train_steps_per_second': 7.274, 'total_flos': 54207108392208.0, 'train_loss': 0.44362344886317395, 'epoch': 3.0})"
- ]
- },
- "execution_count": 83,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "print(\"=\" * 50)\n",
- "print(\"TRAINING DISTILBERT\")\n",
- "print(\"=\" * 50)\n",
- "\n",
- "distil_trainer.train()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "0b64fe6f",
- "metadata": {},
- "source": [
- "## 8. Evaluación — DistilBERT"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "9647c651",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "============================================================\n",
- "DistilBERT\n",
- "============================================================\n",
- " precision recall f1-score support\n",
- "\n",
- " No tóxico 0.82 0.72 0.76 81\n",
- " Tóxico 0.71 0.81 0.76 69\n",
- "\n",
- " accuracy 0.76 150\n",
- " macro avg 0.76 0.76 0.76 150\n",
- "weighted avg 0.77 0.76 0.76 150\n",
- "\n"
- ]
- },
- {
- "data": {
- "image/png": "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",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "distil_results = evaluate_model(\n",
- " distil_trainer,\n",
- " distil_test,\n",
- " y_test,\n",
- " \"DistilBERT\",\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "92d5d1bc",
- "metadata": {},
- "source": [
- "\n",
- "# 9. Fine-Tuning especializado — RoBERTa Hate\n",
- "\n",
- "Modelo especializado en:\n",
- "- hate speech\n",
- "- toxicidad\n",
- "- abuso online\n",
- "\n",
- "Modelo:\n",
- "cardiffnlp/twitter-roberta-base-hate\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "40cbdf8d",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "cardiffnlp/twitter-roberta-base-hate\n"
- ]
- }
- ],
- "source": [
- "HATE_MODEL = \"cardiffnlp/twitter-roberta-base-hate\"\n",
- "\n",
- "MAX_LEN = 128\n",
- "BATCH_SIZE = 8\n",
- "EPOCHS = 3\n",
- "LR = 2e-5\n",
- "\n",
- "print(HATE_MODEL)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "6d0d9245",
- "metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "Map: 100%|██████████| 699/699 [00:00<00:00, 13631.74 examples/s]\n",
- "Map: 100%|██████████| 151/151 [00:00<00:00, 9566.49 examples/s]\n",
- "Map: 100%|██████████| 150/150 [00:00<00:00, 10121.39 examples/s]\n"
- ]
- }
- ],
- "source": [
- "hate_tokenizer = AutoTokenizer.from_pretrained(\n",
- " HATE_MODEL\n",
- ")\n",
- "\n",
- "hate_train = tokenize_dataset(\n",
- " hf_train_raw,\n",
- " hate_tokenizer,\n",
- " MAX_LEN,\n",
- ")\n",
- "\n",
- "hate_valid = tokenize_dataset(\n",
- " hf_valid_raw,\n",
- " hate_tokenizer,\n",
- " MAX_LEN,\n",
- ")\n",
- "\n",
- "hate_test = tokenize_dataset(\n",
- " hf_test_raw,\n",
- " hate_tokenizer,\n",
- " MAX_LEN,\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "5114bb65",
- "metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "Loading weights: 100%|██████████| 201/201 [00:00<00:00, 5778.78it/s]\n"
- ]
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "RobertaForSequenceClassification\n"
- ]
- }
- ],
- "source": [
- "hate_collator = DataCollatorWithPadding(tokenizer=hate_tokenizer)\n",
- "\n",
- "hate_model = AutoModelForSequenceClassification.from_pretrained(\n",
- " HATE_MODEL,\n",
- " num_labels=2,\n",
- " ignore_mismatched_sizes=True,\n",
- ")\n",
- "\n",
- "hate_model.to(device)\n",
- "\n",
- "print(hate_model.__class__.__name__)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "9fb50f46",
- "metadata": {},
- "source": [
- "## 10. Fine-Tuning controlado"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "c3729fb1",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Classification head desbloqueada\n",
- "\n",
- "Trainable params: 592,130\n",
- "Total params: 124,647,170\n",
- "Trainable %: 0.48%\n"
- ]
- }
- ],
- "source": [
- "# Congelar backbone\n",
- "\n",
- "for param in hate_model.base_model.parameters():\n",
- " param.requires_grad = False\n",
- "\n",
- "# Classification head entrenable\n",
- "classifier_found = False\n",
- "\n",
- "for name, param in hate_model.named_parameters():\n",
- "\n",
- " if \"classifier\" in name:\n",
- "\n",
- " param.requires_grad = True\n",
- " classifier_found = True\n",
- "\n",
- "if classifier_found:\n",
- " print(\"Classification head desbloqueada\")\n",
- "else:\n",
- " print(\"⚠️ No se encontró classifier head\")\n",
- "\n",
- "# Verificación\n",
- "total_params = 0\n",
- "trainable_params = 0\n",
- "\n",
- "for p in hate_model.parameters():\n",
- "\n",
- " total_params += p.numel()\n",
- "\n",
- " if p.requires_grad:\n",
- " trainable_params += p.numel()\n",
- "\n",
- "pct = trainable_params / total_params * 100\n",
- "\n",
- "print()\n",
- "print(f\"Trainable params: {trainable_params:,}\")\n",
- "print(f\"Total params: {total_params:,}\")\n",
- "print(f\"Trainable %: {pct:.2f}%\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "7a0a4821",
- "metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "[transformers] warmup_ratio is deprecated and will be removed in v5.2. Use `warmup_steps` instead.\n"
- ]
- }
- ],
- "source": [
- "hate_args = TrainingArguments(\n",
- "\n",
- " output_dir= PROJECT_ROOT / \"models\" / \"roberta_hate_results\",\n",
- "\n",
- " learning_rate=LR,\n",
- "\n",
- " num_train_epochs=EPOCHS,\n",
- "\n",
- " per_device_train_batch_size=BATCH_SIZE,\n",
- " per_device_eval_batch_size=BATCH_SIZE,\n",
- "\n",
- " weight_decay=0.01,\n",
- "\n",
- " eval_strategy=\"epoch\",\n",
- " save_strategy=\"epoch\",\n",
- "\n",
- " load_best_model_at_end=True,\n",
- "\n",
- " metric_for_best_model=\"f1_toxic\",\n",
- " greater_is_better=True,\n",
- "\n",
- " warmup_ratio=0.1,\n",
- "\n",
- " logging_steps=10,\n",
- "\n",
- " fp16=torch.cuda.is_available(),\n",
- "\n",
- " report_to=\"none\",\n",
- "\n",
- " seed=RAND,\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "6a3acd3d",
- "metadata": {},
- "outputs": [],
- "source": [
- "hate_early_stopping = EarlyStoppingCallback(early_stopping_patience=2)\n",
- "\n",
- "hate_trainer = Trainer(\n",
- "\n",
- " model=hate_model,\n",
- "\n",
- " args=hate_args,\n",
- "\n",
- " train_dataset=hate_train,\n",
- " eval_dataset=hate_valid,\n",
- "\n",
- " processing_class=hate_tokenizer,\n",
- "\n",
- " data_collator=hate_collator,\n",
- "\n",
- " compute_metrics=compute_metrics,\n",
- "\n",
- " callbacks=[hate_early_stopping],\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "a5752cbb",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "==================================================\n",
- "TRAINING ROBERTA HATE\n",
- "==================================================\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "\n",
- " \n",
- " \n",
- "
\n",
- " [264/264 00:39, Epoch 3/3]\n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " Epoch \n",
- " Training Loss \n",
- " Validation Loss \n",
- " Accuracy \n",
- " Precision Toxic \n",
- " Recall Toxic \n",
- " F1 Toxic \n",
- " Roc Auc \n",
- " \n",
- " \n",
- " \n",
- " \n",
- " 1 \n",
- " 0.613999 \n",
- " 0.514029 \n",
- " 0.721854 \n",
- " 0.769231 \n",
- " 0.571429 \n",
- " 0.655738 \n",
- " 0.844621 \n",
- " \n",
- " \n",
- " 2 \n",
- " 0.612199 \n",
- " 0.497269 \n",
- " 0.741722 \n",
- " 0.792453 \n",
- " 0.600000 \n",
- " 0.682927 \n",
- " 0.853704 \n",
- " \n",
- " \n",
- " 3 \n",
- " 0.556086 \n",
- " 0.492456 \n",
- " 0.741722 \n",
- " 0.781818 \n",
- " 0.614286 \n",
- " 0.688000 \n",
- " 0.856085 \n",
- " \n",
- " \n",
- "
"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "Writing model shards: 100%|██████████| 1/1 [00:06<00:00, 6.59s/it]\n",
- "Writing model shards: 100%|██████████| 1/1 [00:06<00:00, 6.55s/it]\n",
- "Writing model shards: 100%|██████████| 1/1 [00:06<00:00, 6.07s/it]\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "TrainOutput(global_step=264, training_loss=0.6079502448891149, metrics={'train_runtime': 35.1712, 'train_samples_per_second': 59.623, 'train_steps_per_second': 7.506, 'total_flos': 107744491058700.0, 'train_loss': 0.6079502448891149, 'epoch': 3.0})"
- ]
- },
- "execution_count": 93,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "print(\"=\" * 50)\n",
- "print(\"TRAINING ROBERTA HATE\")\n",
- "print(\"=\" * 50)\n",
- "\n",
- "hate_trainer.train()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "d18a20d2",
- "metadata": {},
- "source": [
- "## 11. Evaluación — RoBERTa Hate"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "d58a64a5",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "============================================================\n",
- "RoBERTa Hate\n",
- "============================================================\n",
- " precision recall f1-score support\n",
- "\n",
- " No tóxico 0.69 0.79 0.74 81\n",
- " Tóxico 0.70 0.58 0.63 69\n",
- "\n",
- " accuracy 0.69 150\n",
- " macro avg 0.69 0.68 0.69 150\n",
- "weighted avg 0.69 0.69 0.69 150\n",
- "\n"
- ]
- },
- {
- "data": {
- "image/png": "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uJ6IiEimWMkTEZHR4ux6IiIimeLseiIiIiqWWMkTEZHRknkhzyRPRERGTOZZnsP1REREMsVKnoiIjBZn1xMREckUZ9cTERFRscRKnoiIjJbMC3kmeSIiMmIyz/IcriciIpIpVvJERGS0OLueiIhIpji7noiIiIolVvJERGS0ZF7IM8kTEZERk3mW53A9ERGRTLGSJyIio8XZ9URERDLF2fVERERULLGSJyIioyXzQp5JnoiIjJjMszyH64mIiGSKlTwRERktzq4nIiKSKc6uJyIiomKJlTwRERktmRfyTPJERGS8OFxPRERExRIreSIiMmLyLuWZ5ImIyGhxuJ6IiIiKJVbyRERktGReyDPJExGR8eJwPRERERVLrOSJiMho8d71REREciXvHM/heiIiIrliJU9EREZL5oU8K3kiIjJeCoXhlrwIDw/HBx98ABsbGzg5OaFdu3aIiYnR2SY1NRX9+vVDyZIlYW1tjaCgINy7dy9P+2GSJyIiKmT79u1Dv379cOTIEezcuRPp6en48MMPkZycrN0mNDQUmzZtwqpVq7Bv3z7cvXsX7du3z9N+FEIIYejgpXbo8hOpQyAqcKsu5O0bPVFxNKNt5QLt/8GzDIP15WiT/zPgDx48gJOTE/bt24dGjRohMTERjo6OWLZsGTp06AAAuHjxIqpUqYLDhw+jfv36ueqXlTwRERkvheEWjUaDp0+f6iwajSZXYSQmJgIAHBwcAAAnTpxAeno6AgICtNtUrlwZHh4eOHz4cK4Pj0meiIjIAMLDw6FWq3WW8PDwt74uKysLgwcPhp+fH6pVqwYAiI+Ph4WFBezs7HS2dXZ2Rnx8fK5j4ux6IiIyWoacXR8WFoYhQ4botCmVyre+rl+/fjh37hwOHjxowGheYJInIiKjZch71yuVylwl9Vf1798ff//9N/bv34/SpUtr211cXJCWloaEhASdav7evXtwcXHJdf8criciIipkQgj0798f69atw549e1CuXDmd9T4+PjA3N8fu3bu1bTExMYiNjYWvr2+u98NKnoiIjJZU967v168fli1bhg0bNsDGxkZ7nl2tVkOlUkGtVqNnz54YMmQIHBwcYGtriwEDBsDX1zfXM+sBJnkiIjJiUj1qdt68eQCAJk2a6LRHREQgJCQEADB9+nSYmJggKCgIGo0GgYGBmDt3bp72w+vkiYop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",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "hate_results = evaluate_model(\n",
- " hate_trainer,\n",
- " hate_test,\n",
- " y_test,\n",
- " \"RoBERTa Hate\",\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "c15c6ff1",
- "metadata": {},
- "source": [
- "## 12. Comparación de modelos"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "d7f2b05f",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " Model \n",
- " Accuracy \n",
- " Precision \n",
- " Recall \n",
- " F1 \n",
- " ROC-AUC \n",
- " \n",
- " \n",
- " \n",
- " \n",
- " 0 \n",
- " DistilBERT \n",
- " 0.760000 \n",
- " 0.708861 \n",
- " 0.811594 \n",
- " 0.756757 \n",
- " 0.865987 \n",
- " \n",
- " \n",
- " 1 \n",
- " RoBERTa Hate \n",
- " 0.693333 \n",
- " 0.701754 \n",
- " 0.579710 \n",
- " 0.634921 \n",
- " 0.797370 \n",
- " \n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " Model Accuracy Precision Recall F1 ROC-AUC\n",
- "0 DistilBERT 0.760000 0.708861 0.811594 0.756757 0.865987\n",
- "1 RoBERTa Hate 0.693333 0.701754 0.579710 0.634921 0.797370"
- ]
- },
- "execution_count": 95,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "comparison_df = pd.DataFrame({\n",
- "\n",
- " \"Model\": [\n",
- " \"DistilBERT\",\n",
- " \"RoBERTa Hate\",\n",
- " ],\n",
- "\n",
- " \"Accuracy\": [\n",
- " distil_results[\"accuracy\"],\n",
- " hate_results[\"accuracy\"],\n",
- " ],\n",
- "\n",
- " \"Precision\": [\n",
- " distil_results[\"precision\"],\n",
- " hate_results[\"precision\"],\n",
- " ],\n",
- "\n",
- " \"Recall\": [\n",
- " distil_results[\"recall\"],\n",
- " hate_results[\"recall\"],\n",
- " ],\n",
- "\n",
- " \"F1\": [\n",
- " distil_results[\"f1\"],\n",
- " hate_results[\"f1\"],\n",
- " ],\n",
- "\n",
- " \"ROC-AUC\": [\n",
- " distil_results[\"roc_auc\"],\n",
- " hate_results[\"roc_auc\"],\n",
- " ],\n",
- "})\n",
- "\n",
- "comparison_df"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "2c757b76",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/png": "iVBORw0KGgoAAAANSUhEUgAAArMAAAHXCAYAAACvatLKAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAOZ5JREFUeJzt3XlcVXX+x/H3vQgXUcGFBHQYULHcJTEMHQdrKFxaLGuoLJAxbJG0H5NNmiPaRmNmWONklqiVjubSbphhzuRSOjhW7vsyKqijgmKCcs/vjx7e6QYYJHD52uv5eJzHg/s93+/3fM7lweHN4ZxzbZZlWQIAAAAMZPd0AQAAAMDPRZgFAACAsQizAAAAMBZhFgAAAMYizAIAAMBYhFkAAAAYizALAAAAYxFmAQAAYCzCLABcRrKysvTaa695ugwAqDWEWQAwRJ8+fdSnT58K1y9YsEAjR47UNddcU3tFAYCHEWYB1Khdu3bpgQceUOvWreXr6yt/f3/16tVLU6ZM0Xfffefp8i4bO3bs0IMPPqh33nlH3bp1q9a5V6xYIZvNVu5y1113ufqtXbtWDz/8sKKiouTt7S2bzVal7ZSUlGjKlCm6+uqr5e/vr8aNG6tjx44aNmyYtm7dWq37BODyUc/TBQC4fH388ce688475XA4lJiYqE6dOqmkpEQrV67UqFGjtGnTJk2fPt3TZRrj008/rXDd119/rZkzZ6pfv341tv0RI0aUOesbHh7u+nrJkiV644031KVLF7Vu3Vrbt2+v0vyDBg3SJ598orvvvlspKSk6d+6ctm7dqo8++kg9e/ZUu3btqmM3AFxmbJZlWZ4uAsDlZ8+ePerSpYt+9atfafny5QoJCXFbv3PnTn388ccaOXKkhyqsOU6nUyUlJfL19fV0KdVixYoVuu6667RgwQLdcccdFfbLz8+Xv7+/6tevr9TUVE2dOlWV/RWzbt06RUdH69lnn9WYMWPc1pWWlurkyZNq1qzZJe1HZZ09e1Y+Pj6y2/nnJWACflIB1IiJEyfq9OnTmjFjRpkgK0kRERFuQfb8+fN6+umn1aZNGzkcDoWHh2vMmDEqLi52GxceHq6bbrpJK1asUPfu3VW/fn117txZK1askCQtXrxYnTt3lq+vr6KiovTvf//bbfyQIUPUsGFD7d69W/Hx8WrQoIFatGihp556qkzwmjRpknr27KlmzZqpfv36ioqK0sKFC8vsi81mU2pqqubMmaOOHTvK4XAoOzu7SnNI0ttvv63o6Gj5+fmpSZMm+u1vf+t2Nra8a2aPHDmioUOHKigoSL6+vuratatmz57t1mfv3r2y2WyaNGmSpk+f7nqPr7nmGq1bt67cWn6OoKAg1a9f/2eN3bVrlySpV69eZdZ5eXmVCbIHDx7U0KFD1aJFCzkcDrVq1UoPPfSQSkpKXH12796tO++8U02bNpWfn5+uvfZaffzxx27zXLiEYt68eRo7dqxatmwpPz8/FRYWSpK++uor9e3bVwEBAfLz81NsbKxWrVr1s/YRQM3gMgMANeLDDz9U69at1bNnz0r1v//++zV79mzdcccd+uMf/6ivvvpKGRkZ2rJli9599123vjt37tQ999yjBx54QPfee68mTZqkm2++WdOmTdOYMWP08MMPS5IyMjL0+9//Xtu2bXM7y1ZaWqq+ffvq2muv1cSJE5Wdna309HSdP39eTz31lKvflClTdMstt2jw4MEqKSnRvHnzdOedd+qjjz7SgAED3Gpavny53nnnHaWmpiowMND17/fKzjFhwgSNHz9ePXv21FNPPSUfHx999dVXWr58uW688cZy37PvvvtOffr00c6dO5WamqpWrVppwYIFGjJkiE6ePFnmrPfcuXN16tQpPfDAA7LZbJo4caJuv/127d69W97e3j/5PTp16pSOHTvm1ta0adNqOYMZFhYmSZozZ4569eqlevUq/vV06NAhRUdH6+TJkxo2bJjatWungwcPauHChTpz5ox8fHyUn5+vnj176syZMxoxYoSaNWum2bNn65ZbbtHChQt12223uc359NNPy8fHR4899piKi4vl4+Oj5cuXq1+/foqKilJ6errsdrtmzpyp66+/Xl988YWio6Mveb8BVAMLAKpZQUGBJcm69dZbK9V/w4YNliTr/vvvd2t/7LHHLEnW8uXLXW1hYWGWJGv16tWutqVLl1qSrPr161v79u1ztb/22muWJOvzzz93tSUlJVmSrEceecTV5nQ6rQEDBlg+Pj7W0aNHXe1nzpxxq6ekpMTq1KmTdf3117u1S7Lsdru1adOmMvtWmTl27Nhh2e1267bbbrNKS0vd+judTtfXsbGxVmxsrOt1ZmamJcl6++233eaPiYmxGjZsaBUWFlqWZVl79uyxJFnN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sE9ERITOnTunV155Rbt379Zbb71VrZc/tW3bVm+99Za2bNmir776SoMHD1b9+vXd+pR3bB43bpzefPNNTZgwQZs2bdKWLVs0b948jR07ttpqQ91BmMVlKzs7WyEhIQoPD1ffvn31+eef6+WXX9b7778vLy+vMv0bNWqkiRMnqnv37rrmmmu0d+9eLVmyxPVX/Isvvqhly5YpNDRUV199dZXrCAkJUY8ePbRu3TotWLBAffr0ceuXnJzs6ndheeWVVy46d2pqqrZs2aIFCxZUuh4AdVO9evWUmpqqiRMnqqioSM8//7wGDRqk++67T926ddPOnTu1dOlSNWnSxG1cXFyc61g3bNgw9e/fX/Pnz3frs2nTpjLHlx9es1+epk2bKjExUePHj3f7sJkf6tq1qyZPnqy//OUv6tSpk+bMmeN6pGF1mDFjhk6cOKFu3brpvvvucz2q7IfKOzbHx8fro48+0qeffqprrrlG1157rV566aWf3GeYyWZxSgcAAACG4swsAAAAjEWYBQAAgLEIswAAADAWYRYAAADGIswCAADAWIRZAAAAGIswCwAAAGMRZgHgMrVixQrZbDadPHmy0mPCw8OVmZlZYzUBQHUjzAKAhwwZMkQ2m00PPvhgmXXDhw+XzWbTkCFDar8wADAIYRYAPCg0NFTz5s3Td99952o7e/as5s6dq1//+tcerAwAzECYBQAP6tatm0JDQ7V48WJX2+LFi/XrX//a9TnzklRcXOz6XHpfX1/95je/0bp169zmWrJkia688krVr19f1113nfbu3VtmeytXrlTv3r1Vv359hYaGasSIESoqKqqx/QOAmkaYBQAP+8Mf/qCZM2e6XmdlZSk5Odmtz+OPP65FixZp9uzZWr9+vSIiIhQfH6/jx49Lkg4cOKDbb79dN998szZs2KD7779fTzzxhNscu3btUt++fTVo0CB98803mj9/vlauXKnU1NSa30kAqCGEWQDwsHvvvVcrV67Uvn37tG/fPq1atUr33nuva31RUZFeffVVvfDCC+rXr586dOig119/XfXr19eMGTMkSa+++qratGmjF198UVdddZUGDx5c5nrbjIwMDR48WI8++qjatm2rnj176uWXX9abb76ps2fP1uYuA0C1qefpAgDgl+6KK67QgAEDNGvWLFmWpQEDBigwMNC1fteuXTp37px69erlavP29lZ0dLS2bNkiSdqyZYt69OjhNm9MTIzb66+//lrffPON5syZ42qzLEtOp1N79uxR+/bta2L3AKBGEWYBoA74wx/+4Pp3/9SpU2tkG6dPn9YDDzygESNGlFnHzWYATEWYBYA6oG/fviopKZHNZlN8fLzbujZt2sjHx0erVq1SWFiYJOncuXNat26dHn30UUlS+/bt9cEHH7iN+/LLL91ed+vWTZs3b1ZERETN7QgA1DKumQWAOsDLy0tbtmzR5s2b5eXl5bauQYMGeuihhzRq1ChlZ2dr8+bNSklJ0ZkzZzR06FBJ0oMPPqgdO3Zo1KhR2rZtm+bOnatZs2a5zfOnP/1Jq1evVmpqqjZs2KAdO3bo/fff5wYwAEYjzAJAHeHv7y9/f/9y1z3//PMaNGiQ7rvvPnXr1k07d+7U0qVL1aRJE0nfXyawaNEivffee+rataumTZum5557zm2OLl266B//+Ie2b9+u3r176+qrr9a4cePUokWLGt83AKgpNsuyLE8XAQAAAPwcnJkFAACAsQizAAAAMBZhFgAAAMYizAIAAMBYhFkAAAAYizALAAAAYxFmAQAAYCzCLAAAAIxFmAUAAICxCLMAAAAwFmEWAAAAxiLMAgAAwFj/D8UaLF174v4vAAAAAElFTkSuQmCC",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "plt.figure(figsize=(8, 5))\n",
- "\n",
- "sns.barplot(\n",
- " data=comparison_df,\n",
- " x=\"Model\",\n",
- " y=\"F1\",\n",
- ")\n",
- "\n",
- "plt.title(\"Comparación F1 Score\")\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "7603506d",
- "metadata": {},
- "source": [
- "## 13. Error Analysis"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "0f32e457",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Best model: DistilBERT\n"
- ]
- }
- ],
- "source": [
- "if hate_results[\"f1\"] >= distil_results[\"f1\"]:\n",
- "\n",
- " best_name = \"RoBERTa Hate\"\n",
- " best_preds = hate_results[\"preds\"]\n",
- " best_probs = hate_results[\"probs\"]\n",
- "\n",
- "else:\n",
- "\n",
- " best_name = \"DistilBERT\"\n",
- " best_preds = distil_results[\"preds\"]\n",
- " best_probs = distil_results[\"probs\"]\n",
- "\n",
- "print(\"Best model:\", best_name)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "1d7148ce",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Errores: 36\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " text \n",
- " real \n",
- " pred \n",
- " prob_toxic \n",
- " is_error \n",
- " \n",
- " \n",
- " \n",
- " \n",
- " 0 \n",
- " So sad, he looked like such a nice young man \n",
- " 0 \n",
- " 0 \n",
- " 0.098947 \n",
- " False \n",
- " \n",
- " \n",
- " 1 \n",
- " peggy Hubbard for president \n",
- " 0 \n",
- " 0 \n",
- " 0.175114 \n",
- " False \n",
- " \n",
- " \n",
- " 2 \n",
- " Thats a real parent, a real mother. Nothing bu... \n",
- " 0 \n",
- " 1 \n",
- " 0.875734 \n",
- " True \n",
- " \n",
- " \n",
- " 3 \n",
- " Lol stupid mooslims \n",
- " 1 \n",
- " 1 \n",
- " 0.884139 \n",
- " False \n",
- " \n",
- " \n",
- " 4 \n",
- " Another great video and thanks for not putting... \n",
- " 0 \n",
- " 0 \n",
- " 0.323487 \n",
- " False \n",
- " \n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " text real pred prob_toxic \\\n",
- "0 So sad, he looked like such a nice young man 0 0 0.098947 \n",
- "1 peggy Hubbard for president 0 0 0.175114 \n",
- "2 Thats a real parent, a real mother. Nothing bu... 0 1 0.875734 \n",
- "3 Lol stupid mooslims 1 1 0.884139 \n",
- "4 Another great video and thanks for not putting... 0 0 0.323487 \n",
- "\n",
- " is_error \n",
- "0 False \n",
- "1 False \n",
- "2 True \n",
- "3 False \n",
- "4 False "
- ]
- },
- "execution_count": 98,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "error_df = pd.DataFrame({\n",
- "\n",
- " \"text\": X_test.values,\n",
- " \"real\": y_test.values,\n",
- " \"pred\": best_preds,\n",
- " \"prob_toxic\": best_probs,\n",
- "})\n",
- "\n",
- "error_df[\"is_error\"] = (\n",
- " error_df[\"real\"] != error_df[\"pred\"]\n",
- ")\n",
- "\n",
- "print(\"Errores:\", error_df[\"is_error\"].sum())\n",
- "error_df.head()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "64457e22",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "================================================================================\n",
- "FALSE NEGATIVES\n",
- "================================================================================\n",
- "\n",
- "Prob toxicidad: 0.3945\n",
- "------------------------------------------------------------\n",
- "They are protecting and serving us, from people like Michael Brown. The guy deserved to be killed, cry more about it...\n",
- "\n",
- "Prob toxicidad: 0.497\n",
- "------------------------------------------------------------\n",
- "So the autopsy showed a number of wounds to the right arm making the scenario of him being shot with his hands raised a lot less likely. Or are we still trying to claim that? Let's see, innocent unarmed gentle giant, minding his own business, gunned down in cold blood for jaywalking by a sadistic, jack-booted, racist thug of a police officer who shot the innocent youth in the back while his hands were raised trying to surrender. I keep forgetting which BS story we are still trying to defend and which claims have been totally refuted by the facts. Regardless, it \"doesn't matter\" because we have already decided that the cop is guilty.\n",
- "\n",
- "Prob toxicidad: 0.2156\n",
- "------------------------------------------------------------\n",
- "Let's get this straight and present the facts as the mass media should have from the beginning. 18 yr old (by all legal aspects an adult) robs a convince store. The criminal later flees the seen and is aprehended by the police. Resists arrest and altercation occurs between the two. The police (as in every case similar to this uses force). Criminal is killed. The killing goes to court. A randomly selected jury views all the evidence and hears out all witnesses which pertain to the case. Radom jury reaches unanimous verdict of not guilty. Im sorry protestors I can't here over all this DEMOCRACY!\n",
- "\n",
- "Prob toxicidad: 0.0761\n",
- "------------------------------------------------------------\n",
- "Ah, beautiful.\n",
- "\n",
- "Prob toxicidad: 0.337\n",
- "------------------------------------------------------------\n",
- "Remember that time every other race rioted because someone of their race got shot by a white cop after attacking the officer or waving a gun around?\n",
- "Remember the huge riot last year when a 13 month old was shot in the head by 2 black kids?\n",
- "\n",
- "Oh.\n",
- "\n",
- "Prob toxicidad: 0.3528\n",
- "------------------------------------------------------------\n",
- "finally a black person with a unbiased opinion. An incredibly high percentage of black lives are lost among themselves and only an extremely small fraction from police. Black people need to take responsibility for their violence.\n",
- "\n",
- "Prob toxicidad: 0.3718\n",
- "------------------------------------------------------------\n",
- "Bottom line: Michael Brown was a drug addict criminal, a violent criminal.\n",
- "So why should anyone feel bad he got killed, unless you're a criminal yourself?\n",
- "\n",
- "Prob toxicidad: 0.1755\n",
- "------------------------------------------------------------\n",
- "Hahahahaha. This guy is Ed Bassmaster's character ALWAYS TESTE. Ed Bassmaster has a semi-retarded character who is cross-eyed just like this guy\n",
- "\n",
- "Prob toxicidad: 0.4335\n",
- "------------------------------------------------------------\n",
- "All you have to do is drive slowly towards them. If they're smart, they'll get out of the way.\n",
- "\n",
- "Prob toxicidad: 0.1389\n",
- "------------------------------------------------------------\n",
- "Seeing the comments on here just proves how backward this country is.\n"
- ]
- }
- ],
- "source": [
- "false_negatives = error_df[(error_df[\"real\"] == 1) & (error_df[\"pred\"] == 0)]\n",
- "\n",
- "print(\"=\" * 80)\n",
- "print(\"FALSE NEGATIVES\")\n",
- "print(\"=\" * 80)\n",
- "\n",
- "for idx, row in false_negatives.head(10).iterrows():\n",
- "\n",
- " print(\"\\nProb toxicidad:\", round(row[\"prob_toxic\"], 4))\n",
- " print(\"-\" * 60)\n",
- " print(row[\"text\"])\n"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "db158aab",
- "metadata": {},
- "source": [
- "## 14. Guardado del mejor modelo"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "8cc4001e",
- "metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "Writing model shards: 100%|██████████| 1/1 [00:02<00:00, 2.58s/it]"
- ]
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Modelo guardado en: /mnt/c/Users/under/Documents/F5/3_Projects/Project_9_Equipo3/Project_YT/models/best_distilbert\n"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "\n"
- ]
- }
- ],
- "source": [
- "SAVE_DIR = PROJECT_ROOT / \"models\"\n",
- "\n",
- "if best_name == \"RoBERTa Hate\":\n",
- "\n",
- " final_model = hate_trainer\n",
- " final_tokenizer = hate_tokenizer\n",
- "\n",
- " save_path = SAVE_DIR / \"best_roberta_hate\"\n",
- "\n",
- "else:\n",
- "\n",
- " final_model = distil_trainer\n",
- " final_tokenizer = distil_tokenizer\n",
- "\n",
- " save_path = SAVE_DIR / \"best_distilbert\"\n",
- "\n",
- "final_model.save_model(save_path)\n",
- "final_tokenizer.save_pretrained(save_path)\n",
- "print(\"Modelo guardado en:\", save_path)"
- ]
- }
- ],
- "metadata": {
- "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": 5
-}