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

Familia de clasificadores

Mismo gold (4.034 notas) y la misma definición operacional v5.

Modelo Método Parámetros Demo
BETO Full FT + ventanas 110 M vivo · Space
Qwen2.5-0.5B Full SFT 494 M vivo · Space
Qwen2.5-1.5B LoRA 1,54 B + adapter 18,5 M vivo · Space
BETO Qwen 0.5B Qwen 1.5B LoRA
Accuracy OOF 0.924 0.959 0.959
Recall CONFLICTO 0.963 0.895 0.906
Precisión CONFLICTO 0.765 0.917 0.910
FN / FP 33 / 273 94 / 72 84 / 80

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.

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
17
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
(198)
this model

Dataset used to train agusnieto77/beto-conflict-classifier

Space using agusnieto77/beto-conflict-classifier 1