English · Español
Lab 01 — Línea base de n-gramas¶
Objetivo: comprometer el número de perplejidad que el Mini-GPT de las Fases 17–18 tiene que batir.
Tiempo estimado: 90–120 minutos.
Prerrequisito: lab 00 (splits tokenizados) comprometido.
Lo que produces¶
Un directorio experiments/14-ngram-baseline/ que contiene:
ngram.py— tu implementación del modelo de lenguaje de n-gramas (según el blueprint desrc/minimodel/sequence_baselines/ngram.py).train.py— ajusta 3-gramas y 5-gramas sobre el split de train, evalúa la perplejidad en dev.results.json— números de perplejidad para \(n \in \{1, 2, 3, 4, 5, 6, 7\}\) en dev.perplexity_vs_n.png— gráfica de perplejidad en dev frente a \(n\).manifest.json— segúnLYNX_CORTEX.md§5.README.md(2–3 párrafos) — qué significan los números.
El modelo¶
Implementa NGramLM según el blueprint en src/minimodel/BLUEPRINT.md §1. API pública:
class NGramLM:
def __init__(self, n: int, alpha: float = 0.01, vocab_size: int): ...
def fit(self, sequences: list[list[int]]) -> None: ...
def logp_token(self, context: tuple[int, ...], token: int) -> float: ...
def logp_sequence(self, sequence: list[int]) -> float: ...
def perplexity(self, sequences: list[list[int]]) -> float: ...
Estructura de almacenamiento: un dict[tuple[int, ...], collections.Counter] que mapea contexto (los últimos \(n-1\) tokens) a un contador sobre el siguiente token.
TODOs¶
Bloque A — implementar el modelo¶
- Pre-rellena cada secuencia con \((n-1)\) copias del token
<bos>antes de contar. - Construye un
dict[context_tuple -> Counter[next_token]]a partir del split de train. - Almacena también
context_totals: dict[context_tuple -> int]para \(c(\text{context})\) — por comodidad. - Implementa
logp_token(context, token)usando suavizado add-\(\alpha\). - Implementa
perplexity(sequences)según la fórmula entheory/01-ngram-models.md. - Test de cordura: entrena sobre un corpus de juguete diminuto (5 secuencias), confirma que
logp_tokenes razonable, confirma que la perplejidad se calcula correctamente. Test unitario antes de evaluar.
Bloque B — ajustar y evaluar¶
Para cada \(n \in \{1, 2, 3, 4, 5, 6, 7\}\):
- Ajusta sobre
train_ids. - Calcula la perplejidad sobre
dev_ids. - Registra (n, perplexity_train, perplexity_dev) en
results.json.
Dibuja perplexity_vs_n.png con \(n\) en el eje x, la perplejidad en el eje y (escala logarítmica). Pinta las curvas de train y dev.
Bloque C — la sonda de completado de conjugación¶
Más allá de la perplejidad, el resultado cualitativo titular es la tarea de completado de conjugación:
- Para el 3-grama y el 5-grama, calcula los 5 tokens predichos top dado el prompt
<bos> <bos> I work , you work , he. - Imprime y compromete la lista ordenada con probabilidades.
- Resultado esperado: el top-1 debería ser
workspara el 5-grama. El 3-grama podría escogerwork(si su ventana no alcanza el pronombre); compruébalo empíricamente.
Repite para otros dos prompts:
- <bos> <bos> I worked , you worked , he → esperado worked.
- <bos> <bos> I will work , you will work , he → esperado will.
Compromete los resultados como conjugation_completion.json.
Bloque D — interpretar¶
En README.md:
- Indica la línea base. "La perplejidad en dev para \(n=5\) es X. Este es el número que la Fase 17/18 tiene que batir."
- Comenta la curva en U. La perplejidad-vs-n típicamente decrece con \(n\) hasta el punto donde el suavizado domina, y luego crece (porque la mayoría de n-gramas no aparecen → toda la masa va a \(\alpha |V|\)). ¿Dónde está el mínimo para nuestro corpus? ¿Qué dice eso sobre la localidad de la dependencia pronombre-sujeto → forma verbal?
- Observación de completado de conjugación. ¿Predijo el 3-grama correctamente
works? Si sí: indica que la tarea es local (una ventana de 3 basta). Si no: indica que la tarea requiere contexto más largo — puente a la Fase 15. - Pregunta bilingüe (opcional). ¿Aprendió el n-grama el alineamiento entre
I work / yo→trabajo? Calcula la perplejidad de solo los tokens del lado español condicionada al prefijo del lado inglés. Compara con la perplejidad incondicional del español. La diferencia es la "habilidad de traducción" del modelo.
Bloque E — manifest¶
{
"experiment": "14-ngram-baseline",
"date": "YYYY-MM-DD",
"seed": 42,
"config": {
"n_values": [1, 2, 3, 4, 5, 6, 7],
"alpha": 0.01,
"tokenization": "from lab 00 manifest"
},
"results_summary": {
"best_n": null,
"best_dev_perplexity": null,
"conjugation_top1_correct": null
},
"versions": {"python": "3.11.x", "numpy": "X.Y.Z"}
}
Rellena los nulls.
Restricciones¶
- Sin PyTorch. Solo NumPy y biblioteca estándar.
- Sin librerías externas de n-gramas (ni
nltk, nikenlm). Construye el dict tú mismo; ese es el sentido del lab. - Determinista. Pon semilla a cada shuffle. Documenta en el manifest.
- Suavizado fijado a \(\alpha = 0.01\) para el número titular. Puedes barrer \(\alpha\) como extensión, pero la línea base comprometida usa \(\alpha = 0.01\).
Condiciones de parada¶
Hecho cuando:
- El directorio tiene los seis archivos.
results.jsonmuestra números de perplejidad para los 7 valores de \(n\).perplexity_vs_n.pngse ve y está etiquetada.conjugation_completion.jsonmuestra el top-5 para al menos 3 sondas.README.mdresponde a las cuatro preguntas de interpretación.
Trampas (léelas antes de depurar)¶
- Perplejidad infinita. O se te olvidó el suavizado, o tu tokenizer está produciendo
<unk>para tokens de evaluación que no aparecieron en entrenamiento. Comprueba las dos cosas. - Perplejidad MÁS BAJA en test que en train. O es un bug, o un desajuste de tokenización. Train debería ser más fácil (el modelo lo memorizó).
- La predicción top-1 para
he ___es<eos>. Esto significa que(<sep>, he)va seguido más a menudo de fin-de-secuencia en tu conjunto de entrenamiento — posiblemente por cómo formateaste las filas. Comprueba el formato del prompt. - El 3-grama es PEOR que el 1-grama. Posible si tu corpus es tan pequeño que la mayoría de trigramas no aparecen y el suavizado domina. Comprueba
len(set(trigram_contexts_seen))— debería ser de cientos para un corpus sano. - La perplejidad del español es mucho más alta que la del inglés. Probablemente un artefacto de tokenización — los caracteres del español (
á,é,ñ) pueden producir más piezas subpalabra, inflando la perplejidad por token. Documéntalo pero no lo arregles.
Cuándo consultar solutions/¶
Después de haber comprometido los seis archivos y respondido a las cuatro preguntas de interpretación. La solución en solutions/01-ngram-baseline-ref.md compara tus números con una referencia y discute los casos límite habituales.
Siguiente lab: lab/02-rnn-by-hand.md.