Sistema de detección automática de mensajes de odio en comentarios de YouTube, desarrollado como proyecto de Data Science con técnicas de NLP clásico y modelos de deep learning.
- Descripción del problema
- Dataset
- Arquitectura del proyecto
- Pipeline ML
- Modelos y resultados
- Tecnologías
- Instalación
- Estructura del repositorio
- Experimentos MLflow
- Equipo
YouTube gestiona millones de comentarios diarios. La moderación humana no escala al ritmo de crecimiento de la plataforma. Este proyecto implementa un clasificador binario que detecta automáticamente si un comentario es tóxico o no, permitiendo tomar acciones automáticas: eliminar el comentario, banear al usuario o escalar a un moderador humano.
Enfoque: solución práctica y desplegable por encima de precisión teórica.
| Característica | Valor |
|---|---|
| Fuente | YouToxic English 1000 |
| Comentarios originales | 1.000 |
| Tras limpieza (duplicados) | 997 |
| Distribución | 46% tóxicos / 54% no tóxicos |
| Idioma | Inglés |
| Vídeos | 13 (temática: protestas raciales EEUU 2014) |
Etiqueta objetivo: IsToxic (clasificación binaria)
Hallazgos clave del EDA:
IsRacist⊂IsHatespeechal 100% → clasificación binaria más robusta que multi-etiqueta- El odio cambia el registro, no el tema — vocabulario compartido entre clases
- Palabras más discriminantes:
idiot(16x),bitch(14x),fuck(10x) - URLs aparecen en 91.7% de comentarios NO tóxicos → señal de argumentación
Dataset YouTube
↓
EDA (análisis exploratorio)
↓
Preprocesamiento NLP
(limpieza · lematización · stopwords)
↓
Split 80/20 + Augmentation
(back-translation ES+FR)
↓
Entrenamiento de modelos
(LR · LightGBM · DistilBERT)
↓
Optimización con Optuna
↓
Tracking con MLflow + DagsHub
↓
Modelo en producción (DistilBERT)
- Lowercase
- Eliminación de URLs con regex (
https?://\S+) - Eliminación de menciones (
@usuario) - Eliminación de caracteres especiales y números
- Lematización con spaCy
en_core_web_sm - Eliminación de stopwords (NLTK english)
⚠️ El vocabulario de odio (idiot,bitch,isis...) se conserva intencionalmente
- Técnica: back-translation (inglés → español/francés → inglés)
- Aplicada solo al 25% de comentarios tóxicos del train
- Solo sobre el conjunto de entrenamiento — nunca sobre test
- Justificación: WordNet descartado por riesgo semántico (
black → dark)
- TF-IDF con
ngram_range=(1,2),max_features=3000 - Bigramas capturan contexto mínimo: "black people" vs "black officer"
Cada miembro del equipo entrenó sus propios modelos de forma independiente para comparar enfoques.
Los experimentos completos están disponibles en DagsHub MLflow.
| Modelo | F1 test | Precision | Recall | ROC-AUC | Overfitting F1 |
|---|---|---|---|---|---|
| DistilBERT (ganador) | 0.73 | 0.73 | 0.67 | 0.83 | 0.12 |
| LR + Optuna | 0.72 | 0.74 | 0.61 | 0.77 | 0.18 |
| LGBM + Optuna | 0.72 | 0.74 | 0.61 | 0.77 | 0.18 |
| LR baseline | 0.71 | 0.73 | 0.69 | 0.80 | 0.10 |
| LR con augmentation | 0.67 | 0.72 | 0.63 | 0.77 | 0.20 |
| LGBM baseline | 0.58 | 0.64 | 0.53 | 0.73 | 0.22 |
Métrica principal: F1-score — más robusta que Accuracy en clasificación de odio.
Modelo: distilbert-base-uncased (fine-tuning)
F1 test: 0.73
ROC-AUC: 0.83
Overfitting: 0.12 (controlado)
Plataforma: HuggingFace Transformers
El dataset proviene de 13 vídeos sobre el mismo evento (caso Ferguson, 2014). El modelo aprendió que vocabulario relacionado con policía y raza = toxicidad, independientemente del contexto. Comentarios argumentativos sobre esos temas son clasificados como tóxicos (falsos positivos).
"La IA todavía no comprende completamente el contexto humano. El lenguaje es infinitamente más rico que cualquier dataset."
| Categoría | Herramienta | Uso |
|---|---|---|
| Lenguaje | Python 3.11 | Base del proyecto |
| NLP clásico | spaCy, NLTK | Preprocesamiento y lematización |
| ML | Scikit-learn, LightGBM | Modelos baseline y ensemble |
| Deep Learning | HuggingFace Transformers | DistilBERT fine-tuning |
| Optimización | Optuna | Ajuste de hiperparámetros (50 trials, CV 5 folds) |
| Tracking | MLflow + DagsHub | Registro de experimentos del equipo |
| Augmentation | deep-translator | Back-translation ES+FR |
| Entorno | uv, Docker | Gestión de dependencias y despliegue |
- Python 3.11+
- uv (gestor de paquetes)
# Clonar el repositorio
git clone https://github.com/Bootcamp-IA-P6/Project_9_NLP_Team2.git
cd Project_9_NLP_Team2
# Instalar dependencias
uv sync
# Descargar modelo de spaCy
uv run python -m spacy download en_core_web_sm
# Lanzar Jupyter
uv run jupyter notebook# Construir la imagen
docker build -t toxicfilter-ai .
# Ejecutar el contenedor
docker run -p 8888:8888 toxicfilter-aiCrea un archivo .env basado en .env.example:
cp .env.example .envConfigura tus credenciales:
MLFLOW_TRACKING_USERNAME=gemita284
MLFLOW_TRACKING_PASSWORD=tu_token_dagshubProject_9_NLP_Team2/
│
├── data/
│ ├── raw/ # Dataset original (no versionado)
│ └── processed/ # Datasets procesados (no versionados)
│
├── notebooks/
│ ├── V_01/ # Naizabeth Bermúdez
│ │ ├── 0.1-eda-exploracion-inicial.ipynb
│ │ ├── 1.0-limpieza-de-datos.ipynb
│ │ └── 2.0-entrenamiento-modelo.ipynb
│ │
│ ├── V_02/ # Gema Yébenes
│ │ ├── 00_eda_V02.ipynb
│ │ ├── 01_preprocesamiento_V02.ipynb
│ │ ├── 02_split_augmentation_V02.ipynb
│ │ ├── 03_entrenamiento_baseline_V02.ipynb
│ │ ├── 04_optimizacion_optuna_V02.ipynb
│ │ ├── 05_Preprocesamiento_DistilBERT_V02.ipynb
│ │ ├── 06_entrenamiento_distilbert_V02.ipynb
│ │ └── Informe_Tecnico_NLP_Toxicidad.html
│ │
│ ├── V_03/ # Maryori Cruz
│ │ ├── EDA_Toxic_Comments_v03.ipynb
│ │ ├── Preprocessing_NLP_v03.ipynb
│ │ ├── Split_Augmentation_v03.ipynb
│ │ ├── Model_Training_v03.ipynb
│ │ └── Optuna_Tuning_v03.ipynb
│ │
│ └── V_04/ # Raúl Machaca
│ ├── 00_eda_V04.ipynb
│ ├── 01_preprocesamiento_V04.ipynb
│ ├── 02_entrenamiento_baseline_V04.ipynb
│ ├── 03_preprocesamiento_distilbert_V04.ipynb
│ ├── 04_distilbert_V04.ipynb
│ └── 05_distilbert_optimizado_V04.ipynb
│
├── models/ # Modelos serializados
├── reports/
│ ├── figures/ # Gráficas y visualizaciones del EDA
│ └── Informe_Tecnico_NLP_Toxicidad.pdf
├── scripts/ # Scripts auxiliares
├── src/ # Código fuente modular
├── test/ # Tests unitarios
│
├── Dockerfile
├── pyproject.toml
├── .env.example
├── .gitignore
└── README.md
Todos los experimentos del equipo están centralizados en DagsHub bajo el experimento youtube_toxic_comments.
🔗 Ver experimentos: dagshub.com/gemita284/Project_9_NLP_Team2.mlflow
Todos los miembros registraron las mismas métricas para comparación directa:
mlflow.log_metrics({
"accuracy_train", "accuracy_test",
"f1_train", "f1_test",
"precision_test", "recall_test",
"roc_auc_test",
"overfitting_acc", "overfitting_f1"
})import dagshub
import mlflow
dagshub.init(
repo_owner='gemita284',
repo_name='Project_9_NLP_Team2',
mlflow=True
)
mlflow.set_experiment('youtube_toxic_comments')El informe técnico completo del proyecto documenta toda la arquitectura, decisiones técnicas, resultados y análisis comparativo de los modelos.
📥 Descargar Informe Técnico (PDF)
| Sección | Descripción |
|---|---|
| 01 Resumen Ejecutivo | Visión general del pipeline End-to-End |
| 02 Ingeniería de Datos | Preprocesamiento con NLTK/spaCy — reducción del 39.4% |
| 03 Arquitectura de Validación | Split 70/15/15 y Data Augmentation sin leakage |
| 04 Baseline + Optuna | LR · SVM · MNB · LightGBM con 50 trials |
| 05 DistilBERT | Fine-tuning con ToxicTrainer y Early Stopping |
| 06 Resultados | Auditoría comparativa en Test Set (150 filas) |
| 07 Análisis Crítico | Por qué DistilBERT Balanced gana |
| 08 MLOps | Métricas estandarizadas del equipo en DagsHub |
| 09 Conclusión | KPIs cumplidos y próximos pasos |
| Modelo | F1 Test | Recall | Overfit F1 | ROC-AUC |
|---|---|---|---|---|
| LR Baseline | 0.7503 | 0.7526 | 9.68% ❌ | 0.8017 |
| DistilBERT NoAugment | 0.7301 | 0.6865 | 15.27% ❌ | 0.8532 |
| DistilBERT Balanced 🏆 | 0.7785 | 0.8657 | 3.48% ✅ | 0.8529 |
| Miembro | GitHub | Contribución principal |
|---|---|---|
| Gema Yébenes | @gemayc | DistilBERT fine-tuning · modelo ganador · MLflow setup |
| Raúl Machaca | @RaulCtm | EDA · limpieza · entrenamiento modelos V01 |
| Maryori Cruz | @MaryoriCruz | Preprocesamiento · augmentation · LR + LightGBM + Optuna |
| Naizabeth Bermúdez | @Delo-sangeles | EDA · preprocesamiento · modelos V02 |
MIT License — ver LICENSE para más detalles.