Skip to content

English · Español

01 — 25 Preguntas de Whiteboard ML con Árboles de Profundidad

25 preguntas clásicas de whiteboard ML, cada una con respuesta de 3 párrafos, árbol de follow-ups de 3 niveles, y la "trampa" (qué respuesta incorrecta revela falta de profundidad).

La "señal de profundidad"

Los labs top no puntúan amplitud — cada aplicante conoce las palabras de moda. Puntúan profundidad: ¿puedes ir tres niveles más profundo que la respuesta superficial sin titubear? Cada pregunta abajo lleva un árbol de follow-up de 3 niveles mostrando cómo empujará un entrevistador.

La anotación pit-of-failure es lo que tu respuesta incorrecta revela sobre ti — usualmente que has leído sobre el tema pero no lo has implementado.


Q1 — Explica attention.

Respuesta modelo (3 párrafos).

Attention es una búsqueda basada en contenido. Dado un vector query q, un conjunto de vectores key K, y un conjunto de vectores value V, attention computa un promedio ponderado de V donde los pesos son similitudes entre q y cada fila de K. Concretamente: softmax(q K^T / sqrt(d_k)) V. El escalado sqrt(d_k) existe porque el producto punto de dos vectores d_k-dimensionales con entradas de varianza unitaria tiene varianza d_k, así que sin escalado el softmax satura y los gradientes desaparecen.

Self-attention es el caso donde Q, K, V son proyecciones lineales del mismo input. Multi-head attention divide la dimensión de embedding en h heads, ejecuta attention en paralelo por head, y concatena. La motivación es que un softmax mezcla posiciones de una forma; múltiples heads permiten a la capa atender a múltiples relaciones (e.g. head sintáctico, head semántico).

El coste es O(n^2 d) en cómputo y O(n^2) en memoria por head (la matriz de attention). Este es el cuello de botella dominante para contexto largo; FlashAttention elimina el coste de memoria n^2 mediante tiling y recomputo en el backward pass.

Árbol de profundidad. - L1: ¿Por qué sqrt(d_k)? (argumento de varianza arriba) - L2: ¿Por qué la saturación de softmax mata gradientes? (las derivadas off-diagonales del softmax van a cero) - L3: ¿Cuál es el gradiente exacto del softmax a través de la matriz de attention? (dA = (P - P^T diag(P^T g)) g para output g — ver drill 01)

Pit-of-failure. Decir "attention es como una búsqueda en base de datos" sin poder escribir la fórmula. Señales: leíste el blog post, nunca lo programaste.

→ Fase 15 del currículo central.


Q2 — ¿Por qué layer normalization ayuda al entrenamiento?

Respuesta modelo.

LayerNorm normaliza el vector de activación de cada token a media cero, varianza unitaria a lo largo de la dimensión de features, luego aplica una afín aprendida gamma * x + beta. Empíricamente estabiliza el entrenamiento en transformers, donde los tamaños de batch pueden ser pequeños y las secuencias heterogéneas.

El encuadre original (Ba et al. 2016) fue "reducir covariate shift entre capas". El paper de Santurkar et al. 2018 argumentó que esto no es lo que hace BatchNorm, y el beneficio real es que la normalización suaviza el paisaje de pérdida (reduce la constante de Lipschitz de la pérdida). El mismo argumento aplica a LayerNorm.

En transformers, pre-LN (normalizar antes del bloque residual) entrena más establemente que post-LN a gran profundidad porque la varianza del residual stream no crece con la profundidad. Pre-LN es lo que usan GPT-2 y todo transformer posterior.

Árbol de profundidad. - L1: Pre-LN vs post-LN — ¿cuál? (pre-LN; las gradient norms se mantienen acotadas en profundidad) - L2: ¿Por qué RMSNorm funciona tan bien como LayerNorm? (empíricamente la sustracción de media no es crítica; el escalado de varianza sí) - L3: ¿Cuál es el backward pass de LayerNorm? (involucra los gradientes de media y varianza — ver drill 08)

Pit-of-failure. "Normaliza activaciones". ¿Por qué? ¿Cuándo? ¿Fórmula forward? ¿Backward? — silencio.

→ Fase 10, drill 08.


Q3 — ¿Cuál es el bias-variance tradeoff en modelos modernos sobreparametrizados?

Respuesta modelo.

La curva clásica de bias-variance predice una forma U: modelos demasiado simples infraajustan (alto bias), modelos demasiado complejos sobreajustan (alta varianza). Las redes neuronales modernas sobreparametrizadas violan esto — el error de test a menudo decrece monotónicamente con el conteo de parámetros más allá del umbral de interpolación. Este es el fenómeno "double descent" (Belkin et al. 2019, Nakkiran et al. 2020).

El mecanismo: entre las muchas soluciones que interpolan los datos de entrenamiento, SGD tiene un sesgo implícito hacia soluciones de baja norma, y las soluciones de baja norma generalizan. Así que "más parámetros" no significa "más varianza" en el sentido clásico — significa más espacio para que SGD encuentre un mínimo plano.

Para propósitos prácticos: en el régimen donde operan los LMs modernos (1B+ parámetros, billones de tokens), el encuadre correcto no es bias-variance sino compute-optimality (Chinchilla). La pregunta "¿es mi modelo demasiado grande?" se responde con "¿eres compute-optimal dado tu presupuesto de tokens?".

Árbol de profundidad. - L1: ¿Qué es double descent? (epoch-wise vs model-wise, ambos observados) - L2: ¿Qué significa "regularización implícita de SGD" precisamente? (encuentra soluciones de baja norma / planas entre los interpoladores) - L3: ¿Cómo relaciona Chinchilla cómputo a parámetros? (N ∝ D, ambos ∝ sqrt(C); ver paper-read 04)

Pit-of-failure. Citar la curva U clásica como si fuera universal. Señales: modelo mental pre-2019.


Q4 — Explica backpropagation.

Respuesta modelo.

Backpropagation es la regla de la cadena aplicada a un grafo computacional. Forward pass: evalúa cada nodo, almacena activaciones intermedias. Backward pass: para cada nodo de output a input, multiplica el gradiente entrante por el Jacobiano local de ese nodo. El "truco" es que almacenas activaciones en el forward pass para que el backward pass sea O(coste forward), no O(coste forward * profundidad).

Para una pérdida escalar L y un parámetro w en alguna capa: dL/dw = dL/dy * dy/dw, donde dL/dy es el gradiente fluyendo hacia la capa (computado por recursión) y dy/dw es el Jacobiano local. La forma matrix-multiply: si y = W x, entonces dL/dW = (dL/dy) x^T y dL/dx = W^T (dL/dy).

Crucialmente, backprop no es diferenciación automática en general — es reverse-mode AD. Forward-mode AD es O(dim input) por derivada; reverse-mode es O(dim output). Para ML tenemos pérdida escalar (dim output = 1) y millones de parámetros, así que reverse-mode gana por un factor de n_params.

Árbol de profundidad. - L1: ¿Por qué reverse-mode y no forward-mode? (pérdida escalar, miles de millones de params) - L2: ¿Qué intercambia activation checkpointing? (memoria vs recomputo en backward) - L3: ¿Cómo interactúa gradient checkpointing con mixed precision? (activaciones almacenadas en fp16/bf16, recomputa en el mismo dtype — ver drill 03)

Pit-of-failure. "Propaga errores hacia atrás" sin poder escribir dL/dW = dL/dy x^T. Señales: sin experiencia de implementación de autograd.

→ Fase 07 (scalar autograd), Fase 08 (tensor autograd).


Q5 — ¿Por qué Adam supera a SGD para transformers?

Respuesta modelo.

Adam mantiene promedios móviles por parámetro del gradiente (m_t) y del gradiente al cuadrado (v_t), y actualiza theta -= lr * m_t / (sqrt(v_t) + eps). El término 1/sqrt(v_t) hace la tasa de aprendizaje efectiva por parámetro — features raras con gradientes grandes pero infrecuentes se escalan hacia abajo; features frecuentes con gradientes pequeños se escalan hacia arriba.

Para transformers específicamente, la distribución de gradientes es heavy-tailed (unos pocos attention heads, unas pocas capas dominan). SGD con una sola tasa de aprendizaje o se pasa en las direcciones dominantes o se queda corto en las raras. El escalado por parámetro de Adam maneja esto automáticamente.

El coste: 2x memoria de parámetros (los estados m y v). Para modelos 7B eso es 14B floats. AdamW adicionalmente desacopla weight decay del gradiente, que es lo que usa todo entrenador moderno de transformer (Loshchilov & Hutter 2019).

Árbol de profundidad. - L1: Adam vs AdamW — ¿qué diferencia? (AdamW desacopla L2 weight decay del gradiente) - L2: ¿Cómo interactúan beta_1, beta_2 con el tamaño de batch? (batches más grandes → menos ruido → puedes bajar beta_2) - L3: ¿Por qué vemos Adam-8bit / Adam-Lion / Sophia en 2024+? (presión de memoria por estados de Adam; Sophia usa diagonal del Hessiano)

Pit-of-failure. "Adam es adaptativo". Adaptativo ¿a qué? — silencio.


Q6 — Explícame la pérdida de cross-entropy y su gradiente.

Respuesta modelo.

Para una distribución categórica con K clases y un target one-hot y (clase verdadera c), la pérdida de cross-entropy es L = -log p_c donde p = softmax(z) y z son los logits. Equivalentemente: L = -log( exp(z_c) / sum_k exp(z_k) ) = -z_c + logsumexp(z).

El gradiente respecto a los logits es famosamente limpio: dL/dz = p - y. Es decir, el gradiente es la probabilidad predicha menos el target one-hot. Derivación: dL/dz_k = -delta_{ck} + p_k, que es p_k - y_k ya que y es one-hot.

Por estabilidad numérica nunca computamos exp(z) directamente — usamos el truco log-sum-exp: resta max(z) antes de exponenciar. La mayoría de frameworks fusionan esto en una sola op cross_entropy(logits, target) que toma logits crudos, no outputs de softmax.

Árbol de profundidad. - L1: ¿Por qué el gradiente se simplifica a p - y? (derivación arriba) - L2: ¿Qué es label smoothing y qué le hace al gradiente? (reemplaza one-hot con (1-eps) y + eps/K; el gradiente se convierte en p - y_smooth) - L3: ¿Cómo interactúa esto con RLHF regularizado con KL? (el término KL añade log(p / p_ref); el gradiente añade 1/p - 1/p_ref efectivamente)

Pit-of-failure. Intentar escribir softmax luego log luego nll como ops separadas. Señales: sin instinto de estabilidad numérica.

→ Fase 05, Fase 17.


Q7 — Explica tokenización BPE.

Respuesta modelo.

Byte-Pair Encoding empieza con el vocabulario de todos los bytes individuales (256 para BPE byte-level, usado por GPT-2+). Iterativamente encuentra el par adyacente más frecuente de tokens en el corpus de entrenamiento y los fusiona en un nuevo token. Tras N merges el vocabulario tiene 256 + N entradas. En inferencia, aplicas los mismos merges en el mismo orden para tokenizar texto nuevo.

El truco: BPE balancea tamaño de vocabulario contra longitud de secuencia. Character-level: vocab pequeño, secuencias largas, lento. Word-level: vocab grande, problemas de OOV en palabras raras. BPE: subwords. Palabras comunes se vuelven un solo token (" the"); palabras raras se vuelven múltiples subwords ("unhappiness" → "un" + "happiness" o similar).

BPE byte-level (GPT-2) empieza desde bytes crudos, no codepoints Unicode, así que maneja cualquier input sin OOV. El coste es que un carácter Unicode puede tomar 1-4 tokens. Tiktoken (OpenAI), tokenizers (HuggingFace) y SentencePiece (Google) son las tres implementaciones de producción.

Árbol de profundidad. - L1: ¿Por qué byte-level y no character-level? (sin OOV Unicode; determinista en cualquier input) - L2: ¿Cuál es el ratio de tokenización peor caso para un idioma no-inglés? (puede ser 3-4x inglés para CJK; ver diseños de tokenizer Mistral/Cohere) - L3: ¿Cómo entrenarías un tokenizer optimizado para código? (pondera fuertemente el corpus de código; preserva patrones de whitespace; tab es un token)

Pit-of-failure. Confundir BPE con WordPiece (BERT). Señales: no implementaste ninguno.

→ Fase 11, drill 02.


Q8 — ¿Cuál es la diferencia entre arquitecturas encoder, decoder y encoder-decoder?

Respuesta modelo.

Encoder (BERT): self-attention bidireccional sobre el input. El output es un vector por token de input. Entrenado con masked language modeling: enmascara 15% de tokens, predícelos. Usado para tareas de comprensión (clasificación, extracción).

Decoder (GPT): self-attention causal — cada token atiende solo a tokens previos. Entrenado con predicción del siguiente token. Usado para generación. Los modelos frontera modernos (GPT-4, Claude, Gemini, Llama 3) son decoder-only.

Encoder-decoder (T5, Transformer original para traducción): el encoder procesa input bidireccionalmente, el decoder genera output autorregresivamente mientras hace cross-attention al output del encoder. Usado históricamente para traducción, resumen. Mayormente subsumido por decoder-only en 2023+ porque puedes hacer prompting a un modelo decoder-only para hacer cualquiera de estas tareas.

Árbol de profundidad. - L1: ¿Por qué ha ganado decoder-only? (escala + prompting subsume arquitecturas especializadas; un modelo para todas las tareas) - L2: ¿Cuándo seguirías escogiendo encoder-decoder? (ratios de input-muy-largo → output-corto donde el cuello de botella del encoder es aceptable, e.g. algún resumen, traducción de código) - L3: ¿Qué es "prefix LM" y por qué es interesante? (decoder con attention bidireccional sobre el prefijo; posiblemente lo mejor de ambos mundos, ver UL2 / PaLM-2)

Pit-of-failure. Listar los tres sin poder articular por qué ganó decoder-only. Señales: conocimiento de libro de texto, sin gusto.


Q9 — Explícame el forward y backward pass de dropout.

Respuesta modelo.

Forward (entrenamiento): muestrea una máscara Bernoulli m con probabilidad 1-p de ser 1; output y = x * m / (1-p). El escalado 1/(1-p) ("inverted dropout") hace que la expectativa de y sea igual a x, así que no se necesita escalado en inferencia. Inferencia: identidad (y = x).

Backward: el gradiente local de dropout es solo la máscara. dL/dx = (dL/dy) * m / (1-p). Sin parámetros aprendidos, sin estado entre batches.

Dropout reduce la co-adaptación de features forzando a la red a ser robusta a unidades faltantes. En transformers, dropout se aplica (a) en las probabilidades de attention, (b) en el output del FFN, © en los embeddings. Los modelos frontera modernos a menudo quitan dropout porque a escala de billones de tokens, entrenas menos de una época — la regularización implícita de los gradientes estocásticos es suficiente.

Árbol de profundidad. - L1: ¿Por qué escalar por 1/(1-p) en entrenamiento y no en inferencia? (más fácil de razonar; inferencia es el hot path) - L2: ¿Por qué los LMs grandes a menudo saltan dropout? (régimen sub-entrenado; una época; la reg implícita de SGD basta) - L3: ¿Qué es "DropPath" / stochastic depth y cómo difiere? (elimina bloques residuales enteros, no unidades; usado en ViT, ConvNeXt)

Pit-of-failure. Olvidar el escalado 1/(1-p). Señales: nunca escribiste el forward pass desde cero.


Q10 — ¿Cómo funciona el KV cache y por qué es necesario?

Respuesta modelo.

Durante la generación autorregresiva, cada nuevo token requiere atender a todos los tokens previos. Naivamente, recomputarías keys y values para todo el prefijo en cada paso — eso es O(n^2) sobre n pasos de generación, o O(n^3) total. El KV cache almacena las matrices K y V de pasos previos y solo computa la nueva fila, reduciendo el coste total a O(n^2).

El tamaño del cache por capa por head es 2 * n * d_head * dtype_bytes (uno para K, uno para V). Para un modelo 7B con 32 capas, 32 heads, d_head=128, fp16, y n=2048: 2 * 2048 * 32 * 32 * 128 * 2 = 1.07 GB. Por request. Por esto la inferencia de contexto largo está limitada por memoria, no por cómputo.

Optimizaciones: PagedAttention (vLLM) trata el KV cache como memoria virtual con páginas de tamaño fijo, reduciendo fragmentación. Multi-query attention (MQA) y grouped-query attention (GQA) comparten K/V entre heads (Llama 2 70B usa GQA-8), encogiendo el cache 4-8x. Sliding-window attention (Mistral) limita n a un tamaño de ventana.

Árbol de profundidad. - L1: ¿Cuál es la fórmula exacta de tamaño del KV cache? (2 * num_layers * num_kv_heads * d_head * seq_len * dtype_bytes por request) - L2: ¿Cómo reduce PagedAttention la fragmentación? (bloques de tamaño fijo; puede compartir prefijo entre beams) - L3: ¿Cuál es el tradeoff de MQA vs GQA vs MHA? (MQA: 1 KV head, cache más pequeño, ligera pérdida de calidad; GQA: grupos de heads, punto dulce; MHA: calidad completa, cache más grande)

Pit-of-failure. "Cachea keys y values" sin las matemáticas de memoria. Señales: nunca dimensionaste un deployment.

→ Fase 22, drill 04.


Q11 — ¿Qué es positional encoding y por qué lo necesitamos?

Respuesta modelo.

Self-attention es permutation-equivariant: barajar los tokens de input produce un barajado correspondiente del output, así que el modelo no puede distinguir "perro muerde hombre" de "hombre muerde perro" sin información explícita de posición. El positional encoding inyecta esta información.

Dos familias. Absoluta: añade un vector fijo o aprendido al embedding de cada token. El Transformer original usó sinusoides de frecuencias variables (sin(pos / 10000^(2i/d))); BERT/GPT-2 usaron vectores aprendidos. Relativa: sesga los attention scores por una función de (i - j). Ejemplos: el bias bucketizado de T5, ALiBi (bias lineal por distancia, usado en MosaicML / Falcon), RoPE.

RoPE (Rotary Positional Embedding, Su et al. 2021) es el default moderno (Llama, Mistral, Qwen). Rota Q y K por un ángulo proporcional a la posición antes de computar Q K^T. El producto interno (R_i q)^T (R_j k) depende solo de (i - j) — así que es relativa, pero implementada como una rotación por token. RoPE extiende a contexto largo con escalado NTK-aware.

Árbol de profundidad. - L1: ¿Por qué los embeddings sinusoidales pueden extrapolar? (en teoría: funciones lineales de posición; en práctica: mal) - L2: ¿Cómo rota RoPE realmente? (divide embedding en pares, aplica una rotación 2D por par, las frecuencias siguen el schedule sinusoidal) - L3: ¿Qué hace YaRN / NTK-scaling para extender el contexto de RoPE? (interpola la rejilla de posición; reescala la frecuencia base para evitar ángulos de rotación OOD en contexto largo)

Pit-of-failure. Recitar "sinusoidal" sin saber que RoPE existe. Señales: atascado en 2017.

→ Fase 16, drill 10.


Q12 — Explica la cadena de operaciones en un bloque transformer.

Respuesta modelo.

Bloque transformer moderno (pre-LN): x → LN → MHA → +x → LN → FFN → +x. Dos residual streams, dos normalizaciones, dos sub-bloques. El residual es la clave de la profundidad — sin él, los gradientes mueren exponencialmente con la profundidad (Fase 10).

MHA: Q, K, V = x W_Q, x W_K, x W_V; divide en heads; attn = softmax(Q K^T / sqrt(d_k)) V (por head); concat heads; proyecta con W_O. Coste: O(n^2 d + n d^2).

FFN: típicamente Linear(d, 4d) → activation → Linear(4d, d). La expansión 4d es convencional. La activación ha evolucionado: ReLU (original) → GELU (BERT, GPT-2) → SwiGLU (Llama, moderno). SwiGLU es Swish(x W_1) * (x W_3) → W_2, gated, con 3 matrices en vez de 2 (así el FFN es más ancho por parámetro).

Árbol de profundidad. - L1: ¿Qué te aporta SwiGLU sobre GELU? (empíricamente mejor perplejidad a iso-params; el gating ayuda) - L2: ¿Dónde vive la mayor parte del presupuesto de parámetros en un transformer? (en el FFN — aproximadamente ⅔, más con SwiGLU) - L3: ¿Por qué pre-LN en vez de post-LN a escala? (Xiong et al. 2020: pre-LN mantiene gradient norms acotadas; post-LN necesita trucos de warmup a profundidad > 12)

Pit-of-failure. Olvidar que existen residuales, o poner LN en el sitio equivocado. Señales: nunca escribiste forward().

→ Fase 17.


Q13 — ¿Cómo depurarías una ejecución de entrenamiento donde la pérdida es NaN en el paso 1000?

Respuesta modelo.

Paso 1: identifica qué es NaN. ¿Pérdida? ¿Una activación? ¿Un gradiente? Culpables comunes: (a) gradientes explosivos → revisa grad_norm; (b) división por cero en softmax / layernorm → revisa valores epsilon; © overflow fp16 → cambia a bf16 o fp32 para la capa sospechosa; (d) data mala → revisa el batch que lo disparó.

Paso 2: bisecta. Guarda un checkpoint en el paso 999, reproduce el paso 1000 determinísticamente (semilla + mismo batch). Si es reproducible: instrumenta. Si no: depende de la data o del rng.

Paso 3: instrumenta con register_forward_hook (PyTorch) o equivalente. Loguea max/min/media de activación por capa. Encuentra la primera capa donde la activación explota. Desde ahí usualmente está claro: una capa de attention sin clipping, un softmax sin escalado, un residual que creció ilimitadamente a través de la red, o un pico de LR de un scheduler malo.

Árbol de profundidad. - L1: ¿Por qué grad clipping (e.g. clip_grad_norm_(model.parameters(), 1.0)) es estándar? (captura picos transitorios de batches raros) - L2: ¿Cómo distingues overflow fp16 de una divergencia real? (cambia a bf16 con mismo lr; si desaparece, era fp16) - L3: ¿Cuál es el patrón "spike → recover" en curvas de pérdida de pretraining de LLM? (los picos de pérdida son normales a escala; logs de PaLM, OPT los documentan; usualmente por batches malos)

Pit-of-failure. "Bajaría la tasa de aprendizaje". (¡Tal vez! Pero eso es después de entender la causa.)

→ Fase 19, anécdota behavioral 2.


Q14 — ¿Cuál es la diferencia entre SFT, RLHF y DPO?

Respuesta modelo.

SFT (ajuste fino supervisado): pérdida estándar de predicción del siguiente token sobre demostraciones humanas de alta calidad. Barato, simple, pero el modelo solo puede imitar lo que vio — no aprende de ejemplos negativos.

RLHF (Christiano 2017, Ouyang 2022): tres etapas. (1) SFT. (2) Entrena un reward model en preferencias humanas por pares usando la verosimilitud Bradley-Terry: P(a > b) = sigmoid(r(a) - r(b)). (3) RL-ajusta finamente el modelo SFT para maximizar r(x, y) - beta * KL(pi || pi_SFT), típicamente usando PPO. El término KL previene reward hacking.

DPO (Rafailov 2023): observación de que el óptimo de RLHF tiene una solución de forma cerrada pi*(y|x) = pi_ref(y|x) exp(r(x,y)/beta) / Z(x). Reordenando da r(x,y) = beta log(pi(y|x) / pi_ref(y|x)) + beta log Z. Sustituyendo en la pérdida Bradley-Terry da una pérdida simple de estilo clasificación sobre pares de preferencia directamente sobre el LM, sin reward model y sin RL. Más barato, más estable, calidad comparable en la mayoría de benchmarks.

Árbol de profundidad. - L1: ¿Por qué existe la penalización KL-a-referencia? (previene que la política RL derive a regiones off-distribution donde el reward model es poco fiable) - L2: Deriva la pérdida DPO desde el óptimo RLHF. (Lagrangiano → forma cerrada → sustitución BT; ver X3 theory/04) - L3: ¿Cuándo falla DPO vs RLHF? (DPO es sensible al ruido de preferencias; el RM de RLHF promedia sobre muchas preferencias; algunos papers encuentran que DPO va peor en matemáticas / código)

Pit-of-failure. Saber que DPO existe pero no poder derivar la pérdida. Señales: leíste el abstract, saltaste §3.

→ Módulo X3, drill 06.


Q15 — ¿Cómo funciona FlashAttention?

Respuesta modelo.

La attention estándar materializa la matriz de attention n x n en HBM (high-bandwidth memory). Para n = 4096 y fp16, eso son 32 MB por head — y leemos/escribimos dos veces (forward + backward). El ancho de banda de HBM es el cuello de botella.

FlashAttention (Dao et al. 2022) tilea el cómputo: carga un bloque de Q y un bloque de K, V en SRAM, computa softmax parcial incrementalmente, acumula el output. La matriz completa n x n nunca se materializa en HBM. El forward pass es exacto (no aproximado).

Backward pass: las activaciones del forward pass normalmente costarían O(n^2) almacenar. FlashAttention en su lugar almacena solo el normalizador del softmax y recomputa la matriz de attention bloque por bloque en el backward pass. Resultado neto: 2-4x aceleración en entrenamiento, aceleración mucho mayor en contexto largo.

Árbol de profundidad. - L1: ¿Cuál es el truco "online softmax"? (cómputo en streaming de softmax con max corrido + suma corrida, numéricamente estable) - L2: ¿Por qué FlashAttention-2 mejora sobre v1? (mejor paralelización a lo largo de la longitud de secuencia, menos flops non-matmul) - L3: ¿Cómo usa FlashAttention-3 (Hopper) TMA / async? (warp-specialization asíncrona; tensor memory accelerator en H100)

Pit-of-failure. "Es solo un kernel más rápido". ¿Por qué es más rápido? — silencio.

→ Fase 24, Fase 27.


Q16 — ¿Qué es entrenamiento en mixed precision?

Respuesta modelo.

Mixed precision (Micikevicius 2017) mantiene los pesos del modelo y el estado del optimizer en fp32 pero hace los forward y backward passes en fp16 (o bf16). El forward es más rápido (fp16 tiene 2x throughput en tensor cores) y usa la mitad de memoria para activaciones.

El detalle: fp16 tiene un rango dinámico estrecho (6e-5 a 65504). Los gradientes pequeños hacen underflow a cero. Solución: loss scaling — multiplica la pérdida por un factor grande (e.g. 65536) antes del backward, luego divide los gradientes por el mismo factor antes del paso del optimizer. Esto desplaza los gradientes al rango representable.

bf16 (brain float) tiene el mismo rango exponencial que fp32 (1e-38 a 3e38) pero solo 7 bits de mantissa. Sin loss scaling necesario. Ligeramente menos preciso pero sin underflow. El hardware moderno (A100+, TPU v3+) soporta bf16 nativamente, que es por lo que bf16 se ha convertido en default para nuevas ejecuciones de entrenamiento.

Árbol de profundidad. - L1: fp16 vs bf16 — ¿cuándo difieren? (fp16 necesita loss scaling; bf16 no; fp16 tiene mayor precisión en el rango representable; bf16 tiene rango más amplio) - L2: ¿Cómo funciona el loss scaling dinámico? (empieza alto; reduce a la mitad en NaN; duplica tras N pasos sin NaN) - L3: ¿Por qué los master weights se mantienen en fp32? (las actualizaciones de pesos w -= lr * g pueden ser mucho más pequeñas que w; fp16 las perdería en el redondeo)

Pit-of-failure. "fp16 es más rápido". ¿Por qué entrenar en fp16 a veces diverge? — silencio.

→ Fase 26.


Q17 — Explica LoRA.

Respuesta modelo.

LoRA (Hu et al. 2021) reemplaza una matriz de pesos congelada W (shape d × k) con W + B A donde A es r × k, B es d × r, y r << min(d, k) (típico r = 8 o 16). Solo A y B se entrenan; W permanece congelado. El conteo de parámetros cae de d k a r (d + k) — una reducción 30-100x.

La hipótesis (y el resultado empírico del paper): la actualización a W durante el ajuste fino tiene rank intrínseco bajo, así que una descomposición de rank-r es suficiente. A se inicializa Gaussiana, B se inicializa a cero — así que en el paso 0, la capa LoRA es la identidad (B A = 0) y el comportamiento del modelo no cambia.

En inferencia, puedes o bien mantener B A separado (forward = W x + B A x) o fusionar: W' = W + B A, sin coste extra. Para serving multi-adapter (muchos ajustes finos del mismo base), los mantienes separados y los intercambias en runtime.

Árbol de profundidad. - L1: ¿Por qué inicializar B = 0? (para que el modelo arranque desde el comportamiento pre-entrenado; de otra forma init aleatorio destruiría el prior) - L2: ¿Cómo combina QLoRA pesos base 4-bit con adaptadores LoRA? (cuantiza W a NF4; mantén A, B en bf16; los gradientes fluyen a través del W decuantizado pero solo A, B se actualizan) - L3: ¿Cuál es el hiperparámetro "alpha" en LoRA? (factor de reescalado; la actualización efectiva es (alpha / r) * B A x; te permite desacoplar el LR efectivo de la elección de rank)

Pit-of-failure. "LoRA es ajuste fino eficiente en parámetros". ¿Cuán eficiente? ¿Por qué funciona? — silencio.

→ Fase 28, drill 05.


Q18 — Explícame top-p (nucleus) sampling.

Respuesta modelo.

Dados los logits z de un modelo de lenguaje: computa probabilidades p = softmax(z). Ordena p descendentemente. Encuentra el prefijo más pequeño cuya suma acumulada exceda top_p (e.g. 0.9). Trunca a ese prefijo, renormaliza, muestrea.

¿Por qué top-p en vez de top-k? Top-k corta en un conteo fijo, que es demasiado restrictivo para contextos de alta entropía (muchos tokens siguientes plausibles) y demasiado laxo para contextos de baja entropía (un token siguiente obvio). Top-p adapta — agranda el set de candidatos cuando la distribución es plana y lo encoge cuando está concentrada.

En la práctica combinas top-p con temperatura (z / T antes del softmax). T < 1 agudiza; T > 1 aplana. Configuraciones comunes: T = 0.7, top_p = 0.9 para chat de asistente; T = 1.0, top_p = 1.0 para output creativo diverso; greedy (T → 0 o top_k = 1) para eval determinista.

Árbol de profundidad. - L1: ¿Qué es min-p sampling? (filtra tokens con p < min_p * max(p); umbral relativo al pico; funciona bien a baja T) - L2: ¿Cómo difiere typical sampling? (filtra por entropía absoluta de la condicional; Meister 2022) - L3: ¿Cómo implementarías decoding restringido para schemas JSON? (sampling restringido por gramática — enmascara logits de tokens que violarían la gramática; outlines / jsonformer / xgrammar)

Pit-of-failure. Confundir top-p con top-k. Señales: nunca afinaste sampling para un producto real.

→ Fase 21, drill 07.


Q19 — ¿Qué es RAG y dónde se rompe?

Respuesta modelo.

Retrieval-Augmented Generation: en tiempo de consulta, hace embedding de la consulta del usuario, recupera los top-k pasajes de un vector store, los concatena en el prompt, y deja que el LLM responda con ese contexto. El LLM hace el razonamiento; el retriever hace la memoria.

El pipeline estándar: chunk de documentos (a menudo 500-1000 tokens con overlap), embedding con un encoder de oraciones (BGE, E5, OpenAI ada), índice con FAISS / Qdrant / pgvector. Consulta: embed, búsqueda ANN, rerank opcional con un cross-encoder, mete en el prompt.

Modos de ruptura. (1) Chunking pierde contexto cross-chunk (una frase en un borde de chunk). (2) Single-query retrieval falla para preguntas multi-hop ("¿quién sucedió al predecesor de X?"). (3) Citaciones alucinadas — el modelo fabrica un pasaje que no fue recuperado. (4) Mismatch retriever-generator — el retriever usa similitud semántica, el LLM usa matching literal de texto para evidencia. Mitigaciones: retrieval jerárquico, reescritura de consulta, sparse+dense híbrido, reranker, restricciones de citación-con-span.

Árbol de profundidad. - L1: ¿Qué es retrieval híbrido y por qué ayuda? (BM25 + dense; BM25 captura términos / IDs exactos; dense captura semántica) - L2: ¿Cómo evalúas un sistema RAG end-to-end? (retrieval@k vs faithfulness de generación — métricas separadas; RAGAS, TruLens; precision/recall + groundedness) - L3: ¿Cómo difiere graph RAG (Microsoft 2024)? (construye un grafo de conocimiento desde el corpus; recupera subgrafos; maneja multi-hop mejor)

Pit-of-failure. "RAG funciona genial". ¿Cuándo no? — silencio.

→ Fase 29.


Q20 — ¿Cómo afecta el tamaño del vocabulario del tokenizer al diseño del modelo?

Respuesta modelo.

Vocab más grande → más parámetros en el embedding y la proyección de output (ambos son vocab_size × d_model). Para el vocab 128k de Llama 3 y d_model = 4096, eso son 524M parámetros por matriz — 1B total, comparable a un modelo 1B entero.

Vocab más grande → secuencias más cortas para el mismo texto → menos cómputo de attention por oración (O(n^2) ahorrado). Para dominios multilingües o cargados de código, esto importa: el vocab 32k de Llama 2 tokeniza coreano a 3-4 tokens/char; el vocab 128k de Llama 3 corta eso aproximadamente a la mitad.

Tradeoffs. Vocab más grande: más tokens raros que pueden estar sub-entrenados (embeddings pobres para tokens que aparecen una vez); huella mayor de init de embeddings; cómputo de softmax más grande en la capa de output (mitigado por embeddings input/output atados o softmax factorizado). Vocab más pequeño: más cómputo de attention por oración; embeddings mejor entrenados; peor para no-inglés.

Árbol de profundidad. - L1: ¿Qué es tied embedding? (matriz de embedding de input = matriz de proyección de output transpuesta; reduce a la mitad el coste de parámetros) - L2: ¿Qué es adaptive softmax / hierarchical softmax? (agrupa tokens por frecuencia; tokens raros obtienen representaciones más baratas; de Grave 2017) - L3: ¿Cómo medirías "eficiencia del tokenizer" para un dominio objetivo? (tokens-por-byte en un corpus held-out; bits-por-byte del LM dividido por la compresión del tokenizer)

Pit-of-failure. "Vocab más grande es mejor". ¿Más grande por qué factor y a qué coste? — silencio.

→ Fase 11.


Q21 — Explica gradient checkpointing.

Respuesta modelo.

Durante backprop, necesitas las activaciones de input de cada capa para computar el gradiente del peso. Naivamente, almacenas todas las activaciones del forward pass — eso escala como O(num_layers × batch × seq × d), que domina memoria en contexto largo.

Gradient checkpointing intercambia cómputo por memoria: almacena activaciones solo en un subconjunto de capas ("checkpoints"). En el backward pass, recomputa las activaciones entre checkpoints re-ejecutando el forward de ese segmento. Si haces checkpoint cada sqrt(L) capas, la memoria cae de O(L) a O(sqrt(L)) y el cómputo aumenta ~33%.

PyTorch expone esto como torch.utils.checkpoint.checkpoint. La función envuelve un cómputo forward y lo re-ejecuta en backward. Advertencias: (1) el estado RNG debe preservarse si dropout está en el bloque envuelto; (2) los tensores guardados deben detacharse apropiadamente para evitar bugs de double-backprop; (3) no compone trivialmente con autocast — hay que tener cuidado con mixed precision.

Árbol de profundidad. - L1: ¿Cuál es la frecuencia óptima de checkpointing? (cada sqrt(L) capas minimiza el producto memoria × cómputo) - L2: ¿Cómo difiere la recomputación selectiva en Megatron? (solo recomputa las ops baratas — softmax, dropout — almacena las caras; mejor que uniforme) - L3: ¿Cómo se compara el activation offloading a CPU? (ahorra más memoria pero la transferencia PCIe puede ser cuello de botella; solo vale la pena en contexto muy largo)

Pit-of-failure. "Ahorra memoria". ¿Cómo? ¿A qué coste? — silencio.

→ Drill 03.


Q22 — ¿Qué es in-context learning y por qué es sorprendente?

Respuesta modelo.

In-context learning (ICL): un modelo de lenguaje congelado realiza una tarea nueva al mostrársele ejemplos en su prompt, sin actualizaciones de pesos. GPT-3 (Brown 2020) es la demostración canónica — dale 5 ejemplos de traducción, luego una frase nueva, y traduce.

Por qué sorprendente: el modelo fue entrenado para predecir el siguiente token sobre texto web. Nada en ese objetivo enseña explícitamente "si ves English: foo / Spanish: bar / English: baz / Spanish:, output una traducción al español". Aun así a escala emerge. Esto sugirió que la escala sola produce razonamiento general, lo que arrancó la carrera de scaling 2020-2023.

El mecanismo aún se debate. Hipótesis: (a) ICL es descenso de gradiente en espacio de activaciones — el modelo implementa una optimización interna (Akyürek 2022, Garg 2022, von Oswald 2022); (b) ICL es meta-aprendizaje sobre la distribución de pretraining — patrones comunes en data de entrenamiento (e.g. formatos Q/A) hacen prompts few-shot in-distribution; © ICL es solo pattern matching sofisticado. Lo más probable es que las tres contribuyen.

Árbol de profundidad. - L1: ¿Qué es chain-of-thought prompting? (pedir al modelo que razone paso a paso antes de responder; emergió en Wei 2022; funciona solo a escala) - L2: ¿Cómo se relaciona el mecanismo de "induction heads" (Olsson 2022) con ICL? (circuito específico de attention de 2 capas que hace completado de secuencia; aparece en una transición de fase durante el entrenamiento) - L3: ¿Cómo probarías si un modelo está "realmente aprendiendo" de ejemplos in-context vs pattern matching? (usa ejemplos contrafactuales que violen la distribución de entrenamiento; ver "Counterfactual Reasoning in ICL")

Pit-of-failure. Confundir ICL con ajuste fino. Señales: nunca leíste el paper de GPT-3.


Q23 — ¿Cómo difiere la evaluación entre pretraining, instruction-tuning y chat fine-tuning?

Respuesta modelo.

Pretraining se evalúa con perplejidad en texto web held-out, más benchmarks académicos zero-shot / few-shot (HellaSwag, MMLU, ARC). Estos miden calidad de modelado de lenguaje y capacidades emergentes. Barato, automático, determinista.

Instruction-tuning se evalúa en benchmarks de instruction-following (MT-Bench, AlpacaEval, IFEval). Estos usan o bien (a) LLM-as-judge (GPT-4 o Claude puntúa por pares) o (b) checks de satisfacción de restricciones (IFEval: "¿produjo el modelo exactamente 5 bullets?"). Menos fiable que perplejidad pero más cercano a utilidad user-facing.

Modelos chat / preference-tuned se evalúan con preferencias humanas por pares en un set held-out (Chatbot Arena, evals red-team internos) y crecientemente con evals capability-specific (código: HumanEval, MBPP, LiveCodeBench; matemáticas: GSM8K, MATH; razonamiento: ARC-AGI, GPQA). Para seguridad / alineamiento: tasas red-team de completados dañinos, tasas de rechazo en pedidos benignos.

Árbol de profundidad. - L1: ¿Por qué LLM-as-judge está sesgado? (position bias, verbosity bias, self-preference; mitigado por intercambio de score, rúbricas normalizadas por longitud) - L2: ¿Qué es "Goodhart en evals"? (cuando la eval se vuelve un target de entrenamiento — overfit; e.g. los scores tempranos de MT-Bench inflados por respuestas largas) - L3: ¿Cómo diseñas una eval held-out que sobreviva un año? (privada; rota; cubre capacidad + seguridad + calibración de rechazo; anclada a quejas reales de usuarios)

Pit-of-failure. Citar número de MMLU sin saber qué mide MMLU o cómo se filtra.

→ Fase 20.


Q24 — ¿Qué es constitutional AI?

Respuesta modelo.

Constitutional AI (Bai et al. 2022, Anthropic) es un método para entrenar un asistente inofensivo usando feedback de IA en vez de feedback humano. Dos fases.

SL-CAI: el modelo genera una respuesta a un prompt red-team; luego critica su propia respuesta contra una constitución escrita (e.g. "por favor reescribe esta respuesta para que sea menos dañina"); la respuesta revisada reemplaza la original en SFT. Itera.

RL-CAI: el modelo genera dos respuestas a un prompt; otro modelo (o el mismo) elige la mejor según la constitución. Estas preferencias por pares entrenan un reward model, que luego conduce RLHF (o DPO). El humano se reemplaza por un juez IA anclado a un set escrito de principios.

Por qué importa en Anthropic: escala el entrenamiento de inocuidad sin requerir un gran red-team humano para cada iteración. La constitución es texto auditable. Tradeoff: el juez IA hereda los sesgos de cualquier modelo que se usara; la constitución debe escribirse cuidadosamente; "inofensivo" puede derivar en "evasivo".

Árbol de profundidad. - L1: ¿Cómo difiere RLAIF (Lee 2023) de CAI? (RLAIF es la técnica general — feedback IA en vez de humano; CAI es la receta Anthropic-específica con una constitución escrita) - L2: ¿Cómo es la constitución pública de Anthropic? (set de principios derivados de la Declaración Universal de Derechos Humanos, ToS de Apple e interno de Anthropic; publicado en el apéndice del paper de CAI) - L3: ¿Cuál es la relación entre CAI y "el carácter de Claude"? (la constitución da forma a patrones de rechazo, tono, comportamiento de matización; el refinamiento iterativo de la constitución es parte de cómo Claude evoluciona)

Pit-of-failure. Confundir CAI con RLHF. Señales: crítico para una entrevista de Anthropic.

→ X3 theory/05.


Q25 — ¿Cómo decides entre ajuste fino, RAG y prompt engineering?

Respuesta modelo.

El árbol de decisión. (1) ¿Puede el prompt engineering alcanzar la barra? Prueba primero — coste cero, iteración instantánea. Usa few-shot, output estructurado, chain-of-thought. (2) ¿El problema es de conocimiento (el modelo no sabe los hechos) o comportamiento (el modelo sabe pero responde mal)? Conocimiento → RAG. Comportamiento → ajuste fino. (3) ¿El conocimiento es estático (libro de texto) o dinámico (cambia semanalmente)? Estático → puedes hacer ajuste fino; dinámico → RAG (más barato actualizar un índice que reentrenar).

Coste de ajuste fino: decenas a miles de dólares (LoRA), miles a millones (SFT completo). Tiempo: horas a días. Coste de actualización en data nueva: reentrenar. Coste de inferencia: igual que base. Reproducibilidad: alta (los pesos están versionados).

Coste de RAG: construir el índice es barato; por-consulta es una búsqueda vectorial + prompt más grande (más tokens facturados). Coste de actualización en data nueva: re-embed y upsert (minutos). Coste de inferencia: tokens de prompt mayores. Reproducibilidad: depende de la versión del índice y el determinismo del retrieval.

Árbol de profundidad. - L1: ¿Cuándo se combinan ajuste fino + RAG? (ajuste fino para tono / formato; RAG para hechos; patrón común de producción) - L2: ¿Qué es "long-context" como alternativa? (salta RAG, mete todo en 200k de contexto; funciona para corpus pequeños pero el coste escala linealmente con tokens; calidad puede degradarse con "lost in the middle") - L3: ¿Cómo haces A/B test de ajuste fino vs RAG en producción? (shadow-traffic a los dos pipelines; mide calidad (humano o LLM-juez) y coste; elige por coste-por-unidad-de-calidad; ver Fase 38 / CpQU)

Pit-of-failure. "El ajuste fino siempre es mejor". ¿Cuándo no lo es? — silencio.

→ Fase 29, Fase 38.


Cómo drillear este archivo

  1. Cubre la respuesta modelo. Lee la pregunta. Habla por 3 minutos en voz alta.
  2. Compara con la respuesta modelo. Anota gaps.
  3. Pide a un amigo (o un script) que dispare follow-ups aleatorios del árbol de profundidad.
  4. Re-drillea semanalmente hasta que cada pregunta sea < 90 segundos para la ruta L1, < 3 minutos para L1→L2→L3.

→ Siguiente: 02-systems-design-for-llms.md