Carlos Hernández
Senior AI Platform Engineer · San Salvador
UTC−6
← Field notes EN·ES
Field note Jun 2026 4 min

Cuándo gana lo clásico

Multipliqué los datos de entrenamiento por 7.4×. El F1 se movió cuatro centésimas de punto. Una nota desde un benchmark controlado sobre qué limita de verdad un problema — y qué solo agrega costo.

Esto sale de mi tesis de máster: un benchmark de qué técnica de NLP clasifica mejor el texto de transacciones bancarias — esas cadenas cortas y crípticas que una app de finanzas tiene que leer, como BIZUM ENVIO 15.00 o TRF NOMINA EMPRESA X. El resultado más útil hasta ahora no fue una cifra de accuracy. Fue lo que pasó cuando intenté subir una.

Tomé el clasificador que funcionaba, congelé todo a su alrededor y le di 7.4× más datos — de 68.000 filas a 500.000. El F1 pasó de 0,9845 a 0,9849. Cuatro centésimas de punto. El tiempo de entrenamiento pasó de 67 segundos a 304. Siete veces los datos compraron nada que pudiera medir, a cuatro veces y media el costo.

En machine learning los dos reflejos son más datos y un modelo más grande. En este problema los dos hicieron casi nada — y el benchmark muestra exactamente dónde cada uno dejó de pagar.

El montaje

El objetivo nunca fue un leaderboard. Era el balance honesto entre precisión, cómputo y escala — la decisión que de verdad tomas al poner un modelo en producción, no la que responde una sola cifra de accuracy.

Así que el diseño aísla variables. Un solo pipeline de preprocesamiento, una sola función de evaluación, una semilla fija, compartidos por cada modelo y cada corpus. Lo que se mueva es el modelo o los datos — nunca la plomería. Dos datasets públicos de HuggingFace; uno sintético, uno real.

Las tres corridas, y qué hay de verdad en ellas:

CorpusNaturalezaFilasCategoríasVocab (TF-IDF)Palabras (media)
Asintético68.0001711.5085,2
Breal68.000105.9013,1
Creal500.0001014.8163,1
Fuentes (públicas, HuggingFace): A — DoDataThings/us-bank-transaction-categories-v2 (sintético). B y C — mitulshah/transaction-categorization (real). Todos balanceados (max/min ≈ 1,0). Nota el set sintético: más categorías, pero descripciones más largas y un vocabulario más rico.

Y cómo les fue a los dos modelos clásicos en las tres:

CorpusModeloF1 (macro)Entren.Infer (ms/tx)
A · sintético · 68KSVM0.998310.5s0.0004
XGBoost0.9963171.3s0.1268
B · real · 68KSVM0.98451.2s0.0001
XGBoost0.984867.0s0.0871
C · real · 500KSVM0.984922.5s0.0004
XGBoost0.9847303.9s0.1022
Features TF-IDF en todo · split 70/15/15 · semilla 42 · datasets públicos de HuggingFace. La red neuronal y el transformer (DistilBERT) entran en la siguiente fase.

Tres cosas que dijeron los números

1. Más datos toparon con un techo, rápido

Mismo corpus, mismo modelo, 68.000 filas y luego 500.000. F1 0,9845 → 0,9849. El modelo ya había aprendido todo lo que los datos tenían para enseñarle con el tamaño menor. Las 432.000 filas extra eran redundantes — reenseñaban lo que ya se sabía.

7.4× los datos → +0,04 puntos de F1. Y 4,5× el tiempo de entrenamiento.

Más datos no es gratis. Cuando deja de mover la métrica, sigue moviendo la cuenta.

2. Ganó el modelo más simple

Dos enfoques clásicos sobre las mismas features: un SVM lineal y árboles con gradient boosting (XGBoost). El SVM igualó o superó a XGBoost en cada corpus — y en costo no estuvo cerca.

SVM vs XGBoost: 20–150× más barato de entrenar, 200–600× más rápido en inferencia, F1 igual o mejor.

SVM XGBoost tiempo de entrenamiento (s) 10.5s 171s sintético · 68K 1.2s 67.0s real · 68K 22.5s 304s real · 500K
Tiempo de entrenamiento por corrida. La misma accuracy en todos — XGBoost solo cuesta 10–150× más para llegar ahí, y la brecha crece con los datos. Las barras wine (SVM) apenas se ven.

El modelo más elaborado compró un sistema más lento para ser, en el mejor caso, exactamente igual de preciso. En producción eso no es un empate. Es una pérdida que pagas en cada request.

3. Los datos sintéticos inflaron el modelo

El score más alto de la tabla, 0,9983, es el corpus sintético (A). En el momento en que corrí el mismo pipeline sobre un dataset real del mismo tamaño, el F1 bajó cerca de 1,4 puntos a 0,9845. Mismo modelo, misma plomería. El set sintético era simplemente más fácil: más regular, más limpio, descripciones más largas (5,2 palabras contra 3,1). Su número casi perfecto describía los datos, no el modelo.

Un score de datos sintéticos es una promesa, no una medición.

Antes de que alguien lo diga

Sí — incluso un F1 de 98% es sospechosamente alto (y el 99,8% era sintético). Lo es. Hasta el dataset real de aquí es público, limpio y balanceado, y el texto de transacciones es muy separable: el token del comercio casi siempre delata la categoría. Los datos bancarios de producción son más sucios: typos, campos faltantes, categorías que de verdad se solapan.

Así que el número no es el punto, y no lo citaría como tal. El perfil sí: el problema satura temprano y barato. Una vez que ves ese perfil, tirarle datos y capacidad de modelo es gastar donde ya no queda nada por comprar.

La decisión de ingeniería

Es la misma decisión que tomo en sistemas en producción, solo que con un marco académico limpio alrededor. El modelo aburrido que le queda al problema le gana al impresionante que no justifica su costo. La precisión es el titular; la cuenta llega en cada inferencia, para siempre.

Los clásicos aquí ya están en 98–99%. Así que la pregunta honesta para la siguiente fase no es si un transformer puede hacerlo mejor — casi no hay margen. Es si un transformer puede justificar su costo.

¿Cuándo fue la última vez que más datos, o un modelo más grande, se pagaron solos en tu problema — y lo mediste, o solo asumiste que lo harían?

Próxima: hago fine-tuning de un transformer (DistilBERT) sobre exactamente el mismo pipeline — y lo juzgo no por la precisión que suma, sino por la latencia y el cómputo que cobra a cambio. La respuesta interesante no es si gana. Es si vale la pena.