Implementación de Modelos Ocultos de Markov en NLTK y Python

Clase 13 de 26Curso de Algoritmos de Clasificación de Texto

Contenido del curso

Resumen

Construir un etiquetador de categorías gramaticales desde cero y luego compararlo con una implementación profesional es una de las mejores formas de comprender cómo funcionan los modelos marcoviano latentes (Hidden Markov Models). Aquí se cierra ese ciclo completo: desde la selección de etiquetas con la matriz de Viterbi hasta el uso directo de la clase HMM que ofrece NLTK.

¿Cómo se selecciona la secuencia de etiquetas más probable con Viterbi?

En clases anteriores se construyó una función llamada viterbi_matrix que recibía una cadena de texto y devolvía la matriz de probabilidades de Viterbi [0:36]. El paso siguiente consiste en transformar esa función para que, en lugar de devolver la matriz, entregue directamente las etiquetas gramaticales más probables. Por eso se renombra a viterbi_tags [1:07].

El proceso adicional funciona así:

  • Se crea una lista vacía llamada res que almacenará las parejas de palabra y etiqueta.
  • Se recorre cada palabra de la secuencia usando enumerate para conservar el índice de columna [1:30].
  • Dentro de ese recorrido, se itera sobre todas las etiquetas posibles consultando el diccionario de estados (tag_state_dict).
  • Para cada palabra se busca la fila cuyo valor sea el máximo en la columna correspondiente de la matriz viterbi_prob [2:07].
  • Si una etiqueta coincide con ese máximo, se agrega la pareja (palabra, etiqueta) a la lista.

El return final ya no es la matriz, sino la lista res con la secuencia completa de etiquetas [2:41].

¿Qué resultados produce la función viterbi_tags?

Al ejecutar la función con la frase "El mundo es pequeño", el resultado es una secuencia tokenizada donde cada palabra recibe su etiqueta: determinante, sustantivo, auxiliar, adjetivo [3:15]. Con otra frase como "Estos instrumentos han de rasgar", el modelo identifica correctamente que rasgar es un verbo, aunque las demás etiquetas requieren verificación individual [3:38].

Esta verificación se haría mediante una métrica de accuracy, tal como se hace en machine learning con un esquema supervisado [3:56]. Lo esencial es haber comprendido el proceso completo: entrenamiento con matrices de probabilidad, ejecución del algoritmo y generación de la secuencia más probable.

¿Cómo se entrena un HMM directamente con NLTK?

NLTK incluye una clase llamada HiddenMarkovModelTrainer que encapsula todo el proceso que se programó desde cero [4:50]. Para usarla se trabaja con el corpus Treebank en inglés, un dataset ya etiquetado que se descarga con nltk.download [4:43].

¿Cómo se preparan los datos de entrenamiento?

Del corpus Treebank se seleccionan las frases etiquetadas (tagged sentences) hasta la sentencia 3900, lo que representa aproximadamente el 90 % del dataset [5:20]. La estructura resultante es una lista de listas donde cada frase está tokenizada en tuplas de palabra y etiqueta gramatical [5:47].

Es importante notar que este dataset usa una convención de etiquetado distinta a la UPOS que se venía utilizando con el corpus Áncora en español [6:02]. El algoritmo funciona con cualquier convención que se decida emplear.

¿Qué tan sencillo es ejecutar el entrenamiento?

El código se reduce a pocas líneas [6:30]:

python from nltk.tag import hmm

tagger = hmm.HiddenMarkovModelTrainer().train_supervised(train_data)

Con tagger.tag("Pierre Binkin will get old".split()) se obtiene la secuencia de etiquetas predicha [7:30]. Y para medir el rendimiento se usa tagger.evaluate(train_data), que arroja una precisión cercana al 98 % sobre el conjunto de entrenamiento [8:05].

Detrás de esa simplicidad hay un volumen de código muy elaborado. Revisar el código fuente de la clase HiddenMarkovModelTrainer permite entender la diferencia entre convertir matemáticas en código y optimizar ese código hasta cumplir buenas prácticas de desarrollo de software [8:35].

¿Qué ejercicio práctico cierra esta primera parte?

Al final del notebook se propone un ejercicio que combina el dataset Áncora en español con la clase de modelo marcoviano latente de NLTK [9:15]. El objetivo es aplicar la implementación profesional de NLTK al mismo corpus con el que se trabajó manualmente, comparando resultados y consolidando lo aprendido.

Comparte tus resultados y hallazgos en la sección de comentarios: ¿qué accuracy obtuviste al combinar Áncora con la clase HMM de NLTK?