Introducción
Actualmente estoy trabajando en el desarrollo de una aplicación web que utiliza la geolocalización del usuario para ofrecer bienes y servicios en su cercanía. Hasta ahora, la lógica de "inteligencia" era delegada: utilizo la API de OpenRouter (accediendo a modelos como GPT5 y Gemini) para clasificar lo que el usuario escribe en el buscador y así decidir qué lógica de código ejecutar.
El Problema
Sobre el papel, usar un LLM (Large Language Model) sonaba genial. Pero en la práctica, me topé con un gran problema: la latencia.
Cada consulta tarda hasta 5 segundos en procesarse. En el entorno web actual, donde todo debe ser instantáneo, hacer esperar al usuario 5 segundos solo para entender qué quiere es inaceptable. Además, depender de una API externa añade costos y una capa de complejidad que no controlo.
La Meta
Necesito una solución que cumpla tres requisitos:
Local: Que corra en mi propio servidor.
Baja Latencia: Que responda en milisegundos.
Control Total: Entender exactamente qué pasa bajo el capó.
El Nombre del Proyecto: "Prize"
Como anécdota personal, quería involucrar a mi hijo en este proyecto para tratar de despertar su curiosidad por la tecnología. Le pedí que bautizara a la red neuronal que estamos construyendo y, tras pensarlo, decidió llamarla "Prize".
Así que, oficialmente, el objetivo no es solo crear un clasificador, sino dar vida a Prize. Si logramos que funcione, el nombre le vendrá como anillo al dedo, porque será una verdadera recompensa después de pelear con tantos hiperparámetros y código.
La Idea: "Hardcore Mode"
Podría haber descargado TensorFlow o PyTorch y tener un modelo corriendo en una tarde. Pero mi objetivo no es solo solucionar el problema, sino aprender.
Por eso, he decidido construir mi propio clasificador de texto desde cero, utilizando únicamente Python y Numpy, basándome en el código del libro "Neural Networks and Deep Learning" de Michael Nielsen. Nada de frameworks modernos que esconden la matemática.
La Arquitectura: Reciclando Inteligencia
Para no empezar de cero absoluto, decidí aprovechar algo que ya tenía implementado. Mi aplicación cuenta con un sistema de recomendación que utiliza Embeddings (vectores numéricos que representan el significado semántico del texto).
Como ya tengo el inventario vectorizado, decidí usar estos embeddings como la entrada de mi red. El diseño inicial de la arquitectura es el siguiente:
Capa de Entrada (1024 neuronas): Corresponde al tamaño exacto de los vectores de embedding que ya utilizo.
Capa Oculta (100 neuronas): Decidí usar 100 neuronas para no hacer una reducción de dimensiones tan drástica y permitir que la red capture mejor los patrones.
Capa de Salida (2 neuronas): Aunque mi meta final es clasificar en 5 categorías de servicios, para esta primera etapa de entrenamiento voy a simplificar el problema. Empezaré con una clasificación binaria (2 clases). Si logro que funcione bien aquí, escalaré a las 5 categorías.
El Desafío de los Datos:
Aquí es donde la teoría chocó con la realidad de mi base de datos. Al revisar mi inventario para crear el dataset de entrenamiento, encontré un desbalance masivo:
- Farmacia: Tengo un inventario robusto de 6,000 ítems.
- Laboratorio Odontológico: Apenas tengo 20 ítems de referencia.
Si entreno la red con estos datos tal cual, aprenderá rápidamente a decir siempre "Farmacia" para maximizar su acierto, ignorando por completo al laboratorio.
La Estrategia: Data Sintética
Para solucionar esto, tengo un plan de ataque:
Filtrado: Voy a limpiar la data de farmacia para quedarme estrictamente con los medicamentos, eliminando ruido.
IA Generativa: Usaré la misma API de OpenRouter para generar data sintética. Tomaré los 20 ítems del laboratorio y le pediré a la IA que genere cientos de variaciones de cómo un usuario pediría esos servicios. Así equilibraré la balanza antes de entrenar.
¿En qué punto estoy?
Actualmente estoy procesando la materia prima: estoy filtrando el inventario de 6,000 ítems de farmacia para preparar el dataset de entrenamiento.
Mi meta es tener la data limpia y lista para la próxima semana y correr las primeras pruebas de concepto. Documentaré los primeros resultados (sean buenos o malos) en la segunda parte de esta serie.
Top comments (0)