English · Español
Lab 02 — Walkthrough de Inferencia con Whisper¶
Objetivo: cargar
whisper-tiny.ende OpenAI (39M params) víatransformersde HuggingFace, alimentarlo con 24 clips de audio pre-grabados de formas verbales en inglés (uno por muestra (verb, tense, person) de §A13), e inspeccionar (a) la secuencia de tokens decodificada, (b) los logits por-token, © los tokens de timestamp, (d) el patrón de cross-attention encoder-decoder. Sin entrenamiento. Solo inferencia + introspección.🇪🇸 Esta lab es inspección, no entrenamiento. Cargamos Whisper-tiny pre-entrenado, le damos clips de audio de verbos en distintas conjugaciones, y abrimos la caja: ¿qué tokens emite? ¿qué timestamps marca? ¿a qué frames de audio presta atención cuando genera cada token de texto? Es el punto donde la teoría del frontend log-mel y de cross-attention se vuelve concreta.
Tiempo estimado: 3–4 horas.
Prerequisitos: -
docs/extension-track/X2-multimodal/theory/02-audio-models.mdleído. -huggingface_hub,transformers,librosa(osoundfile) instalados en tu envuv. - Los 24 clips de audio commiteados endocs/extension-track/X2-multimodal/lab/data/audio/. Ver "Datos" debajo para cómo obtener o generar.
Por qué este lab usa transformers (una excepción única)¶
CLAUDE.md §0.4 dice: nada de librería transformers antes de la Fase 24.
X2 es un extension track, no parte del ritual core de 40-fases. Estamos post-Fase-24 en espíritu. Además:
- Este lab es solo-inferencia. No hay mecánica de entrenamiento que revelar.
- Re-implementar el frontend log-mel + conv stem + encoder de 4 capas + decoder de 4 capas + tokenizer BPE de Whisper desde cero es un proyecto de ~3 semanas que añade cero insight conceptual más allá de lo que
theory/02-audio-models.mdya deriva. - El objetivo del lab es introspección de un checkpoint pre-entrenado, lo que requiere cargar ese checkpoint, lo que requiere
transformers(o replicar su código de carga de checkpoints, que es el mismo compromiso).
La excepción es local a este lab. El lab 00 y el lab 01 se quedan en NumPy solo.
Datos¶
Necesitamos 24 clips de audio pre-grabados. Uno por muestra (verb, tense, person) para 8 verbos elegidos de §A13 (un subset; los 300 completos serían excesivos).
Subset de verbos (24 clips = 8 verbos × 3 formas cada uno, mezclando tiempos/personas)¶
Un conjunto representativo cubriendo los 5 tiempos y las 3 personas:
| Clip # | Frase | Verbo | Tiempo | Persona |
|---|---|---|---|---|
| 01 | "I work" | work | present_simple | 1sg |
| 02 | "you worked" | work | past_simple | 2sg |
| 03 | "he works" | work | present_simple | 3sg |
| 04 | "I will play" | play | future | 1sg |
| 05 | "you played" | play | past_simple | 2sg |
| 06 | "she has played" | play | past_participle | 3sg |
| 07 | "to walk" | walk | infinitive | - |
| 08 | "he walks" | walk | present_simple | 3sg |
| 09 | "I talked" | talk | past_simple | 1sg |
| 10 | "you will talk" | talk | future | 2sg |
| 11 | "she listens" | listen | present_simple | 3sg |
| 12 | "I have listened" | listen | past_participle | 1sg |
| 13 | "you watch" | watch | present_simple | 2sg |
| 14 | "he watched" | watch | past_simple | 3sg |
| 15 | "I am" | be | present_simple | 1sg |
| 16 | "you were" | be | past_simple | 2sg |
| 17 | "she has been" | be | past_participle | 3sg |
| 18 | "I will be" | be | future | 1sg |
| 19 | "I go" | go | present_simple | 1sg |
| 20 | "you went" | go | past_simple | 2sg |
| 21 | "he has gone" | go | past_participle | 3sg |
| 22 | "to eat" | eat | infinitive | - |
| 23 | "I ate" | eat | past_simple | 1sg |
| 24 | "she will eat" | eat | future | 3sg |
Cómo obtener los clips¶
Dos opciones:
Opción A (preferida, determinista): generar desde text-to-speech.
- Usa pyttsx3 (offline, sin red) o espeak-ng desde CLI.
- Una voz, pitch/rate fijos, WAV mono 16 kHz.
- Guarda como data/audio/clip_<NN>.wav donde NN es el número de clip.
- Commitea un script data/audio/generate.py que produce los 24 clips deterministamente desde la tabla de arriba.
Opción B (más realista): grábate tú.
- Usa arecord o sox o cualquier DAW. 16 kHz, mono, ~2-3 segundos por clip.
- Commitea los archivos WAV. Anota en el README que son grabados por humano y no reproducibles bit-a-bit.
Cualquiera sirve para el lab. La opción A se recomienda por reproducibilidad — el comportamiento de Whisper sobre audio TTS es su propia pregunta interesante (transcribe TTS bien; así es como en parte fue entrenado).
Lo que produces¶
Un directorio experiments/X2-multimodal/lab-02-whisper-inference/ que contiene:
BLUEPRINT.mdtranscribe.py— carga Whisper-tiny.en, transcribe los 24 clips, guarda salidas.inspect_tokens.py— para cada clip, vuelca los tokens BPE + sus probabilidades + sus timestamps.inspect_cross_attention.py— para cada clip, extrae el patrón de cross-attention del decoder.plot_cross_attention.py— visualiza la cross-attention como un heatmap (pasos del decoder × posiciones del encoder).transcriptions.json—{clip_id: {expected, predicted, wer, tokens, token_probs, timestamps}}.manifest.json.README.md.cross_attention_<NN>.png— un heatmap por clip.
Recap rápido de arquitectura (lee theory/02 primero)¶
audio waveform (T_audio at 16 kHz)
↓ log-mel (80 mel × 3000 frames; padded for < 30s)
↓ Conv1D × 2 (stride 1 then stride 2) → (1500 frames, d_model=384)
↓ + sinusoidal positional embedding
↓ encoder: 4 transformer blocks (no causal mask)
↓ encoder_output: (1500, 384)
│
↓ cross-attention key/value
↓
[<|startoftranscript|> <|en|> <|transcribe|>] (or +timestamp tokens)
↓ decoder: 4 transformer blocks (causal self-attn + cross-attn to encoder)
↓ next-token logits (vocab_size = 51865)
↓ greedy / beam decode
↓ "I work" (with optional timestamp tokens interspersed)
Vas a hurgar en: - La secuencia de tokens de salida (salida del decoder). - La distribución de probabilidad en cada paso decodificado (introspección de la incertidumbre del decoder). - Los pesos de cross-attention en cada capa del decoder (a qué frames de audio miró el decoder cuando generó cada token de texto).
TODOs¶
Bloque A — BLUEPRINT¶
- Sketch de cómo vas a cargar Whisper, obtener los hidden states del encoder, obtener la cross-attention del decoder, plotear. Referencia la API de
transformers:WhisperProcessor,WhisperForConditionalGeneration,model.generate(..., output_attentions=True, return_dict_in_generate=True). - Lista la config real del modelo para verificar (vocab_size, d_model, n_layers).
Bloque B — transcribir¶
En transcribe.py:
- Carga
openai/whisper-tiny.eny suWhisperProcessor. - Para cada WAV en
data/audio/: - Carga vía
librosa.load(path, sr=16000). - Pasa por
processorpara obtenerinput_features(el log-mel). - Verifica
input_features.shape == (1, 80, 3000). - Llama a
model.generate(input_features, return_timestamps=True, return_dict_in_generate=True, output_scores=True, output_attentions=True). - Decodifica los IDs generados con
processor.batch_decode(..., skip_special_tokens=False). - Guarda la transcripción esperada vs predicha por clip.
- Computa word error rate (WER) por clip. (Para 24 clips simples, el WER debería ser cercano a 0% — Whisper es muy bueno con habla limpia. Cualquier error es por sí mismo un hallazgo interesante.)
Bloque C — introspección de tokens¶
En inspect_tokens.py:
- Para cada clip, recorre la secuencia de tokens generada paso a paso.
- En cada paso, loguea:
- El ID del token y su texto decodificado.
- Las top-5 alternativas + sus probabilidades softmax (desde
outputs.scores). - Si este token es un token de timestamp (ID de token en el rango
<|N.NN|>). - Hallazgos a buscar:
- ¿Los tokens de timestamp están aproximadamente donde ocurrió el habla? (Para "I work" el primer token de texto debería seguir a un
<|0.00|>y terminar con un<|1.5|>o así.) - En pasado vs presente: ¿cae la confianza de Whisper en el token de forma verbal (p. ej. "worked" vs "works")? ¿Son las alternativas semánticamente similares?
- En el prefix de tarea
<|en|> <|transcribe|>: ¿son estos de muy alta confianza? (deberían serlo — el modelo ha sido entrenado con estos tokens millones de veces.)
Bloque D — extracción de cross-attention¶
En inspect_cross_attention.py:
- Para cada clip, extrae la cross-attention del decoder desde
outputs.cross_attentions. - Forma por paso de generación:
(n_layers, batch, n_heads, query_len, key_len) = (4, 1, 6, 1, 1500). - Promedia sobre heads (o escoge un único head — el head 4 a menudo es el más interpretable para Whisper-tiny; este es un hallazgo empírico conocido).
- Ahora tienes, para cada token de texto decodificado, una distribución sobre las 1500 posiciones del encoder.
Bloque E — plotear¶
En plot_cross_attention.py:
- Para cada clip, plotea un heatmap: filas = tokens de texto decodificados (p. ej.
"I", " work"), cols = posiciones del encoder 0..1499. Color = peso de cross-attention. - Anota las etiquetas de fila con el texto decodificado.
- El patrón esperado (comportamiento sello de Whisper): alineamiento monotónico, cuasi-diagonal. La cross-attention "escanea" de izquierda a derecha a través del audio conforme se genera texto. Esta es la base de la predicción de timestamp de Whisper.
- Guarda como
cross_attention_<NN>.png.
Bloque F — análisis¶
En README.md:
- ¿Se transcribieron correctamente los 24 clips (WER ≈ 0)?
- ¿Qué clips tuvieron la confianza más baja del decoder en el token verbal? ¿Cuáles eran las top-5 alternativas en ese paso?
- ¿Fueron precisos los timestamps? Compara contra la duración real del clip.
- ¿Muestra la cross-attention alineamiento monotónico? Escoge el ejemplo más limpio y el más sucio para discutir.
- Conecta con el tutor de gramática: si quisieras marcar errores de pronunciación (p. ej. el usuario dice "he work" en vez de "he works"), ¿cómo usarías las probabilidades por-token de Whisper? (Pista: mira la probabilidad de
worksvsworken la posición del token verbal cuando el audio es "he work".)
Bloque G — objetivos stretch¶
- Test adversarial. Graba 5 clips con errores de gramática deliberados ("he work", "you was", "I has"). ¿Whisper los transcribe como se dijeron (preservando el error), o los "corrige" a inglés gramatical? Esta es una propiedad conocida de los modelos grandes de habla: a menudo "arreglan" pequeños errores de gramática silenciosamente. Reporta lo que encuentres.
- Especialización de heads de cross-attention. Para un clip, plotea cada uno de los 6 heads de atención por separado. ¿Hay heads especializados (p. ej. uno para detección de frontera, uno para duración de vocal)? Esto es exploratorio y los hallazgos varían.
- Comparación greedy vs beam decode. Genera el mismo clip con
num_beams=1vsnum_beams=5. ¿Son las salidas idénticas, o beam search encuentra una transcripción diferente?
Criterios de aceptación¶
BLUEPRINT.mdaprobado.- Los 24 clips transcritos; WER reportado por clip.
- Probabilidades por-token volcadas para al menos 5 clips representativos.
- Heatmaps de cross-attention commiteados para los 24 clips.
- La discusión en
README.mdincluye el hallazgo de alineamiento monotónico y al menos una observación sorprendente o inesperada. manifest.jsonincluye hash del checkpoint de Whisper, versión detransformers, versión delibrosa, seed (si es relevante para cualquier decode estocástico), wall-clock de la corrida completa de inferencia.
Lo que este lab intencionadamente NO es¶
- No es entrenamiento de Whisper. No estamos re-entrenando. El modelo se usa tal cual.
- No es una comparación de Whisper con otro ASR. Nada de wav2vec, nada de Conformer-RNN-T. Un modelo, inspección profunda.
- No es streaming. Whisper es batch. Los 24 clips son < 30 s.
- No es multilingüe.
whisper-tiny.enes solo-inglés. Elwhisper-tinymultilingüe (74 M, sin.en) tiene un vocabulario y comportamiento diferentes.
Lo que habrás aprendido¶
- El frontend log-mel es concreto: un clip de 30 s → matriz log-mel
(80, 3000). Elprocessorhace esto por ti, pero ahora sabes qué hay eninput_features. - La cross-attention es interpretable en Whisper. El patrón "mira el audio para el siguiente token de texto" del decoder es visible y aproximadamente monotónico. Esta es la base de la lógica de timestamps de Whisper.
- Un modelo de 39 M params es suficiente para habla limpia en un idioma conocido. La mayoría de tareas de "transcripción" no necesitan escala GPT; necesitan 39 M entrenados sobre suficiente audio.
- El modelo tiene priors de language-model integrados. A veces "arreglará" errores de gramática silenciosamente. Esto es genial para ASR-como-producto, malo para tutor-de-gramática-como-producto. El tutor de gramática necesita un modelo que transcriba exactamente lo que se dijo, no una versión suavizada.
Ese último punto es el hallazgo relevante-para-entrevista: cuando elijas un ASR para un tutor de gramática, específicamente quieres un modelo con menos prior de language-model que Whisper — quizá wav2vec2 fine-tuneado con pérdida CTC, que no tiene el bias autoregresivo de language-model. El modelo correcto depende de si quieres una transcripción fluida o una literal.
Cross-references¶
theory/02-audio-models.md— la derivación log-mel y la arquitectura de Whisper.theory/03-fusion-strategies.md§"unified-token" — nota que Whisper no es unified-token; es un encoder de audio dedicado + decoder de texto. La capacidad de audio de GPT-4o es unified-token.docs/phase-15-attention/theory/03-multi-head.md— atención multi-head. La cross-attention de Whisper es la variante "el encoder son keys/values, el decoder son queries" que discutimos ahí.HIRING_PATH.md— línea "audio gap" — cerrado al completar este lab + la teoría.