Clasificador de Conflictos Sociales (BETO cased)

Clasificador binario de notas periodísticas en español: CONFLICTO vs NO_CONFLICTO para conflicto civil/social — una confrontación o disputa colectiva real con al menos un actor social/civil (trabajadores, estudiantes, vecinos, sindicatos, asociaciones, población civil organizada), o una reacción colectiva concreta frente a una necesidad, agravio o condición social explícita.

Full fine-tuning de dccuchile/bert-base-spanish-wwm-cased sobre 4.034 notas periodísticas anotadas manualmente de noticias locales argentinas.

Ventaja sobre LLM: documentos largos

Este modelo usa ventanas deslizantes + max pooling para manejar notas que exceden los 512 tokens de BETO: cada documento se trocea en ventanas con solapamiento, se clasifica cada fragmento, y el score del documento es el máximo. Esto reduce los falsos negativos a la mitad comparado con truncar al inicio (head-512).

Demo

Dataset

Uso

import torch
from transformers import AutoModelForSequenceClassification, AutoTokenizer

model_dir = "agusnieto77/beto-conflict-classifier"
tok = AutoTokenizer.from_pretrained(model_dir)
model = AutoModelForSequenceClassification.from_pretrained(model_dir)
model.eval()

STRIDE = 256
MAX_LENGTH = 512
THRESHOLD = 0.52  # ajustable según prioridad recall/precision

def clasificar(texto: str) -> tuple[str, float]:
    """Trocea en ventanas deslizantes, clasifica cada chunk, agrega con max."""
    enc = tok(
        texto, truncation=True, max_length=MAX_LENGTH, stride=STRIDE,
        return_overflowing_tokens=True, padding=True, return_tensors="pt",
    )
    ov_map = enc.pop("overflow_to_sample_mapping", None)
    enc = {k: v for k, v in enc.items() if k != "overflow_to_sample_mapping"}
    with torch.no_grad():
        logits = model(**enc).logits
        probs = torch.softmax(logits.float(), dim=-1)[:, 1]
    score = float(probs.max())  # max pooling
    etiqueta = "CONFLICTO" if score >= THRESHOLD else "NO_CONFLICTO"
    return etiqueta, score

texto = (
    "Los trabajadores del hospital municipal decidieron continuar con el paro "
    "de actividades en reclamo de mejoras salariales. El gremio anunció una "
    "movilización hacia la Municipalidad y rechazó la propuesta de aumento "
    "del Ejecutivo."
)

etiqueta, score = clasificar(texto)
print(f"{etiqueta} (score = {score:.3f})")
# → CONFLICTO (score ≈ 0.95)

Evaluación

Validación cruzada de 5 folds sobre las 4.034 notas de entrenamiento (predicciones out-of-fold, inferencia por ventanas deslizantes stride=256

  • max pooling, umbral 0.5).
Métrica Media Desvío
Recall CONFLICTO 0.9631 0.0318
Precision CONFLICTO 0.7648 0.0621
F1 CONFLICTO 0.8508 0.0351
F2 CONFLICTO 0.9141 0.0211
PR-AUC 0.9601 0.0028
ROC-AUC 0.9821
Accuracy 0.9241
Macro F1 0.8993
FN (total OOF) 33
FP (total OOF) 273

Matriz de confusión OOF: TP=862 · FN=33 · FP=273 · TN=2866

Comparación con head-512 (truncado)

Estrategia FN FP Recall F2
head-512 (truncado) 66 189 0.926 0.901
ventanas + max 33 273 0.963 0.914

La mitad de los falsos negativos se recuperan al procesar el texto completo.

Entrenamiento

  • Full fine-tuning de dccuchile/bert-base-spanish-wwm-cased
  • 4.034 notas: 895 CONFLICTO (22,2%) / 3.139 NO_CONFLICTO (77,8%)
  • Learning rate 3e-5, batch efectivo 32, bf16, 4 epochs (early stopping)
  • Selección de checkpoint por F2 CONFLICTO en validation
  • Threshold 0.5193 optimizado en OOF CV con inferencia chunked

Definición operacional (v5)

Una nota es CONFLICTO si contiene un acto colectivo civil/social ligado a una disputa real entre partes identificables, o a una necesidad, agravio o condición social explícita frente a la cual un colectivo protesta, se rebela o ejerce presión.

Actos que hacen CONFLICTO: medida de fuerza laboral; petición o reclamo formal de un actor colectivo con objeto concreto o contraparte identificada; manifestación popular con reclamo; violencia o acción colectiva en una disputa social; reacción colectiva frente a un delito o abuso; motín carcelario; conflicto resuelto cuando la nota establece el reclamo subyacente.

Casos NO_CONFLICTO: asambleas sin disputa; gestión habitual de entidades civiles; opinión individual; delito común sin reacción social; violencia interpersonal; conflicto puramente militar; cobertura de crisis sin reclamo; asistencia solidaria sin disputa; campaña y retórica electoral; contienda político-institucional ordinaria entre poderes del Estado; marchas conmemorativas, educativas o de concientización sin reclamo.

A diferencia del clasificador Qwen, BETO no requiere la definición en el prompt: la definición está representada por el gold standard con el que fue entrenado. El archivo completo está en conflict_definition.md para referencia.

Limitaciones

  • Dominio: noticias locales argentinas. El desempeño en otras regiones o estilos periodísticos no está validado.
  • Las métricas provienen de validación cruzada sobre el conjunto de entrenamiento; el modelo final fue reentrenado sobre la totalidad de los datos.
  • El 52% de las notas excede 512 tokens; la estrategia de ventanas deslizantes mitiga el truncamiento pero puede generar más falsos positivos que un modelo que solo procesa el inicio.

Comparación con Qwen2.5-1.5B LoRA

Ambos modelos usan el mismo dataset, los mismos folds y la misma definición:

BETO cased Qwen2.5-1.5B LoRA
Método Full fine-tuning LoRA
Parámetros 110 M 1.500 M (adapter)
Recall CONFLICTO 0.963 0.906
FN 33 84
Precision CONFLICTO 0.765 0.910
F1 CONFLICTO 0.851 0.908
ROC-AUC 0.982 0.992
Tiempo entrenamiento ~35 min ~3 h
VRAM entrenamiento 6.7 GB 24 GB

Qwen es más preciso; BETO recupera más conflictos. La elección depende de si la prioridad operacional es minimizar FN (BETO) o maximizar precision (Qwen).

Créditos

Guillermina Laitano, Luciana Nogueira, Nicolás Rabino, Rodrigo Fernández, Ivana Teijón, Agustín Nieto


English version / Versión en inglés: README.en.md

Downloads last month
-
Safetensors
Model size
0.1B params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for agusnieto77/beto-conflict-classifier

Finetuned
(193)
this model

Dataset used to train agusnieto77/beto-conflict-classifier

Space using agusnieto77/beto-conflict-classifier 1