Phase 10 - Lesson 16
Atención Diferencial (V2)
This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.
La atención softmax distribuye una pequeña cantidad de probabilidad sobre cada token que no coincide. En 100k tokens, ese ruido se acumula y ahoga la señal. El Differential Transformer (Ye et al., ICLR 2025) soluciona esto computando la atención como la diferencia entre dos softmaxes, restando el piso de ruido compartido. DIFF V2 (Microsoft, enero de 2026) es la reescritura para el stack de producción: iguala la latencia de decodificación al Transformer de línea de base (baseline), no requiere kernels personalizados y es compatible con FlashAttention. Esta lección aborda la transición de V1 a V2 de extremo a extremo, con una implementación simplificada (toy) funcional de la operación de diferencia que puedes ejecutar en Python stdlib.
Tipo: Build Lenguajes: Python (stdlib) Prerrequisitos: Phase 7 · 02 (autoatención), Phase 7 · 15 (variantes de atención), Phase 10 · 14 (recorrido de la arquitectura) Tiempo: ~60 minutos
Objetivos de Aprendizaje
- Explicar con precisión por qué la atención softmax tiene un piso de ruido y por qué este crece con la longitud del contexto.
- Derivar la fórmula de atención diferencial y explicar por qué la resta cancela el componente de ruido compartido al tiempo que preserva la señal.
- Analizar la diferencia entre V1 y V2: qué se volvió más rápido, qué se simplificó, qué se volvió más estable y por qué cada cambio era necesario para el preentrenamiento en producción.
- Implementar la atención diferencial desde cero en Python puro y verificar empíricamente la propiedad de cancelación de ruido en una consulta sintética de señal más ruido.
O Problema
La atención softmax estándar tiene una propiedad matemática que se convierte en un dolor de cabeza operativo a gran escala. Para una consulta q, los pesos de atención son softmax(qK^T / sqrt(d)). Softmax nunca puede producir ceros exactos; cada token que no coincide recibe cierta masa positiva. Esa masa residual es ruido y escala con la longitud del contexto. En 128k tokens, incluso si cada token que no coincide obtiene solo el 0.001% de la probabilidad, 127,999 de ellos combinados contribuyen con aproximadamente el 12% del total. El modelo debe aprender a evadir un piso de ruido que crece con el contexto.
Empiricamente, esto se manifiesta como interferencia en las cabezas de atención: citas alucinadas en RAG de contexto largo, fallos de "perdido en el medio" (lost-in-the-middle) en tareas de recuperación de 100k tokens y una degradación sutil de la precisión en benchmarks de aguja en el pajar (needle-in-a-haystack) más allá de 32k. El artículo de Differential Transformer (arXiv:2410.05258, ICLR 2025) mediu la brecha: los DIFF Transformers lograron una menor perplejidad, una mayor precisión en contextos largos y menos alucinaciones que las líneas de base del mismo tamaño. (Wait: "mediu" is Portuguese, let's fix it to "midió" in Spanish). Let's check: yes, it should be "midió").
DIFF V1 tenía tres problemas que lo mantuvieron fuera de los pipelines de preentrenamiento de frontera. Su caché de valores (value cache) tenía que cargarse dos veces por paso de decodificación, requería kernels CUDA personalizados que rompían la compatibilidad con FlashAttention y su RMSNorm por cabeza desestabilizaba el entrenamiento a largo plazo a escalas de más de 70B. DIFF V2 (blog unilm de Microsoft, 20 de enero de 2026) solucionó los tres. Esta lección recorre ambas versiones, construye el operador de diferencia y evalúa la cancelación de ruido en una consulta simplificada (toy).
El Concepto
El piso de ruido de softmax
Para una consulta q y claves K = [k_1, ..., k_N], los pesos de atención son:
w_i = exp(q . k_i / sqrt(d)) / sum_j exp(q . k_j / sqrt(d))
Ningún w_i es jamás cero. Si k_i es completamente ajeno a q, la puntuación q . k_i no es 0; fluctúa alrededor de cero con una varianza de ||q||^2 / d. Después de la normalización por softmax, cada token ajeno sigue contribuyendo con O(1/N) a la suma ponderada. La contribución total de los tokens ajenos es O((N-1)/N) = O(1), lo cual no es una cantidad pequeña.
Lo que el modelo quiere es algo similar a un top-k estricto (hard top-k): peso alto en los tokens coincidentes y peso casi nulo en todos los demás lugares. Softmax es demasiado suave para hacer eso directamente.
La idea diferencial
Divida las proyecciones Q y K de cada cabeza en dos: Q = (Q_1, Q_2) and K = (K_1, K_2). Compute dos mapas de atención:
A_1 = softmax(Q_1 K_1^T / sqrt(d))
A_2 = softmax(Q_2 K_2^T / sqrt(d))
Salida:
DiffAttn = (A_1 - lambda * A_2) V
La resta cancela cualquier distribución de ruido que compartan los dos mapas. Si ambos mapas tienen un peso aproximadamente uniforme en los 127k tokens ajenos (lo cual sucederá en la inicialización aleatoria), estos se cancelan. La señal (el peso concentrado en los pocos tokens realmente relevantes) solo se cancela si aparece en ambos mapas con la misma magnitud, lo cual no sucederá una vez que el modelo se entrene.
lambda es un escalar aprendible por cabeza, parametrizado como lambda = exp(lambda_q1 dot lambda_k1) - exp(lambda_q2 dot lambda_k2) + lambda_init. Puede ser negativo. lambda_init se inicializa por defecto en un número positivo pequeño como 0.8.
Por qué esto se asemeja a la cancelación de ruido dirigida
Pense en dos micrófonos ruidosos que graban la misma voz. Ambos captan al hablante más el ruido de fondo correlacionado. Reste uno del otro y el ruido compartido desaparecerá. La voz sobrevive porque las dos señales difieren en fase o amplitud lo suficiente como para evitar la cancelación total. El lambda por cabeza aprende exactamente este equilibrio. (Wait: "Pense" is Portuguese/typo, should be "Piense" in Spanish).
V1 vs V2: la diferencia
V1 mantuvo la cantidad de parámetros igual a la del Transformer de línea de base. Para obtener dos consultas por cabeza, redujo a la mitad la dimensión de la cabeza. Eso costó expresividad de la cabeza y, lo que es peor, redujo a la mitad el caché de valores (value cache) por cabeza. La decodificación tenía que cargar el caché de valores dos veces por paso (una vez por cada rama de softmax). Resultado: decodificación más lenta que la línea de base a pesar de tener la misma cantidad de parámetros.
V2 duplica el número de cabezas de consulta (query heads) y mantiene las cabezas KV iguales (tomando parámetros prestados de la proyección ascendente). La dimensión de la cabeza sigue siendo la misma que la de la línea de base. Después de la resta, la dimensión extra se proyecta de nuevo hacia abajo para coincidir con la proyección O_W del Transformer de línea de base. Tres cosas ocurren a la vez:
- La velocidad de decodificación coincide con la línea de base (el caché KV se carga una sola vez).
- FlashAttention se ejecuta sin cambios (sin kernel personalizado).
- La intensidad aritmética en la decodificación aumenta (más cómputo por byte cargado desde HBM).
V2 también elimina la RMSNorm por cabeza que V1 usaba para estabilizar la resta. En escalas de preentrenamiento de la clase de 70B, esa RMSNorm desestabilizaba el entrenamiento tardío. V2 la reemplaza con un esquema de inicialización más simple que mantiene estable el entrenamiento sin el módulo adicional.
Cuándo recurrir a esto
| Carga de trabajo | Beneficio |
|---|---|
| RAG de contexto largo (64k+) | Mapas de atención más limpios, menos citas alucinadas |
| Benchmarks de aguja en el pajar | Incremento sustancial de precisión después de 32k |
| QA de múltiples documentos | Menos interferencia entre documentos |
| Finalización de código en 8k | Marginal, no vale la pena el cambio de arquitectura |
| Chat corto (< 4k) | Esencialmente indistinguible de la línea de base |
El valor crece con la longitud del contexto. En 4k tokens, el piso de ruido es lo suficientemente pequeño como para que la atención estándar sea adecuada. En 128k, te está perjudicando.
Cómo se compara con otras características de 2026
| Característica | ¿Compatible con DIFF V2? |
|---|---|
| GQA | Sí (V2 aumenta las cabezas Q, no las cabezas KV) |
| MLA (DeepSeek) | Sí en principio, no hay artículos publicados que los combinen |
| MoE | Sí (la atención es independiente del bloque MLP) |
| RoPE | Sí (sin cambios) |
| YaRN / escalado de contexto largo | Sí (exactamente donde DIFF ayuda más) |
| FlashAttention | Sí en V2 (era no en V1) |
| Decodificación especulativa | Sí (el cambio de atención es invisible para el bucle de decodificación especulativa) |
Implementación
code/main.py implementa la atención diferencial en Python puro. Una consulta simplificada (toy) con una estructura conocida de señal más ruido te permite medir la relación de cancelación de ruido directamente.
Paso 1: atención softmax estándar
Operaciones de matriz de stdlib: listas de listas, matmul manual, softmax con resta del máximo para estabilidad numérica.
def softmax(row):
m = max(row)
exps = [math.exp(x - m) for x in row]
s = sum(exps)
return [e / s for e in exps]
Paso 2: dividir Q, K en dos mitades
Estilo V1: reduce a la mitad la dimensión de la cabeza. Estilo V2: mantiene la dimensión de la cabeza y duplica el número de cabezas. La implementación simplificada utiliza V1 para mayor claridad pedagógica; la matemática es idéntica, solo difiere la contabilidad de los datos.
Paso 3: dos ramas de softmax + resta
A1 = [softmax([dot(q1, k) / scale for k in K1]) for q1 in Q1]
A2 = [softmax([dot(q2, k) / scale for k in K2]) for q2 in Q2]
diff_weights = [[a1 - lam * a2 for a1, a2 in zip(r1, r2)] for r1, r2 in zip(A1, A2)]
out = [[sum(w * v[j] for w, v in zip(row, V)) for j in range(d_v)] for row in diff_weights]
Nota: los pesos de salida pueden ser negativos. Eso está bien; el caché de valores aún maneja contribuciones con signo. La proyección V posterior absorbe el signo.
Paso 4: medición de la cancelación de ruido
Construya una secuencia sintética de longitud 1024. Coloque el token de señal en una posición conocida, llene el resto con ruido. Compute (a) el peso de atención softmax estándar en la posición de la señal y (b) el peso de atención diferencial. Mida la relación señal-ruido en cada uno. La atención DIFF produce de manera confiable una relación señal-ruido de 3 a 10 veces mayor, dependiendo de cuánto se hayan entrenado las dos ramas para diferir.
Paso 5: contabilidad de parámetros de V1 vs V2
Dada una configuración (hidden=4096, heads=32, d_head=128), imprima:
- Transformer de línea de base: Q, K, V cada uno de tamaño
hidden * hidden, MLP en 4 * hidden. - DIFF V1: Q, K cada uno de tamaño
hidden * hidden, V de tamañohidden * hidden(sin cambios), la dimensión de la cabeza se reduce a la mitad internamente. Agrega parámetroslambdapor cabeza (O(heads * d_head)). - DIFF V2: Q de tamaño
2 * hidden * hidden, K de tamañohidden * hidden, V de tamañohidden * hidden. La dimensión extra se proyecta de nuevo hacia abajo antes de O_W. Agrega los mismos parámetroslambda.
El modelo simplificado mide el costo de parámetros adicionales para V2 (aproximadamente hidden * hidden extra por bloque de atención) y lo imprime.
Úselo
DIFF V2 aún no se distribuye en todos los servidores de inferencia de producción a partir de abril de 2026, pero la integración está en marcha en vLLM y SGLang. Mientras tanto, el patrón aparece en:
- Modelos de producción internos de Microsoft para contexto largo.
- Replicaciones de investigación en varias ejecuciones de entrenamiento de modelos abiertos que apuntan a un contexto de más de 256k.
- Arquitecturas híbridas que combinan atención DIFF con atención de ventana deslizante (sliding-window) en capas alternas.
Cuándo recurrir a esto en 2026:
- Al entrenar un nuevo modelo desde cero que apunte a un contexto efectivo de más de 64k. Agregue la atención diferencial desde el principio; reentrenar más tarde es costoso.
- Al realizar el ajuste fino (fine-tuning) de un modelo de contexto largo donde los fallos de "perdido en el medio" (lost-in-the-middle) dominan su evaluación. Un LoRA en las proyecciones Q puede aproximar la estructura de DIFF.
Cuándo no hacerlo:
- Si está sirviendo un modelo denso preentrenado con un rendimiento de contexto largo estable. El costo del reentrenamiento rara vez se amortiza con los pesos existentes.
- Su contexto siempre está por debajo de 16k. El piso de ruido es insignificante.
Envíe para Producción
Esta lección produce el archivo outputs/skill-diff-attention-integrator.md. Dada la arquitectura de un modelo, la longitud del contexto objetivo, el perfil de alucinación y el presupuesto de entrenamiento, genera un plan de integración para agregar atención diferencial a una nueva ejecución de preentrenamiento o ajuste fino con LoRA.
Ejercicios
Ejecute
code/main.py. Verifique que la relación señal-ruido informada para la atención diferencial sea mayor que la de la atención softmax estándar en la consulta sintética. Varíe la amplitud del ruido y muestre el punto de cruce donde la atención estándar se vuelve inutilizable.Calcule la diferencia en la cantidad de parámetros desde la línea de base hasta DIFF V1 y desde la línea de base hasta DIFF V2 para un modelo de clase 7B (hidden=4096, heads=32, d_head=128, 32 capas). Muestre qué componentes ganaron parámetros y cuáles permanecieron iguales.
Lea la Sección 3 del artículo de DIFF V1 (arXiv:2410.05258) y la Sección 2 del blog de DIFF V2 en Hugging Face. En dos oraciones, explique por qué la RMSNorm por cabeza de V1 era necesaria y por qué V2 pudo eliminarla sin causar divergencia en el entrenamiento.
Implemente una ablación: compute la atención diferencial con
lambda = 0(primera softmax pura) ylambda = 1(resta completa). En la consulta sintética, mida cómo cambia la relación señal-ruido a lo largo del barrido. Identifique ellambdaque maximiza la relación señal-ruido.Extienda el modelo simplificado a GQA + DIFF V2. Elija 8 cabezas KV y 32 cabezas Q. Muestre que el tamaño del caché KV coincide con un modelo GQA de línea de base con la misma configuración (8, 32).
Términos Clave
| Término | Lo que la gente dice | Lo que realmente significa |
|---|---|---|
| Atención diferencial | "Dos softmaxes restadas entre sí" | Divide Q, K en dos mitades, computa dos mapas softmax, resta el segundo (escalado por lambda) del primero y luego multiplica por V |
| Piso de ruido | "La cola no nula de softmax" | El peso O(1/N) que softmax asigna a cada token no relacionado, el cual suma O(1) a lo largo de contextos largos |
| lambda | "La escala de resta" | Escalar aprendible por cabeza parametrizado como exp(lq1.lk1) - exp(lq2.lk2) + lambda_init; puede ser negativo |
| DIFF V1 | "La versión de ICLR 2025" | Differential Transformer original; reduce a la mitad la dimensión de la cabeza para preservar la cantidad de parámetros, requiere un kernel personalizado, decodificación más lenta |
| DIFF V2 | "La solución de enero de 2026" | Duplica las cabezas Q manteniendo las cabezas KV; iguala la velocidad de decodificación de la línea de base y funciona con FlashAttention |
| RMSNorm por cabeza | "El estabilizador de V1" | Normalización adicional que V1 aplicaba después de la diferencia; V2 la eliminó para evitar la inestabilidad en el entrenamiento tardío |
| Relación señal-ruido | "Cuánta atención se desperdicia" | Relación entre el peso en la posición de la señal real y el peso promedio en las posiciones no relacionadas |
| Perdido en el medio | "Modo de fallo de contexto largo" | Fenómeno empírico en el que la precisión de recuperación cae para documentos en medio de un contexto largo; la atención DIFF reduce esto |
| Intensidad aritmética | "FLOPs por byte cargado" | Relación que V2 aumentó en la decodificación al duplicar las consultas por carga de KV; importante para la decodificación limitada por memoria |
Lectura Adicional
- Ye et al. — Differential Transformer (arXiv:2410.05258, ICLR 2025) — el artículo original con la teoría de cancelación de ruido y ablaaciones de contexto largo
- Microsoft unilm — Differential Transformer V2 (Hugging Face blog, January 2026) — la reescritura para el stack de producción, que iguala la decodificación de la línea de base y es compatible con FlashAttention
- Understanding Differential Transformer Unchains Pretrained Self-Attentions (arXiv:2505.16333) — análisis teórico de por qué la resta recupera la estructura de atención preentrenada
- Shared DIFF Transformer (arXiv:2501.17900) — variante de compartición de parámetros
- Vaswani et al. — Attention Is All You Need (arXiv:1706.03762) — el Transformer de línea de base del cual resta DIFF
- Liu et al. — Lost in the Middle (arXiv:2307.03172) — el benchmark de contexto largo al que se dirige la atención DIFF