Curso / fast.ai / Lección 4
● piloto de formato

fast.ai · Practical Deep Learning for Coders · Lección 4

NLP: la lección que el propio curso ya tuvo que reescribir

Esta es la lección más interesante del curso para leer con perspectiva de 2026 — no porque su contenido original esté mal, sino porque quedó tan superado que la página web del curso ya no sigue al libro: usa Hugging Face Transformers en vez del enfoque RNN que enseña el Capítulo 10.

1. Dos lecciones en una: el libro (RNN) y la web (Transformers)

El libro es de 2020. En ese momento, BERT y GPT-2 ya existían, pero fastai todavía enseñaba NLP con su propio enfoque insignia: ULMFiT, basado en RNNs (LSTM), que había sido estado del arte en 2018. Para cuando se grabó la versión 2022 del curso — la que ves en course.fast.ai hoy — los Transformers ya habían desplazado por completo a las RNN en NLP, y el proyecto de la lección cambió para reflejar eso: clasificar similitud entre frases de patentes de EE.UU. usando la librería transformers de Hugging Face en vez de AWD_LSTM.

Como ya hiciste el recorrido completo de Transformers en el curso de HF, esta página se enfoca en lo que el libro enseña (ULMFiT/RNN) — que sigue siendo un capítulo brillante sobre transfer learning en NLP, y vale la pena entender aunque la arquitectura de base haya cambiado — y lo contrasta explícitamente con lo que ya sabés de transformers.

2. Tokenización con reglas, no solo minúsculas

La tokenización de fastai usa spaCy como base pero le agrega una capa de reglas propias diseñada para preservar información en vez de descartarla. En lugar de simplemente poner todo en minúsculas (perdiendo la señal de énfasis o nombres propios), inserta tokens especiales con prefijo xx: xxbos (inicio de documento — le dice al modelo "olvidate del contexto anterior"), xxmaj (la palabra siguiente empezaba con mayúscula), xxup (la palabra entera estaba en mayúsculas), xxunk (palabra fuera del vocabulario), y variantes que comprimen repeticiones de caracteres (xxrep) en vez de gastar un token distinto por cada variante de "!!!!".

La idea de fondo, que sigue siendo relevante hoy: en vez de perder información para simplificar el vocabulario, se traduce el texto a un "lenguaje" auxiliar diseñado para que el modelo aprenda un concepto general (la capitalización) con una matriz de embeddings chica, en vez de necesitar una entrada distinta por cada palabra en cada variante de mayúsculas posible.

🟢 El contraste con lo que ya sabés

En el Capítulo 6 de HF viste BPE byte-level: en vez de reglas explícitas sobre mayúsculas, un tokenizer BPE moderno aprende directamente del corpus qué unidades sub-palabra son frecuentes, sin necesitar tokens especiales xx* diseñados a mano. Es un cambio de filosofía completo: de reglas lingüísticas escritas por humanos a patrones estadísticos aprendidos — el mismo movimiento general que separa todo este capítulo (ULMFiT) de los Transformers.

3. ULMFiT: transfer learning en NLP, en 3 pasos

La idea central del capítulo, y del paper ULMFiT (2018), es que el transfer learning en NLP no es un salto directo como en visión (donde ImageNet → tu dataset funciona en un solo paso). Hacen falta tres etapas:

  1. Language model preentrenado en un corpus genérico grande (Wikipedia, WikiText-103), con la tarea self-supervised de predecir la siguiente palabra — sin necesitar ninguna etiqueta humana, porque la etiqueta ya está "embebida" en el propio texto.
  2. Fine-tuning del language model en el corpus específico del dominio final (reviews de IMDb, incluyendo las que no tienen etiqueta de sentimiento). Este es el paso que el libro insiste en que la gente se salta y no debería: Wikipedia tiene un registro completamente distinto al de reviews de cine informales con nombres de actores. Saltarse este paso intermedio empeora significativamente los resultados, según el propio paper.
  3. Fine-tuning del clasificador, reusando el encoder del language model ya afinado (sin su capa final de predecir la próxima palabra) como cuerpo, con una cabeza nueva para la tarea final.
dls_lm = DataBlock(blocks=TextBlock.from_folder(path, is_lm=True), ...)
learn = language_model_learner(dls_lm, AWD_LSTM, drop_mult=0.3,
                                metrics=[accuracy, Perplexity()]).to_fp16()
learn.fit_one_cycle(1, 2e-2)
learn.unfreeze(); learn.fit_one_cycle(10, 2e-3)
learn.save_encoder('finetuned')

dls_clas = DataBlock(blocks=(TextBlock.from_folder(path, vocab=dls_lm.vocab), CategoryBlock), ...)
learn = text_classifier_learner(dls_clas, AWD_LSTM, drop_mult=0.5, metrics=accuracy).to_fp16()
learn = learn.load_encoder('finetuned')

Notá que el vocab del language model se pasa explícitamente al DataBlock del clasificador — imprescindible para que los embeddings ya afinados sigan correspondiendo a los mismos índices. Resultado del paper: 94.3% de accuracy en IMDb (95.1% con modelo bidireccional), estado del arte en 2018.

El backbone es AWD-LSTM (ASGD Weight-Dropped LSTM): una LSTM estándar con varias técnicas de regularización superpuestas (dropout en distintos puntos — embeddings, pesos recurrentes, capas ocultas — más una variante de optimización promediada) para evitar el sobreajuste típico de RNNs sobre texto.

4. Discriminative learning rates y gradual unfreezing

Al afinar el clasificador, fastai recomienda algo distinto a lo que hiciste en visión: no descongelar todo el modelo de una vez. La receta:

  1. Entrenar 1 época con solo la cabeza nueva descongelada.
  2. learn.freeze_to(-2): descongelar los últimos 2 grupos de parámetros, con discriminative learning rates — un rango de LR donde las capas más profundas/tempranas reciben un learning rate más bajo y las capas finales uno más alto, porque las capas tempranas capturan features más generales que conviene perturbar menos.
  3. freeze_to(-3): un grupo más, LR aún más bajo.
  4. learn.unfreeze(): finalmente todo el modelo, con LR mínimo.

Este descongelamiento gradual, capa por capa, es lo que el paper ULMFiT llama gradual unfreezing, y el libro es explícito en que para NLP hace una diferencia real frente a descongelar todo de una — a diferencia de visión, donde fine_tune descongela todo después de la primera época sin mayor drama.

5. Por qué ULMFiT importa aunque ya no se use

Nadie entrena un AWD-LSTM en 2026 para un clasificador de texto nuevo — un modelo pretrained tipo BERT o un LLM moderno con unas pocas capas de clasificación (o directamente pedido por prompt) le gana por goleada. Pero la estructura de tres pasos que introdujo ULMFiT — preentrenar en genérico, adaptar al dominio, afinar en la tarea — sigue siendo exactamente el patrón que usás hoy con LLMs, solo que con nombres distintos:

🔧 Es el mismo patrón que ya corre en tus proyectos

Preentrenar en Wikipedia → afinar en el dominio (reviews de IMDb) → afinar en la tarea final (clasificación) es, estructuralmente, el mismo ciclo CPT + SFT (Continued Pre-Training + Supervised Fine-Tuning) que corre en interpretante-lacaniano: el modelo base Gemma-4 ya viene preentrenado en un corpus genérico; el CPT lo adapta al "dominio" (textos lacanianos/freudianos, el estilo del corpus curado); y el SFT final lo afina a la tarea concreta (responder en el estilo del intérprete). ULMFiT en 2018 y tu pipeline en 2026 resuelven el mismo problema estructural — que un modelo genérico no rinde bien de una en un dominio muy específico sin un paso intermedio de adaptación — con arquitecturas completamente distintas (LSTM vs. transformer) pero la misma lógica de tres etapas.

Y en cuanto a discriminative learning rates y gradual unfreezing: la idea de "las capas tempranas cambian menos, las capas finales cambian más" es precisamente la intuición detrás de por qué LoRA (que viste en el Capítulo 11 de HF) suele aplicarse selectivamente sobre ciertas proyecciones de atención y no sobre el modelo entero — no es una técnica nueva, es la misma pregunta ("¿qué tanto debería moverse cada parte del modelo pretrained?") resuelta con una herramienta distinta.

6. Resumen

  1. Esta lección es un caso real de un curso que se actualizó más rápido que su propio libro: la web ya usa Transformers, el libro sigue enseñando RNN/ULMFiT.
  2. La tokenización de fastai preserva información (mayúsculas, énfasis) con tokens especiales xx* en vez de descartarla — un enfoque basado en reglas, contra el enfoque estadístico de BPE que ya conocés.
  3. ULMFiT formalizó el transfer learning en NLP en tres etapas: LM genérico → LM adaptado al dominio → clasificador — el paso intermedio es el que la mayoría se salta y no debería.
  4. Discriminative learning rates + gradual unfreezing: capas tempranas se mueven poco, capas finales se mueven más — la misma intuición que hoy motiva dónde aplicar LoRA.
  5. La arquitectura (LSTM) es historia; la estructura de tres etapas sigue viva en cualquier pipeline moderno de CPT + SFT.