Inicio / Blog / Datos

12 de mayo de 2026 · 7 min de lectura

Clasificar 963 productos sin machine learning.

Un catálogo de pintura de automoción exportado a Excel, sin etiquetas, sin formato consistente y con un negocio esperando su web. Esto es lo que hice y por qué no entrené ningún modelo.

Pinturas Autos Torres tenía su catálogo donde lo tienen casi todos los negocios pequeños: en una hoja de cálculo que alguien fue rellenando durante años. Cientos de referencias, una descripción de texto libre por producto y ninguna columna que dijera de qué marca era ni qué tipo de producto era.

Para que la web tuviera un catálogo filtrable —«enséñame solo los barnices de esta marca»— necesitaba justo eso: marca y tipo de cada uno de los 963 productos.

Por qué descarté el machine learning

Es la primera idea que se le ocurre a cualquiera que acabe de terminar formación en Big Data e IA, y por eso mismo me obligué a justificarla antes de lanzarme:

  • No había datos etiquetados. Para entrenar un clasificador necesitaría exactamente lo que estaba intentando obtener.
  • 963 filas no son un dataset. Son un problema pequeño con reglas conocidas.
  • Tenía que poder explicar cada fallo. Cuando el cliente me dijera «este producto está en la categoría equivocada», la respuesta no podía ser «lo ha decidido el modelo».
  • Alguien tiene que mantenerlo. Una lista de reglas la puede tocar cualquiera; un modelo hay que reentrenarlo.

La información ya estaba en la descripción del producto. No hacía falta un modelo: hacía falta leerla bien.

Paso 1: normalizar antes de decidir nada

El 80 % del trabajo real fue este. Los mismos datos venían escritos de siete formas distintas: mayúsculas y minúsculas mezcladas, acentos irregulares, dobles espacios, abreviaturas y erratas heredadas de años de escritura manual.

function normalizar(texto) {
  return String(texto)
    .toUpperCase()
    .normalize('NFD')                  // separa las tildes
    .replace(/\p{Diacritic}/gu, '')    // y las elimina
    .replace(/[^A-Z0-9 ]/g, ' ')       // fuera signos raros
    .replace(/\s+/g, ' ')              // espacios dobles
    .trim();
}

Sobre el texto normalizado ya se puede buscar sin miedo: «Barníz 2K» y «BARNIZ 2K» dejan de ser dos cosas distintas.

Paso 2: diccionarios con alias, no listas de palabras

Cada marca aparecía escrita de varias maneras, así que en lugar de una lista de nombres monté un diccionario donde cada marca tiene sus alias reales, los que estaban en la hoja:

const MARCAS = {
  'MARCA A': ['MARCA A', 'MARCAA', 'M A'],
  'MARCA B': ['MARCA B', 'MRC B'],
};

function detectarMarca(descripcion) {
  const texto = normalizar(descripcion);
  for (const [marca, alias] of Object.entries(MARCAS)) {
    if (alias.some((a) => texto.includes(a))) return marca;
  }
  return null; // mejor null que una marca inventada
}

Ese return null es una decisión de diseño, no un descuido. Prefiero un producto sin clasificar a uno mal clasificado: lo primero se ve y se corrige, lo segundo se queda ahí engañando a quien busca.

Paso 3: el orden de las reglas importa

Con el tipo de producto apareció el problema clásico: una descripción puede contener varias palabras clave a la vez. «Imprimación con acabado barniz» daría positivo en dos categorías.

Lo resolví ordenando las reglas de la más específica a la más genérica y parando en la primera coincidencia. Es menos elegante que un sistema de puntuación, pero es predecible: dada una descripción, siempre puedo explicar por qué salió esa categoría.

Paso 4: medir la cobertura de verdad

El 99,3 % no salió de una intuición. Definí la cobertura como el porcentaje de productos a los que el sistema asigna marca y tipo, y después revisé a mano una muestra para comprobar que lo asignado era correcto, no solo que estuviera relleno. Sin ese segundo paso, un sistema que etiquetara todo como «pintura» tendría un 100 % de cobertura y un 0 % de utilidad.

Una métrica que no puede bajar no está midiendo nada.

El 0,7 % que dejé sin resolver

Quedaron unos pocos productos imposibles: descripciones de dos palabras, referencias antiguas, casos únicos. Podría haber escrito reglas específicas para cada uno y presumir de 100 %, pero eso son reglas que nadie más entiende y que se rompen con el próximo Excel.

La solución fue de producto, no de código: esos productos aparecen marcados como «sin clasificar» y se corrigen a mano desde el propio inventario. El sistema hace el 99,3 % del trabajo aburrido y deja a la persona el 0,7 % que requiere criterio.

Lo que me llevo

  • Normalizar es la mitad del proyecto. Casi todos los «errores del algoritmo» eran errores de datos sucios.
  • Explicable gana a sofisticado cuando hay un cliente al que rendir cuentas.
  • Dejar un hueco para la persona no es un fallo de la automatización: es lo que hace que se pueda confiar en ella.
Mateo Ricci
Mateo Ricci Desarrollador full stack · Gran Canaria

Siguiente paso

¿Lo comentamos?

Si trabajas en algo parecido o no estás de acuerdo, me interesa mucho escucharlo.