Self-speculative decoding: el modelo que se adelanta a sí mismo

Este post es el complemento directo de Speculative decoding: el secretario que adelanta. Allí draft y target son dos modelos distintos; aquí son el mismo modelo a dos profundidades. Léelo primero: damos por sabidos el rejection sampling, el techo 1/(1-α) y la fórmula del speedup, y aquí solo cambiamos qué es el draft.

TL;DR

Speculative decoding clásico exige una pareja: un modelo draft barato propone γ tokens y un target caro los verifica en un único forward pass paralelo. En modelos grandes el draft puede ser un 1 % del target y caber holgado. En modelos pequeños (SLM, 1B–8B) esa receta se rompe por dos lados: un draft que sea 1/10 de un 3B es un 0.3B que apenas acierta (α se desploma), y cargar un segundo modelo —por pequeño que sea— dobla las piezas a mantener y se come VRAM que en una 4090 o en device no sobra. Self-speculative decoding resuelve ambos: el draft es el propio modelo ejecutado de forma superficial. Un modelo de L capas produce tokens borrador saliendo en una capa intermedia k < L (early-exit) o saltando un subconjunto de capas (layer-skip), y luego verifica esos tokens con el forward completo de las L capas. Como draft y verify comparten pesos y comparten el KV cache de las capas comunes, el coste extra de memoria es cero: no hay un segundo modelo, no hay un segundo KV cache, no hay nada nuevo que cargar. El precio es que el draft early-exit es más caro que un draft externo minúsculo (recorre k/L del modelo en vez de un 1 %), así que el coste relativo c sube. El trade-off honesto: con draft dedicado bien entrenado (EAGLE-3) que quepa en memoria, su α suele ser mayor y gana; self-spec gana cuando no hay draft entrenado, no cabe, o estás en device.

La analogía: el ajedrecista que juega a ojo y luego calcula

Un buen jugador de ajedrez hace dos cosas con el mismo cerebro. Primero mira el tablero y, a ojo, en medio segundo, propone una jugada “que pinta bien”: es intuición de patrones, reconocimiento rápido, las capas superficiales del juicio. Después, antes de mover, calcula a fondo: tres jugadas por delante, las respuestas del rival, las líneas tácticas. Ese cálculo profundo confirma la intuición o la corrige.

Lo decisivo es que es la misma persona haciendo de borrador y de revisor. No contrata a un segundo ajedrecista más débil para que adivine la jugada y luego él la valida —eso sería el speculative clásico con draft externo—. Aquí el borrador rápido y la verificación lenta salen del mismo cerebro, recorrido a dos profundidades.

La analogía se sostiene punto por punto:

  • El vistazo a ojo es el forward early-exit: el modelo recorre solo las primeras k capas y emite un token borrador. Rápido, aproximado.
  • El cálculo a fondo es el forward completo de las L capas, que verifica el borrador con rejection sampling exacto.
  • Que sea la misma persona es el reuso de pesos y de KV cache: las k capas superficiales del draft son literalmente las mismas que las k primeras capas del verify; lo ya computado no se recomputa.
  • Que la jugada final sea idéntica a la que el jugador habría elegido calculando siempre a fondo es la garantía de rejection sampling: la calidad del output no se degrada (la prueba está en el post de speculative).

Por qué el draft externo no encaja en modelos pequeños

Repasemos el coste del speculative clásico con dos números. El speedup depende de la tasa de aceptación α (cuánto acierta el draft) y del coste relativo c = T_draft / T_target. Un draft útil necesita α alto y c bajo a la vez. En modelos grandes eso es alcanzable: un draft de 1B para un target de 70B tiene c ≈ 0.015 y, si está bien destilado (EAGLE), α > 0.8. El producto sale rentable.

En un modelo pequeño el equilibrio se rompe:

  1. El draft proporcional es inservible. Si quieres c ≈ 0.1 para un target de 3B, tu draft es un ~0.3B. Un 0.3B genérico tiene una distribución tan distinta del 3B que α cae a la zona 0.3–0.5. Y 1/(1-α) con α = 0.4 es un techo de 1.67 tokens/step: ni con γ infinito sacas más. El premio se evapora.
  2. Cargar un segundo modelo dobla las piezas. Aunque el draft sea pequeño en VRAM, es otro checkpoint que versionar, cuantizar, validar y servir, y tiene su propio KV cache. En una RTX 4090 (24 GB, Ada Lovelace) con un 8B cuantizado y un contexto largo, el KV cache ya aprieta; meter un segundo modelo y su cache puede forzarte a bajar la concurrencia o el contexto máximo. En device (un móvil, un NUC, un edge box) directamente no hay sitio.
  3. No siempre existe un draft entrenado para tu modelo exótico o fine-tuneado. EAGLE necesita entrenar el draft on-policy contra ese target concreto (ver knowledge distillation). Si tu SLM es un fine-tune propio, no hay draft oficial publicado.

Self-speculative ataca los tres a la vez con una idea: no traigas un segundo modelo; usa el primero a media profundidad.

El mecanismo: early-exit como draft, forward completo como verify

Un transformer de L capas, en cada posición, transforma el hidden state capa a capa: h_0 → h_1 → ... → h_L, y la LM head proyecta h_L a logits. La observación que lo habilita todo: h_k para k < L ya es un hidden state razonable. Si lo pasas por la misma LM head (o por una head ligera dedicada), obtienes una distribución de salida “prematura” pero a menudo correcta para los tokens fáciles. Esa es la fuente del borrador.

La iteración de self-speculative tiene la misma estructura que el speculative clásico —draft, verify, accept/reject— pero ambos roles son el mismo modelo:

Paso 1 — Draft superficial. Para producir γ tokens borrador, el modelo recorre solo las primeras k capas (o un subconjunto de capas en el caso layer-skip) y aplica la LM head. Cada token borrador cuesta ≈ k/L de un forward completo. Llamamos c = k/L al coste relativo del draft. Los γ borradores se generan autoregresivamente a este coste reducido.

Paso 2 — Verify completo. El modelo ejecuta un único forward pass de las L capas sobre prompt + x_1...x_γ. Por la atención causal obtiene p(·|prompt, x_<i) para cada posición, exactamente igual que en el speculative clásico.

Paso 3 — Accept/reject. Rejection sampling idéntico al del post anterior: se aceptan tokens de izquierda a derecha, se corrige en la primera divergencia muestreando del residual norm(max(0, p−q)), y si se aceptan los γ se añade el token bonus. La calidad del output es exactamente la del modelo completo.

El truco que hace c aún más barato: reuso de KV cache de capas compartidas

Aquí está la diferencia clave frente a un draft externo. Cuando el modelo hace el draft recorriendo las capas 0..k, calcula y almacena el KV cache de esas k capas para los tokens del prompt y los borradores. Cuando llega el verify completo, las capas 0..k del forward de L capas son bit a bit las mismas operaciones sobre los mismos pesos que ya hizo el draft. No hay que recomputarlas: el verify reusa directamente el KV cache que el draft dejó para las capas 0..k, y solo computa de verdad las capas k..L que faltan.

Eso tiene dos consecuencias:

  • Memoria extra cero. No hay un segundo KV cache. El KV de las capas comunes es uno solo, compartido entre draft y verify. Contrasta con vanilla SD, donde el draft tiene su propio cache completo (ver KV cache).
  • Cómputo parcialmente reusado. El verify solo paga las capas k..L “nuevas” para los tokens que ya pasaron por el draft. El forward completo no es tan caro como sugiere L, porque las primeras k capas vienen del cache.
Un solo modelo de L=32 capas, recorrido a dos profundidades

DRAFT · early-exit en k=8capas 0..8recorrido superficialcoste ≈ k/L = 0.25LM head → borradorx₁ x₂ x₃ x₄ (γ=4)

VERIFY · forward completo L=32capas 0..8(reusadas, nose recomputan)capas 8..32cómputo nuevoLM head → p(·)

KV cache COMPARTIDOcapas 0..8 · un solo cachememoria extra = 0

escribe KV 0..8lee KV 0..8

Rejection sampling (idéntico al speculative clásico)x₁ ✓x₂ ✓x₃ ✓x₄ ✗Output = exactamente el del modelo completo · 0 modelos extra · 0 KV extraEl draft y el verify son el mismo modelo; las capas 0..8 se computan una sola vez.

Las familias (estado 2026)

No hay una sola forma de hacer self-speculative. Difieren en qué capas se saltan y en si hace falta entrenar.

FamiliaAño / venueCómo elige qué saltar¿Entrenamiento?KV extraIdea distintiva
LayerSkip (Elhoushi et al.)2024, arXiv:2404.16710Early-exit en capa fija k; una sola LM head sirve a todas las salidasSí — layer dropout + early-exit loss en train/fine-tune0Un único modelo entrenado para hacer draft y verify; reusa cómputo parcial
SWIFTICLR 2025 (OpenReview EKJhH5D5wA)Selecciona qué capas saltar on-the-fly, sin tocar pesosNo — plug-and-play sobre el modelo dado0Self-spec training-free: optimiza el conjunto de capas saltadas en caliente
CLaSp2025, arXiv:2505.24196In-context layer skip dinámico: el patrón de capas saltadas se adapta al contextoNo (dinámico en inferencia)0El skip no es fijo; cambia según lo que se está generando
ConfLayers2026, arXiv:2604.14612Salta capas según confianza del estado intermedio (adaptativo por token)No (criterio de confianza)0Profundidad variable: tokens fáciles salen antes, difíciles llegan más hondo
Saguaro2025–26Formulación asíncrona: el draft sigue especulando en paralelo mientras corre la verificaciónDepende de la variante0Solapa draft y verify en el tiempo en lugar de alternarlos
SSD para MoE on-deviceACM Web Conf. 2026, doi 10.1145/3774904.3792218Self-spec aprovechando la sparsity del MoE (pocos expertos activos por token)Variante específica MoE0El draft superficial activa aún menos expertos; encaja con MoE en device

Tres lecturas operacionales de la tabla:

  1. El eje que más importa es entrenamiento sí/no. LayerSkip da el mejor α porque el modelo aprende a ser un buen draft superficial (con early-exit loss las capas intermedias se entrenan explícitamente para predecir bien). Pero exige fine-tune. SWIFT, CLaSp y ConfLayers son training-free: peor α, pero se aplican a cualquier modelo ya entrenado sin tocar nada. Para un SLM que no controlas, training-free es lo realista.
  2. El skip adaptativo (CLaSp, ConfLayers) sube α porque ajusta la profundidad del draft al token: gasta poco en lo fácil y más en lo difícil, en vez de un k fijo. A cambio, el c efectivo deja de ser constante.
  3. Saguaro ataca otra cosa: no sube α, solapa el tiempo de draft y verify. Es ortogonal al resto y combinable.

La matemática: mismo marco, distinto c

Reutilizamos el aparato del post de speculative sin cambiar una letra. Con α la tasa de aceptación y γ el número de borradores:

$$E[\text{tokens por step}] = \frac{1 - \alpha^{\gamma+1}}{1 - \alpha}, \qquad \text{Speedup} = \frac{1 - \alpha^{\gamma+1}}{(1 - \alpha)(\gamma c + 1)}$$

Y el techo algorítmico es el mismo: lim_{γ→∞} = 1/(1-α). Lo único que cambia en self-speculative es el valor de c: ya no es el ratio de tamaños de dos modelos, sino c = k/L, la fracción de capas que recorre el draft early-exit.

Ejemplo numérico: self-spec con L=32, salida en k=8

Tomemos un SLM de L = 32 capas que sale en k = 8 para el draft: c = k/L = 8/32 = 0.25. Supongamos α = 0.7 (razonable para early-exit en tokens conversacionales) y γ = 4.

  • Tokens esperados por step: (1 − 0.7⁵) / (1 − 0.7) = (1 − 0.168) / 0.3 = 0.832 / 0.3 = 2.77
  • Speedup: 2.77 / (4 × 0.25 + 1) = 2.77 / 2.0 = 1.39×

El factor del denominador es γc + 1 = 4·0.25 + 1 = 2.0: el draft early-exit, al costar un cuarto del modelo cada token, se come parte del beneficio. Salir más arriba ayuda: con k = 4 (c = 0.125), denominador = 1.5 y speedup = 2.77/1.5 = 1.85× — pero salir más arriba normalmente baja α, así que hay tensión real entre k pequeño (barato) y α alto (acierta).

Comparación honesta con un draft externo

Pongamos al lado un draft externo minúsculo bien destilado: c = 0.1 y α = 0.78 (lo que un EAGLE-style draft puede dar), mismo γ = 4.

  • Tokens/step: (1 − 0.78⁵)/(1 − 0.78) = (1 − 0.289)/0.22 = 0.711/0.22 = 3.23
  • Speedup: 3.23 / (4 × 0.1 + 1) = 3.23 / 1.4 = 2.31×
Configuracióncαtokens/stepspeedupVRAM extrapiezas a mantener
Self-spec early-exit (k=8)0.250.702.771.39×00
Self-spec early-exit (k=4)0.1250.652.501.67×00
Draft externo destilado0.100.783.232.31×sí (+modelo +KV)1 modelo extra

La lectura es exactamente la que cabe esperar y conviene no maquillar: si tienes un draft dedicado, entrenado contra tu target, y cabe en memoria, su α mayor y su c menor le dan más speedup. EAGLE-3 con draft bien entrenado suele ganar en speedup bruto. Self-spec no compite en speedup bruto; compite en coste total. Sus columnas ganadoras son las dos de la derecha: cero VRAM extra y cero piezas que mantener. Self-spec gana cuando:

  • no hay draft entrenado para tu modelo (SLM propio, fine-tune raro),
  • el draft no cabe (4090 ya llena, contexto largo que necesita el KV),
  • estás en device (móvil, NUC, edge), donde un segundo modelo y su KV simplemente no entran.

Es el mismo patrón que con MTP en el post anterior: a veces el mejor draft es el que no tienes que cargar.

Por qué encaja justo con modelos pequeños y device

El régimen donde self-spec brilla es el de baja concurrencia, memory-bandwidth-bound, con presupuesto de memoria escaso — exactamente el de un SLM en una sola GPU o en device (el porqué del régimen está en el roofline invertido). Tres razones:

  1. Cero memoria extra es decisivo donde no sobra. En una RTX 4090 (24 GB, Ada Lovelace) sirviendo un 7B–8B cuantizado con contexto largo, cada GB cuenta. Self-spec no pide ni uno: reusa pesos y KV. Un draft externo, aunque pequeño, te obliga a recortar contexto o concurrencia. En device la diferencia es binaria: con self-spec aceleras; con draft externo no hay sitio y punto.
  2. No hay segundo checkpoint que versionar. Operacionalmente, un SLM en edge desplegado en cientos de cajas se vuelve insostenible si cada una necesita dos modelos sincronizados. Un solo binario que hace draft y verify es muchísimo más simple de mantener.
  3. Encaja con MoE en device. En un MoE de grano fino para device (ver arquitecturas nativas para device), el draft superficial activa aún menos expertos, y el régimen memory-bound persiste incluso a batch medio — justo lo que el trabajo de SSD para MoE on-device (ACM WWW 2026) explota.

El contrapunto, repetido para que no se olvide: en un cluster genérico 4×H100 SXM (320 GB, NVLink, FP8 nativo), donde la memoria no es el cuello de botella, un draft EAGLE-3 dedicado sí cabe y su α mayor le da más speedup. Allí self-spec es plan B: lo usas si el modelo es exótico y no hay draft entrenado, no porque la memoria apriete.

Pitfalls

  • El α depende muchísimo de k. Salir demasiado arriba (k pequeño) abarata el draft pero hunde α; salir demasiado abajo (k cercano a L) sube α pero el draft cuesta casi un forward completo y c → 1, matando el speedup. El óptimo es empírico y específico del modelo. Desconfía de cualquier número de speedup que no diga en qué k se midió.
  • Training-free no es gratis en calidad de draft. SWIFT/CLaSp dan α menores que LayerSkip precisamente porque las capas intermedias del modelo no se entrenaron para ser buenas salidas prematuras. El número que importa es α medido en tu distribución, no el del paper.
  • Sampling temperature y outputs creativos bajan α igual que en el speculative clásico. A T alta, el speedup de self-spec se erosiona más rápido todavía porque parte de un α más bajo.
  • Batch grande lo neutraliza igual que al speculative clásico. En cuanto el decode pasa a compute-bound, los borradores dejan de ser “casi gratis”. Self-spec es para baja concurrencia.

Ver también

Referencias