Saltar a contenido

Modelos de lenguaje con n-gramas: autocompletado y perplejidad

1 El problema: predecir la siguiente palabra

Un modelo de lenguaje asigna probabilidades a secuencias de palabras: tiende a dar más probabilidad a las que se parecen a los patrones observados en su corpus. Suele correlacionar con la fluidez —es lo que hace el autocompletado del móvil cuando, tras “Hola, ¿cómo estás?”, sugiere “tú”— aunque no implica comprender el significado.

Sus aplicaciones van mucho más allá del teclado:

  • Reconocimiento de voz: ante “vi una camioneta”, el modelo confirma que esa frase es mucho más probable que “ojos asombran de un”.
  • Corrección ortográfica: las palabras que el contexto hace improbables son candidatas a error.
  • Comunicación aumentativa: sistemas que predicen palabras a partir de gestos para personas con dificultades motoras.

Este capítulo construye el modelo clásico, por conteo de n-gramas. Décadas después, las redes recurrentes aprenderían la misma tarea con vectores densos (ver modelado del lenguaje con RNN); aquí veremos los cimientos probabilísticos.

2 N-gramas y probabilidades por conteo

Un n-grama es una secuencia ordenada de \(n\) elementos contiguos (normalmente palabras). El orden importa y la contigüidad también: “Estoy feliz” solo es un bigrama del corpus si esas dos palabras aparecen exactamente así, una junto a la otra.

Con la oración “Estoy feliz porque estoy aprendiendo”:

  • Unigramas (\(n=1\)): las cinco palabras individuales, contando cada aparición: [estoy, feliz, porque, estoy, aprendiendo].
  • Bigramas (\(n=2\)): [(estoy, feliz), (feliz, porque), (porque, estoy), (estoy, aprendiendo)].
  • Trigramas (\(n=3\)): [(estoy, feliz, porque), (feliz, porque, estoy), (porque, estoy, aprendiendo)].

Ojo con la distinción: los unigramas son las ocurrencias (con repeticiones); el vocabulario es el conjunto de palabras distintas, \(V = \{\text{estoy}, \text{feliz}, \text{porque}, \text{aprendiendo}\}\).

2.1 Nuestro corpus de trabajo

Para no cambiar de ejemplo en cada sección, trabajaremos con este mini-corpus de tres oraciones (los tokens <START> y <END> se explican más abajo):

<START> el gato duerme <END>
<START> el gato come <END>
<START> el perro duerme <END>

2.2 Estimar probabilidades contando

Un corpus es una colección de texto; denotamos su longitud (en palabras) como \(M\). La probabilidad de un n-grama se estima por su frecuencia relativa.

Unigramas. Nuestro corpus tiene \(M = 9\) palabras: “el” aparece 3 veces, “gato” y “duerme” 2 veces cada una, “come” y “perro” 1 vez cada una:

\[ P(\text{el}) = \frac{3}{9} = \frac{1}{3}, \quad P(\text{gato}) = P(\text{duerme}) = \frac{2}{9}, \quad P(\text{come}) = P(\text{perro}) = \frac{1}{9} \]

(En la oración suelta de arriba, con \(M = 5\): \(P(\text{estoy}) = 2/5\) y \(1/5\) para las demás.)

Bigramas. La probabilidad de \(y\) tras \(x\) es la condicional \(P(y \mid x)\): el número de veces que aparece el par \((x, y)\) dividido por el número de veces que aparece \(x\) como primera palabra del par. En nuestro corpus, “el” aparece 3 veces como historia: 2 seguida de “gato” y 1 de “perro”:

\[ P(\text{gato} \mid \text{el}) = \frac{2}{3}, \qquad P(\text{perro} \mid \text{el}) = \frac{1}{3} \]

Y un aviso de lo que viene: \(P(\text{come} \mid \text{perro}) = 0/1 = 0\), porque esa secuencia no existe en el corpus. Un cero que el suavizado tendrá que corregir.

Trigramas. \(P(w_3 \mid w_1, w_2) = C(w_1, w_2, w_3) / C(w_1, w_2)\): cuántas veces aparece el trío dividido por cuántas aparece su prefijo. Aquí, \(P(\text{duerme} \mid \text{el}, \text{gato}) = 1/2\), porque “el gato” aparece 2 veces y solo 1 seguida de “duerme”.

En general, para un n-grama \(w_1 \dots w_n\) con prefijo \(w_1 \dots w_{n-1}\):

\[ P(w_n \mid w_1 \dots w_{n-1}) = \frac{C(w_1 \dots w_n)}{C(w_1 \dots w_{n-1})} \]

Conviene fijar la correspondencia entre orden y memoria: un modelo de bigramas usa una historia de una palabra; uno de trigramas, de dos; en general, un modelo de \(n\)-gramas condiciona cada palabra a las \(n-1\) anteriores.

3 La regla de la cadena y la aproximación de Markov

¿Y la probabilidad de una oración completa, como “El profesor bebe té”? Por la regla de la cadena de la probabilidad (donde \(P(A \cap B)\) es la probabilidad conjunta de \(A\) y \(B\)):

\[ P(A \cap B) = P(A) \cdot P(B \mid A) \]

y generalizando:

\[ P(w_1 \dots w_m) = P(w_1) \cdot P(w_2 \mid w_1) \cdot P(w_3 \mid w_1, w_2) \cdots P(w_m \mid w_1 \dots w_{m-1}) \]

Cada palabra se condiciona a toda su historia. El problema es la dispersión: una oración larga o sus fragmentos casi nunca aparecen tal cual en el corpus de entrenamiento, así que los conteos son cero y la fórmula no da ninguna estimación.

La salida es la suposición de Markov, ya vista en el capítulo de cadenas de Markov: aproximar la historia completa por una ventana corta. Con bigramas, cada palabra solo mira a la anterior:

\[ P(w_1 \dots w_m) \approx P(w_1) \cdot P(w_2 \mid w_1) \cdot P(w_3 \mid w_2) \cdots P(w_m \mid w_{m-1}) \]

El primer término, \(P(w_1)\), es un unigrama: sin historia previa no hay condicional que estimar. Con trigramas se mirarían las dos anteriores, y así sucesivamente. A diferencia de Naive Bayes —que ignora el orden por completo—, aquí el orden local sí cuenta, aunque sea con memoria corta.

4 Inicio y fin de oración

Hay un cabo suelto: la primera palabra no tiene historia. La solución es añadir tokens especiales de inicio <START> al principio de cada oración: tantos como palabras de contexto exija el modelo.

Modelo Contexto necesario Tokens iniciales
Unigrama 0 palabras anteriores 0
Bigrama 1 palabra anterior 1 <START>
Trigrama 2 palabras anteriores 2 <START>

Con trigramas, “El gato duerme” se representa como <START> <START> El gato duerme <END>.

Para el final se añade un único token <END> por oración, y con él la probabilidad de que la oración termine tras su última palabra. Esto además resuelve un detalle técnico: la fórmula simplificada \(P(y \mid x) = C(x,y)/C(x)\) exige que cada aparición de \(x\) vaya seguida de algo; sin <END>, una palabra al final del corpus rompería la igualdad. Con el token final, toda palabra —incluida la última— inicia exactamente un bigrama. Al incluir <END>, el modelo define una distribución normalizada sobre oraciones terminadas, siempre que el proceso generativo alcance <END> con probabilidad 1 (sin caminos que generen indefinidamente).

4.1 Ejemplo completo

Probabilidad de “el gato duerme” con nuestro corpus:

  1. \(P(\text{el} \mid \text{START}) = 3/3 = 1\) (<START> aparece 3 veces, siempre seguido de “el”).
  2. \(P(\text{gato} \mid \text{el}) = 2/3\).
  3. \(P(\text{duerme} \mid \text{gato}) = 1/2\).
  4. \(P(\text{END} \mid \text{duerme}) = 2/2 = 1\).
\[ P = 1 \times \frac{2}{3} \times \frac{1}{2} \times 1 = \frac{1}{3} \]

La probabilidad restante se reparte entre otras oraciones generables con estos bigramas (“el gato come”, “el perro duerme”…). El modelo generaliza a oraciones no vistas en lugar de memorizar las tres del corpus.

5 La matriz de conteo y la matriz de probabilidad

Para operar, el corpus se comprime en una matriz de conteo de bigramas: filas = palabra anterior (historia), columnas = palabra siguiente, celdas = ocurrencias. Se recorre el texto con una ventana deslizante de tamaño 2 incrementando la celda correspondiente. Con nuestro corpus:

Historia  Siguiente el gato perro duerme come <END>
<START> 3 0 0 0 0 0
el 0 2 1 0 0 0
gato 0 0 0 1 1 0
perro 0 0 0 1 0 0
duerme 0 0 0 0 0 2
come 0 0 0 0 0 1

(También aparecen los bigramas con tokens especiales: (<START>, el), (duerme, <END>) y (come, <END>).)

Dividiendo cada fila por su suma se obtiene la matriz de probabilidad: cada celda \((x, y)\) contiene \(P(y \mid x)\), y —la misma regla de oro de la matriz de transición— cada fila suma 1. Por ejemplo, la fila “el” suma 3, así que \(P(\text{gato} \mid \text{el}) = 2/3\) y \(P(\text{perro} \mid \text{el}) = 1/3\).

Esta descripción matricial simple vale directamente para bigramas. En modelos de orden superior la idea es idéntica, pero la fila representa la historia completa: \((w_{i-1})\) en bigramas, \((w_{i-2}, w_{i-1})\) en trigramas, \((w_{i-3}, w_{i-2}, w_{i-1})\) en 4-gramas.

Esta matriz es el modelo de lenguaje, y sirve para tres tareas:

  • Puntuar una oración: trocearla en bigramas y multiplicar sus probabilidades: \(P(\text{“el gato duerme”}) = 1 \times 2/3 \times 1/2 \times 1 = 1/3\).
  • Predecir la siguiente palabra: tomar la última palabra, buscar su fila y devolver la columna con mayor probabilidad. Tras “gato” hay empate entre “duerme” y “come” (\(1/2\) cada una).
  • Generar texto: paseo aleatorio ponderado —elegir el primer bigrama desde <START> según sus probabilidades, luego encadenar bigramas desde la última palabra elegida, hasta alcanzar <END>. Desde <START> siempre sale “el”; desde “el”, “gato” con probabilidad \(2/3\) y “perro” con \(1/3\). Las opciones probables salen más a menudo, pero a veces toca una rara: así nace la variabilidad del texto generado.

Nota

El desbordamiento numérico se evita con logaritmos. Multiplicar decenas de probabilidades entre 0 y 1 produce números que el ordenador no puede representar. El truco es sumar log-probabilidades en lugar de multiplicar probabilidades: el mismo que usa Viterbi en el capítulo de HMM.

6 Evaluar el modelo: perplejidad

Un buen modelo asigna probabilidad alta a oraciones naturales del idioma. La perplejidad mide exactamente eso sobre un conjunto de prueba reservado: es la inversa de la probabilidad del conjunto, normalizada por su longitud \(m\):

\[ PP(W) = P(w_1 \dots w_m)^{-1/m} = \exp\left(-\frac{1}{m}\sum_{i=1}^{m} \ln p_i\right) \]

Intuición: si el modelo reparte su probabilidad entre \(k\) continuaciones igualmente probables, la perplejidad vale \(k\) —el número efectivo de opciones entre las que “duda”. Menor perplejidad = modelo menos confuso = mejor modelo. Está emparentada con la entropía de teoría de la información.

Referencias típicas en inglés a nivel de palabra: unigramas ~962, trigramas ~109, buenos modelos entre 20 y 60. Cada orden de n-grama añade fluidez: el unigrama genera palabras sueltas sin sentido, el bigrama pares plausibles y el trigrama fragmentos casi naturales.

6.1 Ejemplo de cálculo

Corpus de prueba con \(m = 6\) palabras en dos oraciones: “El gato duerme” y “El perro corre”. El modelo asigna:

Oración 1: \(P = 0.7 \times 0.5 \times 0.6 \times 0.8 = 0.168\) (inicio, “gato” tras “El”, “duerme” tras “gato”, fin tras “duerme”).

Oración 2: \(P = 0.7 \times 0.4 \times 0.7 \times 0.9 = 0.1764\).

Probabilidad conjunta (oraciones independientes): \(P(W) = 0.168 \times 0.1764 = 0.0296352\). Perplejidad:

\[ PP = 0.0296352^{-1/6} \approx 1.80 \]

Aquí \(m = 6\) cuenta las palabras observadas, aunque la probabilidad conjunta incluye los factores de inicio y fin: es una convención simplificada habitual en textos didácticos (la alternativa rigurosa contaría cada predicción, tokens especiales incluidos, y daría otro valor). Un valor bajísimo porque el juguete es diminuto y el modelo lo predice casi todo; en corpus reales se obtienen valores de decenas o centenas. Con logaritmos se llega al mismo resultado evitando productos minúsculos: \(\ln P(W) = \ln(0.168) + \ln(0.1764) = -1.7838 - 1.7350 = -3.5188\), y \(PP = \exp(3.5188/6) \approx 1.80\).

Importante

Compara perplejidades solo en igualdad de condiciones: mismo conjunto de prueba, misma tokenización (incluyendo mayúsculas, puntuación y unidad: palabras, subpalabras o caracteres), mismo vocabulario y tratamiento de <UNK>, y misma convención sobre <START> y <END>. Además, la métrica depende del dominio: un modelo de noticias tendrá alta perplejidad en chat informal aunque sea bueno en su dominio. Una perplejidad menor no significa automáticamente un modelo mejor para cualquier tarea.

7 Palabras desconocidas

El vocabulario es el conjunto de palabras que el modelo conoce. Con vocabulario cerrado (p. ej., un chatbot de dominio acotado) todo está previsto; con vocabulario abierto aparecen palabras fuera de vocabulario (OOV): topónimos nuevos, neologismos, erratas.

La estrategia estándar, idéntica a la del capítulo HMM, es el token <UNK>:

  1. Definir el vocabulario por frecuencia mínima (p. ej., palabras con \(\geq 2\) apariciones) o por tamaño máximo (p. ej., las 50.000 más frecuentes).
  2. Reemplazar en el entrenamiento toda palabra fuera del criterio por <UNK>.
  3. Calcular con normalidad, tratando <UNK> como una palabra más.

El aviso de la perplejidad viene de aquí: si hay demasiados <UNK>, el modelo asigna alta probabilidad a secuencias de <UNK> y la métrica baja artificialmente. Alternativas modernas que dependen menos de <UNK>: modelos a nivel de carácter o tokenización por subpalabras.

8 Suavizado

Aun con vocabulario cerrado, un bigrama de palabras conocidas puede no aparecer jamás: en nuestro corpus, “el perro come” tiene probabilidad cero porque \(C(\text{perro}, \text{come}) = 0\), aunque sea perfectamente posible. El suavizado corrige estos ceros; la teoría y la justificación están en la sección de estimación del capítulo HMM, aquí van las variantes propias de n-gramas.

Laplace (add-one). Sumar 1 a cada conteo de n-grama y el tamaño del vocabulario \(|V|\) al conteo de la historia:

\[ P(w_n \mid \text{historia}) = \frac{C(\text{historia}, w_n) + 1}{C(\text{historia}) + |V|} \]

Es “como si” cada n-grama se hubiera visto una vez. Elimina los ceros, aunque en corpus pequeños reparte demasiada probabilidad a lo no visto.

Add-\(k\). Generalización con \(0 < k < 1\) (p. ej., \(k = 0.5\)): sumar \(k\) al numerador y \(k \cdot |V|\) al denominador. Control más fino del reparto.

Backoff. Si falta el n-grama de orden superior, retroceder al inferior: sin el trigrama “Juan bebe café”, usar el bigrama “bebe café” con descuento (backoff de Katz).

Interpolación lineal. En vez de retroceder, combinar siempre todos los órdenes con pesos \(\lambda_1 + \lambda_2 + \lambda_3 = 1\) estimados en validación:

\[ P = \lambda_3 P_{\text{tri}} + \lambda_2 P_{\text{bi}} + \lambda_1 P_{\text{uni}} \]

Métodos más avanzados (Good-Turing, Kneser-Ney) refinan estas ideas ponderando según la frecuencia de las frecuencias.

Nota

El stupid backoff no es una probabilidad. En corpus gigantescos a escala web se usa una variante sin descuento: si falta el n-grama superior, se toma la puntuación del inferior multiplicada por \(\alpha \approx 0.4\). Esa puntuación ordena candidatos igual de bien, pero no está normalizada como distribución de probabilidad; usarla directamente para calcular perplejidades exige cautela.

9 Dónde encaja esto

Los n-gramas son el modelado de lenguaje clásico: transparente (todo son conteos), barato y con teoría de evaluación propia (perplejidad). Su límite es la memoria corta y la dispersión: ni con suavizado capturan dependencias largas. Las redes recurrentes intentan resumir la historia previa en un vector de estado —con capacidad limitada y olvidos—, y los transformadores consultan el contexto con atención. Pero cada vez que evalúes un modelo de lenguaje moderno con perplejidad, estarás usando la métrica nacida aquí.