15 lecciones para llegar aquí. Ahora todo encaja: el ciclo de entrenamiento, la caída de la pérdida, y el modelo que aprendió a inventar nombres que suenan reales.
Entrenar un modelo es repetir el mismo ciclo de cuatro pasos miles de veces. En cada repetición, los pesos del modelo cambian un poco — y cada cambio hace que el modelo sea un poco mejor prediciendo el siguiente carácter.
Microgpt repite este ciclo 1000 veces con batches aleatorios de 32 nombres. Cada iteración toma ≈1 ms en CPU. Total: 1 segundo de entrenamiento.
Al principio, la red es completamente aleatoria. Sus predicciones son casi uniformes: asigna probabilidad ≈ 1/27 ≈ 0.037 a cada letra. La pérdida de eso es -log(1/27) ≈ 3.3.
Después de 1000 pasos, la pérdida cae a ≈ 2.37. Eso significa que la probabilidad promedio asignada a la letra correcta subió de 0.037 a ≈ 0.094 — casi 3 veces mejor que el azar.
La pérdida cae rápidamente en los primeros 100 pasos y luego se estabiliza gradualmente. La línea punteada marca la pérdida aleatoria (3.3) y el target final (2.37).
Pérdida 3.30: modelo aleatorio
p_correcta ≈ e^(-3.30) ≈ 0.037 = 1/27
El modelo no sabe nada. Elige al azar entre 27 tokens.
Pérdida 2.37: modelo entrenado (microgpt después de 1000 pasos)
p_correcta ≈ e^(-2.37) ≈ 0.094
El modelo asigna el 9.4% de probabilidad a la letra correcta.
Parece poco, pero el azar sería 3.7% — es 2.5x mejor.
Pérdida 1.5: modelo excelente (GPT-2 en texto general)
p_correcta ≈ e^(-1.5) ≈ 0.22
El modelo tiene idea de qué viene después la mayoría del tiempo.
Pérdida 0: modelo perfecto (imposible en texto natural)
p_correcta = 1.0 para todo token
Implicaría que el texto es completamente determinista.
El lenguaje natural no lo es.
Por eso microgpt se queda en 2.37:
- El dataset de nombres tiene alta variabilidad ("a" puede seguirse de
casi cualquier consonante)
- Con 3.808 parámetros, hay límite a cuánto puede capturar la red
- GPT-4 con miles de millones de parámetros llega mucho más bajo
Cuando generamos nombres, no siempre queremos elegir la letra más probable. Si siempre elegimos la más probable, todos los nombres saldrían iguales. La temperatura controla cuánta "variedad" tiene la generación.
El modelo produce logits: puntuaciones sin normalizar para cada token.
Antes del softmax, dividimos los logits por la temperatura T:
probs = softmax(logits / T)
Temperatura T = 1.0 (por defecto):
No cambia nada. Se usa la distribución tal como salió de la red.
Genera nombres variados pero a veces extraños.
Temperatura T = 0.5 (más conservador):
Los logits se amplían (÷ 0.5 = ×2).
Las diferencias se magnifican → el token más probable domina más.
Nombres más "comunes" y predecibles.
Temperatura T = 2.0 (más creativo):
Los logits se comprimen (÷ 2 = × 0.5).
Las diferencias se reducen → distribución más uniforme.
Nombres más originales, pero también más "raros".
Ejemplo con logits para ['a'=2.1, 'r'=1.5, 'n'=0.8, 'x'=0.1]:
T=0.5: softmax([4.2, 3.0, 1.6, 0.2]) → 'a' domina: [0.68, 0.22, 0.09, 0.01]
T=1.0: softmax([2.1, 1.5, 0.8, 0.1]) → balanceado: [0.46, 0.26, 0.14, 0.07] (approx)
T=2.0: softmax([1.05,0.75,0.40,0.05])→ más uniforme: [0.37, 0.28, 0.19, 0.14]
Ajusta la temperatura y genera nombres. Observa cómo cambia el estilo con el mismo modelo:
Hemos recorrido un camino largo. Este diagrama muestra cómo cada lección construyó sobre la anterior para llegar a microgpt:
Cada lección eliminó una caja negra. El resultado final no tiene secretos: 200 líneas de Python, cero dependencias, y nombres que suenan reales.
GPT-4 tiene ~1.000.000.000.000 parámetros en lugar de 3.808.
Tiene ~96 bloques en lugar de 1.
Fue entrenado con billones de tokens en lugar de 32.000 nombres.
Pero la arquitectura es la misma que acabas de entender.