---
title: "Self-speculative decoding: el modelo que se adelanta a sí mismo"
url: https://blog.lo0.es/posts/self-speculative-decoding-early-exit/
markdown: https://blog.lo0.es/posts/self-speculative-decoding-early-exit/index.md
lang: es
date: 2026-06-09
lastmod: 2026-06-12
author: "José Manuel Román"
description: "Cómo un modelo pequeño puede hacer de su propio draft saliendo en una capa intermedia (early-exit) y verificarse con el forward completo, con cero memoria extra: LayerSkip, SWIFT, CLaSp y el trade-off honesto frente a un draft dedicado."
tags: ["self-speculative-decoding","layerskip","early-exit","swift","clasp","layer-skip","speculative-decoding","slm","modelos-pequenos","inferencia","fundamentos"]
translations:
  en: https://blog.lo0.es/en/posts/self-speculative-decoding-model-gets-ahead-of-itself/index.md
---

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


> Este post es el complemento directo de [Speculative decoding: el secretario que adelanta](https://blog.lo0.es/posts/speculative-decoding-fundamentos/index.md). 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](https://blog.lo0.es/posts/speculative-decoding-fundamentos/index.md)).

## 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](https://blog.lo0.es/posts/knowledge-distillation-fundamentos/index.md)). 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](https://blog.lo0.es/posts/kv-cache-fundamentos/index.md)).
- **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.

> **Diagrama:** Early-exit draft y forward completo verify con KV compartido — [verlo en la versión HTML](https://blog.lo0.es/posts/self-speculative-decoding-early-exit/)

## 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**.

| Familia | Año / venue | Cómo elige qué saltar | ¿Entrenamiento? | KV extra | Idea distintiva |
|---|---|---|---|---|---|
| **LayerSkip** (Elhoushi et al.) | 2024, arXiv:2404.16710 | Early-exit en capa fija `k`; una sola LM head sirve a todas las salidas | Sí — *layer dropout* + *early-exit loss* en train/fine-tune | 0 | Un único modelo entrenado para hacer draft y verify; reusa cómputo parcial |
| **SWIFT** | ICLR 2025 (OpenReview EKJhH5D5wA) | Selecciona qué capas saltar **on-the-fly**, sin tocar pesos | **No** — plug-and-play sobre el modelo dado | 0 | Self-spec *training-free*: optimiza el conjunto de capas saltadas en caliente |
| **CLaSp** | 2025, arXiv:2505.24196 | *In-context* layer skip dinámico: el patrón de capas saltadas se adapta al contexto | No (dinámico en inferencia) | 0 | El skip no es fijo; cambia según lo que se está generando |
| **ConfLayers** | 2026, arXiv:2604.14612 | Salta capas según **confianza** del estado intermedio (adaptativo por token) | No (criterio de confianza) | 0 | Profundidad variable: tokens fáciles salen antes, difíciles llegan más hondo |
| **Saguaro** | 2025–26 | Formulación **asíncrona**: el draft sigue especulando en paralelo mientras corre la verificación | Depende de la variante | 0 | Solapa draft y verify en el tiempo en lugar de alternarlos |
| **SSD para MoE on-device** | ACM Web Conf. 2026, doi 10.1145/3774904.3792218 | Self-spec aprovechando la *sparsity* del MoE (pocos expertos activos por token) | Variante específica MoE | 0 | El 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](https://blog.lo0.es/posts/speculative-decoding-fundamentos/index.md) 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ón | c | α | tokens/step | speedup | VRAM extra | piezas a mantener |
|---|---|---|---|---|---|---|
| Self-spec early-exit (k=8) | 0.25 | 0.70 | 2.77 | **1.39×** | **0** | **0** |
| Self-spec early-exit (k=4) | 0.125 | 0.65 | 2.50 | **1.67×** | **0** | **0** |
| Draft externo destilado | 0.10 | 0.78 | 3.23 | **2.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](https://blog.lo0.es/posts/roofline-invertido-modelos-pequenos/index.md)). 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](https://blog.lo0.es/posts/arquitecturas-nativas-device-moe-grano-fino/index.md)), 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

- [Speculative decoding: el secretario que adelanta](https://blog.lo0.es/posts/speculative-decoding-fundamentos/index.md) — el complemento directo y prerequisito: draft + verify + rejection sampling, el techo `1/(1-α)` y la fórmula del speedup que aquí reutilizamos tal cual.
- [El roofline invertido en modelos pequeños](https://blog.lo0.es/posts/roofline-invertido-modelos-pequenos/index.md) — por qué el SLM vive en régimen memory-bound, que es justo lo que habilita cualquier forma de speculative.
- [Arquitecturas nativas para device: MoE de grano fino](https://blog.lo0.es/posts/arquitecturas-nativas-device-moe-grano-fino/index.md) — dónde aterriza el self-spec sobre MoE en device, aprovechando la sparsity del router.
- [KV cache: la memoria de trabajo](https://blog.lo0.es/posts/kv-cache-fundamentos/index.md) — el reuso del KV de las capas compartidas entre draft y verify es lo que hace que la memoria extra sea cero; aquí está el mecanismo del cache.
- [Knowledge distillation](https://blog.lo0.es/posts/knowledge-distillation-fundamentos/index.md) — el early-exit loss de LayerSkip es pariente de la destilación: enseña a las capas intermedias a predecir como el modelo completo.
- [Poda de modelos LLM](https://blog.lo0.es/posts/poda-pruning-llm-fundamentos/index.md) — saltar capas es una forma de poda estructurada *en inferencia*; layer-skip y layer-dropping comparten raíz conceptual.
- [MoE inference: el call center con 256 especialistas](https://blog.lo0.es/posts/moe-inference-fundamentos/index.md) — el régimen memory-bound persistente del MoE hace que el self-spec sobre MoE gane incluso a batch medio.
- [Optimizando el decode en vLLM](https://blog.lo0.es/posts/decode-optimizaciones-vllm/index.md) — dónde se configuran en la práctica los métodos speculative en producción.
- [Entornos mixtos NVIDIA + Intel](https://blog.lo0.es/posts/entornos-mixtos-nvidia-intel-servidores-nucs/index.md) — el caso device/edge donde "cero modelo extra" deja de ser una comodidad y pasa a ser la única opción viable.

## Referencias

- Elhoushi, M., et al. *LayerSkip: Enabling Early Exit Inference and Self-Speculative Decoding*. 2024. <https://arxiv.org/abs/2404.16710>
- *SWIFT: On-the-Fly Self-Speculative Decoding for LLM Inference Acceleration*. ICLR 2025. <https://openreview.net/forum?id=EKJhH5D5wA>
- *CLaSp: In-Context Layer Skip for Self-Speculative Decoding*. 2025. <https://arxiv.org/abs/2505.24196>
- *ConfLayers: Confidence-Adaptive Layer Skipping for Self-Speculative Decoding*. 2026. <https://arxiv.org/abs/2604.14612>
- *Self-Speculative Decoding for MoE on Device*. ACM Web Conference 2026. <https://doi.org/10.1145/3774904.3792218>
- Hugging Face blog. *Faster Text Generation with Self-Speculative Decoding*. <https://huggingface.co/blog/layerskip>
- Leviathan, Y., Kalman, M., Matias, Y. *Fast Inference from Transformers via Speculative Decoding*. ICML 2023. <https://arxiv.org/abs/2211.17192>

