Saltar al contenido
coden

Modelos ocultos de Márkov: el algoritmo de Viterbi y el casino deshonesto

Modelo oculto de Márkov, los tres problemas de Rabiner, el algoritmo hacia delante, el algoritmo de Viterbi, la decodificación a posteriori y el algoritmo de Baum-Welch — en un casino que de vez en cuando cambia en secreto el dado por uno cargado.

14 minutos Matěj Žalmánek 2026-10-15

Serie Fundamentos de IA Parte 39 de 52
  1. Mapa de la inteligencia artificial: qué es cada cosa y cómo encaja todo
  2. Breve historia de la inteligencia artificial: de Turing a los modelos de lenguaje
  3. Datos, modelo, entrenamiento, inferencia: los conceptos básicos en un solo ejemplo
  4. Cómo leer la notación matemática: símbolos, subíndices, sumatorios y cuantificadores
  5. Conjuntos y relaciones: las piezas con las que se construyen las definiciones en IA
  6. Funciones y aplicaciones: por qué todo modelo de IA es una función
  7. Lógica y demostraciones: las reglas con las que se razona en IA
  8. Grafos y árboles: la estructura sobre la que se apoyan la búsqueda y las redes neuronales
  9. Álgebra lineal para aprendizaje automático: vectores, matrices y por qué la IA sobre todo multiplica
  10. Derivadas, gradiente y regla de la cadena: cómo sabe un modelo en qué dirección aprender
  11. Descenso de gradiente: cómo aprende un modelo
  12. Qué es la probabilidad: del lanzamiento de un dado a los axiomas de Kolmogórov
  13. Probabilidad condicionada y teorema de Bayes: cómo cambiar una estimación cuando te enteras de algo nuevo
  14. Variable aleatoria y función de distribución: una sola función que lo dice todo sobre la distribución
  15. Función de densidad y función de probabilidad: por qué una variable continua tiene probabilidad cero en cada punto
  16. Esperanza, varianza y covarianza: dónde está una distribución, qué anchura tiene y qué se relaciona con qué
  17. Resumen de las distribuciones de probabilidad: Bernoulli, binomial, Poisson, uniforme, normal y exponencial
  18. Ley de los grandes números y teorema central del límite: por qué las medias se comportan de forma tan predecible
  19. Estadística y estimación de parámetros: máxima verosimilitud, MAP e intervalos de confianza
  20. Teoría de la información: entropía, entropía cruzada y divergencia KL, el origen de las funciones de pérdida
  21. Búsqueda en el espacio de estados: BFS, DFS, UCS y A* con animaciones
  22. Juegos y adversarios: minimax, poda alfa-beta y Monte Carlo tree search
  23. Satisfacción de restricciones: backtracking, propagación de restricciones y AC-3 con un sudoku y un mapa de regiones checas
  24. Lógica y sistemas basados en conocimiento: encadenamiento hacia delante y hacia atrás, resolución y sistemas expertos
  25. Planificación: STRIPS, el mundo de bloques, heurísticas a partir de la relajación y la planificación en los agentes de IA
  26. Búsqueda local y recocido simulado: un viajante por las capitales regionales checas
  27. Algoritmos genéticos: población, cruce, mutación y selección en una mochila para la excursión
  28. Estrategias evolutivas y programación genética: de la regla de un quinto a la ley de Kepler
  29. Optimización por colonia de hormigas: cómo un rastro de feromona encuentra un camino corto
  30. Optimización por enjambre de partículas: inercia, experiencia propia y experiencia del enjambre
  31. Neuroevolución: evolución de los pesos y la forma de las redes neuronales, y el algoritmo NEAT
  32. Conjuntos difusos y funciones de pertenencia: cómo escribir «algo cálido»
  33. Lógica difusa y probabilidad: por qué «algo cálido» no significa «probablemente cálido»
  34. Lógica difusa: t-normas, implicaciones y reglas SI–ENTONCES
  35. Control difuso: Mamdani y Sugeno, del ventilador al péndulo invertido sobre un carro
  36. Agrupamiento difuso: el algoritmo fuzzy c-means y los puntos entre clusters
  37. Sistemas neuro-difusos (ANFIS): reglas difusas que aprenden de los datos
  38. Cadenas de Markov: matriz de transición, distribución estacionaria y PageRank
  39. Modelos ocultos de Márkov: el algoritmo de Viterbi y el casino deshonesto
  40. Redes bayesianas: por qué está mojada la hierba y qué significa eso para el aspersor
  41. El filtro de Kalman: cómo estimar a partir de mediciones imprecisas dónde está un coche y a qué velocidad va
  42. Tipos de aprendizaje automático: supervisado, no supervisado, semisupervisado y más
  43. Prompts, contexto y RAG: cómo darle a un modelo la información correcta
  44. Autocodificadores variacionales (VAE): imágenes nuevas a partir de un espacio latente continuo
  45. Redes generativas adversarias (GAN): el falsificador contra el detective
  46. Modelos de difusión: cómo el ruido puro se convierte en una imagen
  47. Procesos de decisión de Markov: estados, acciones, recompensas y ecuaciones de Bellman
  48. Q-learning y DQN: aprender el valor de las acciones, de la tabla a la red neuronal
  49. Gradiente de la política y PPO: aprender directamente la política
  50. Cómo funciona un agente de IA: un modelo de lenguaje en un bucle con herramientas
  51. Programación con agentes de IA: encargo, pruebas y revisión
  52. Evaluación y seguridad de los sistemas de IA: cómo medir y cómo vigilar

Temario completo de la serie 52 de 83 temas publicados

Qué te llevarás
  • Qué es un modelo oculto de Márkov y cómo se calcula la probabilidad de las observaciones sin recorrer todos los caminos.
  • Cómo el algoritmo de Viterbi encuentra los estados ocultos más probables y dónde se equivoca.
  • Cómo el modelo aprende sus parámetros solo a partir de las observaciones y cuántos datos necesita para ello.

Conviene conocer antes: Cadenas de Markov: matriz de transición, distribución estacionaria y PageRank

En la parte anterior veíamos el estado de la cadena: hoy hace sol, mañana llueve. Pero a menudo solo vemos sus manifestaciones. Un micrófono capta una onda sonora, no la palabra que la produjo. Un secuenciador lee las letras del ADN, no dónde empieza un gen. Y en el casino vemos qué ha salido, no con qué dado tira el crupier. Los modelos ocultos de Márkov son cadenas cuyos estados no vemos — y algoritmos con los que, aun así, se puede averiguar qué pasa dentro. Durante décadas, el reconocimiento del habla se apoyó en ellos.

Continúa la parte Cadenas de Márkov.

1. El casino deshonesto

Un ejemplo clásico de libro de texto (Durbin et al., 1998): el crupier tira con un dado legal o con uno cargado, en el que el seis sale con probabilidad 1/2 y los demás números con 1/10. Después de cada tirada cambia el dado legal por el cargado con probabilidad 0,05, y el cargado de vuelta por el legal con probabilidad 0,1. El cambio no lo vemos. Solo vemos una serie de números — en nuestro experimento, 300 tiradas que empiezan así:

163665521623524236522511663566613666222461626262162666626516…

Nos preguntamos: ¿se juega limpio aquí? Y si no, ¿cuándo exactamente estuvo en juego el dado cargado?

2. Modelo oculto de Márkov

Definición — modelo oculto de Márkov

Un modelo oculto de Márkov (HMM) λ = (π, A, B) tiene estados ocultos 1, …, N y símbolos observables 1, …, M:

  • los estados ocultos X1, X2, … forman una cadena de Márkov con distribución inicial π y matriz de transición A, aij = P(Xt+1 = j | Xt = i);
  • en cada instante, el estado Xt = i genera una observación Ot según las probabilidades de emisión bi(o) = P(Ot = o | Xt = i), independientemente de todo lo demás.
Dicho de forma sencilla

Detrás del telón corre una cadena de Márkov corriente — el dado cambia según la matriz A. Nosotros solo vemos lo que «sale» de cada estado: una tirada según las probabilidades B. Con el dado cargado, el seis es cinco veces más probable que cualquier otro número, pero también puede salir con el legal. Por eso una sola tirada no delata nada — lo delata el patrón de toda la serie.

ocultos vemos 0,05 0,1 0,95 legal 1 2 3 4 5 6 número obtenido (puntos) P(tirada) (0–1) 1/6 0,9 cargado 1 2 3 4 5 6 número obtenido (puntos) P(tirada) (0–1) 6: 0,5
Modelo del casino: estados ocultos arriba, probabilidades de las tiradas abajo

De la definición se deduce qué probabilidad tiene una «historia» concreta: una secuencia de dados x = (x1, …, xT) junto con las tiradas O = (O1, …, OT).

P(x, O | λ) = πx1 bx1(O1) · ∏t=2T axt−1 xt bxt(Ot)

πx1
el primer dado no tiene predecesor desde el que se pase a él — su probabilidad la da la distribución inicial
axt−1 xt
cada dado siguiente depende solo del anterior (propiedad de Márkov), así que por cada paso basta un número de la matriz A
bxt(Ot)
la tirada depende solo del dado con el que se está tirando — tomamos la probabilidad del número que salió de verdad
∏t=2T
en general se multiplicarían probabilidades condicionadas a todo el pasado (regla de la cadena); las dos hipótesis de independencia de la definición las reducen a estos números locales, y por eso el total es un simple producto
Cada paso añade dos factores: cómo (no) cambió el dado y qué salió con él.
Ejemplo — dos historias de las tres primeras tiradas

Nuestra serie empieza con las tiradas 1, 6, 3. Llamemos L al dado legal y C al cargado. La historia «tres veces cargado»:

P(CCC, 1, 6, 3) = 0,5 · 0,1 · 0,9 · 0,5 · 0,9 · 0,1 = 0,002025,

la historia «tres veces legal»:

P(LLL, 1, 6, 3) = 0,5 · 1/6 · 0,95 · 1/6 · 0,95 · 1/6 = 0,002089.

La historia legal sale un pelín más probable: el seis con el dado cargado recibe 0,5 en vez de 1/6, pero el uno y el tres solo 0,1 en vez de 1/6. (Y eso que en la simulación las tres tiradas se hicieron con el dado cargado — con tres tiradas no se puede notar.)

Lawrence Rabiner, en su famosa revisión de 1989, resumió lo que se puede hacer con un modelo así en tres problemas: evaluación (¿qué probabilidad tiene la serie observada?), decodificación (¿qué estados ocultos es más probable que hubiera detrás?) y aprendizaje (¿qué parámetros tiene el modelo si solo conocemos las observaciones?). Para cada uno existe un algoritmo elegante.

3. Qué probabilidad tiene la serie: el algoritmo hacia delante

La probabilidad de la serie observada es la suma sobre todas las secuencias posibles de estados ocultos. Para 300 tiradas y dos dados hay 2300 ≈ 2 · 1090 — más que átomos en el universo. Sumarlas directamente no es posible. Pero la propiedad de Márkov permite calcular paso a paso.

Ejemplo — probabilidad de tres tiradas como suma sobre todas las historias

La probabilidad de la observación es la suma de la probabilidad conjunta sobre todas las historias posibles: P(O | λ) = ∑x P(x, O | λ). Para las tiradas 1, 6, 3 hay 23 = 8:

HistoriaP(x, O)
LLL0,002089
LLC0,000066
LCL0,000035
LCC0,000188
CLL0,000132
CLC0,000004
CCL0,000375
CCC0,002025
suma0,004913

Cada historia cuesta 2T − 1 = 5 multiplicaciones, en total 8 · 5 = 40. Para T tiradas son (2T − 1) · 2T — con 300 tiradas, una cantidad inimaginable.

Algoritmo — algoritmo hacia delante

Sea αt(j) = P(O1, …, Ot, Xt = j). Entonces

α1(j) = πj bj(O1),   αt+1(j) = [∑i αt(i) aij] bj(Ot+1),   P(O | λ) = ∑j αT(j).

El cálculo tarda O(N2 T) en lugar de O(NT). Para que los números no sufran subdesbordamiento, αt se normaliza en cada paso y se suman los logaritmos de las constantes de normalización.

Dicho de forma sencilla

No hace falta que sigas cada historia posible por separado. Basta con recordar, después de cada tirada, dos números: «qué probabilidad tiene todo lo que he visto hasta ahora y que ahora esté en juego el dado legal» — y lo mismo para el cargado. A partir de ellos se calculan los números de la siguiente tirada. Todas las historias que terminan en el mismo estado se funden en un solo número.

αt+1(j) = ∑i αt(i) aij · bj(Ot+1)

αt(i)
todo lo que sabemos del pasado: la probabilidad de las tiradas hasta ahora y de que ahora esté en juego el dado i; en este único número están fundidas todas las historias que terminan en i
aij
un paso de la cadena de i a j; gracias a la propiedad de Márkov no importa cómo llegamos a i
∑i
no sabemos con qué dado se tiró la vez anterior, y a j se puede llegar desde cualquiera — por eso sumamos sobre todas las posibilidades (las historias son sucesos mutuamente excluyentes)
bj(Ot+1)
la nueva tirada la tiene que generar de verdad el dado j; no depende de i, así que se puede sacar fuera de la suma
La suma sobre 2T historias se descompone en T sumas pequeñas de N términos.
Ejemplo — algoritmo hacia delante sobre las tiradas 1, 6, 3

Inicio: α1(L) = 0,5 · 1/6 = 0,0833, α1(C) = 0,5 · 0,1 = 0,0500. La segunda tirada es un seis:

α2(L) = (0,0833 · 0,95 + 0,0500 · 0,1) · 1/6 = 0,0140,
α2(C) = (0,0833 · 0,05 + 0,0500 · 0,9) · 0,5 = 0,0246.

ttiradaαt(L)αt(C)suma = P(O1, …, Ot)ct
110,08330,05000,1333330,1333
260,01400,02460,0386110,2896
330,00260,00230,0049130,1273

La suma de la última fila es exactamente la suma de las ocho historias del ejemplo anterior, solo que en lugar de 40 multiplicaciones han bastado 2 + 2 · 6 = 14. La última columna, ct = P(Ot | O1, …, Ot−1), es la constante de normalización del escalado: qué probabilidad tenía la tirada t dadas las anteriores. Su producto es P(O | λ), así que log P(O | λ) = ∑t log ct.

¿Por qué logaritmos? Con 3 000 tiradas, P(O | λ) sale alrededor de 10−2 278, y el menor número positivo que un ordenador guarda en la doble precisión habitual (IEEE 754) es aproximadamente 4,9 · 10−324. Sin escalado, α sufriría subdesbordamiento hasta cero.

def dopredu(hody, pi, A, B):
    alfa = pi * B[:, hody[0]]
    logP = 0.0
    for t in range(len(hody)):
        if t > 0:
            alfa = (alfa @ A) * B[:, hody[t]]       # suma sobre i, luego emisión
        c = alfa.sum()                              # c_t = P(O_t | O_1, …, O_t−1)
        alfa = alfa / c                             # escalado: ahora α_t suma 1
        logP += np.log(c)
    return logP                                     # log P(O | λ)

Para nuestras 300 tiradas sale P(tiradas | modelo del casino) ≈ 10−230,03. Si se hubiera jugado limpio todo el tiempo, la probabilidad sería (1/6)300 ≈ 10−233,45. El modelo con un dado cargado ocasional explica las tiradas observadas unas 2 600 veces mejor — una prueba fuerte de que aquí se hace trampa, aunque ninguna tirada por sí sola delate el engaño.

Definición — cociente de verosimilitudes (factor de Bayes)

Para dos modelos M1, M2 y unos datos O, el factor de Bayes es K = P(O | M1) / P(O | M2). Del teorema de Bayes (escrito para ambos modelos y dividido) se deduce:

P(M1 | O) / P(M2 | O) = P(O | M1) / P(O | M2) · P(M1) / P(M2)

P(M1 | O) / P(M2 | O)
la razón de probabilidades tras la observación — lo que nos interesa: cuánto más creemos en el engaño que en el juego limpio una vez vistas las tiradas
P(O | M1) / P(O | M2)
el factor de Bayes — el único sitio por el que los datos entran en la fórmula; las dos verosimilitudes las calcula el algoritmo hacia delante. El denominador P(O) del teorema de Bayes se cancela al dividir, y por eso no hace falta conocerlo
P(M1) / P(M2)
la razón de probabilidades previa — quien confía de antemano en el casino necesita una prueba más fuerte; los datos solo la multiplican

Cálculo. log10 K = −230,03 − (−233,45) = 3,42 (con los valores sin redondear, 3,413), es decir, K ≈ 103,413 ≈ 2 590, redondeando 2 600. Quien de antemano consideraba igual de probables el engaño y el juego limpio, tras 300 tiradas tiene una razón de unos 2 600 : 1 a favor del engaño. Según la escala de Kass y Raftery (1995), de uso habitual, un factor de Bayes superior a 150 es una prueba «muy fuerte».

4. Cuándo se hizo trampa: el algoritmo de Viterbi

Algoritmo — algoritmo de Viterbi (1967)

Buscamos la secuencia de estados más probable, argmaxx P(x, O | λ). Sea δt(j) la probabilidad del mejor camino que en el instante t termina en el estado j:

δ1(j) = πj bj(O1),   δt+1(j) = maxi [δt(i) aij] · bj(Ot+1),

y para cada δt+1(j) recuerda de qué i vino. Al final elige el mejor estado y vuelve hacia atrás siguiendo los enlaces recordados. Se calcula en logaritmos; el tiempo vuelve a ser O(N2 T).

Dicho de forma sencilla

La misma idea que el algoritmo hacia delante, solo que en lugar de sumar sobre todos los caminos se toma el mejor. A cada estado en cada instante lleva un único camino «ganador» — si el mejor camino total pasara por ahí, también llegaría a ese punto por él. Es programación dinámica, emparentada con la búsqueda del camino más corto de la parte «Búsqueda en el espacio de estados».

δt+1(j) = maxi δt(i) aij · bj(Ot+1),   ψt+1(j) = argmaxi δt(i) aij

δt(i)
la probabilidad de la mejor historia que en el instante t termina con el dado i; las historias peores hasta i ya no nos hacen falta — si el mejor camino completo pasara por i, continuaría por la mejor
aij
el coste de la transición de i a j; el pequeño aLC = 0,05 es la razón por la que a Viterbi no le apetece cambiar por un solo seis
maxi, ψt+1(j)
a diferencia del algoritmo hacia delante, no sumamos, sino que elegimos el mejor predecesor — queremos un camino, no la probabilidad de todos; ψ recuerda quién ganó (en la rejilla, las flechas ámbar) para que al final el camino se pueda reconstruir hacia atrás
bj(Ot+1)
lo bien que el dado j explica la nueva tirada — igual que en α
La misma fórmula que para α, solo que la suma ∑ se sustituye por el máximo.
legal cargado tirada 5 −1,1 −1,3 2 −1,9 −2,3 2 −2,7 −3,4 5 −3,5 −4,4 1 −4,3 −5,5 1 −5,1 −6,5 6 −5,9 −6,7 6 −6,7 −7,0 3 −7,5 −8,1 5 −8,3 −9,1 6 −9,1 −9,5 6 −9,9 −9,8
Rejilla de Viterbi para las tiradas 19–30: los números son el log₁₀ de la probabilidad del mejor camino

En doce tiradas se ve cómo decide Viterbi. Las seis primeras (5, 2, 2, 5, 1, 1) parecen legales. Luego salen dos seises seguidos y otros dos un poco más adelante — y el mejor camino cambia al dado cargado. En realidad, el crupier cambió de dado cuatro tiradas más tarde; dos seises seguidos también salen con un dado legal.

Ejemplo — Viterbi paso a paso sobre las tiradas 1, 6, 3

El inicio es el mismo que para α: δ1(L) = 0,0833, δ1(C) = 0,0500. Para el seis de la segunda tirada:

δ2(L) = max(0,0833 · 0,95; 0,0500 · 0,1) · 1/6 = 0,0792 · 1/6 = 0,0132   (ganó L),
δ2(C) = max(0,0833 · 0,05; 0,0500 · 0,9) · 0,5 = 0,0450 · 0,5 = 0,0225   (ganó C).

ttiradaδt(L)ψt(L)δt(C)ψt(C)
110,083333—0,050000—
260,013194L0,022500C
330,002089L0,002025C

Al final gana L (0,002089 > 0,002025) y, volviendo hacia atrás por los enlaces ψ, sale el camino LLL — exactamente la historia del primer ejemplo, que era la más probable de las ocho. Pero el algoritmo hacia delante da para la tercera tirada P(C | O1, O2, O3) = 0,002283 / 0,004913 = 0,465. El mejor camino y el estado más probable coinciden aquí (L), pero la «victoria» es ajustada y tres tiradas no bastan para estar seguros. En general no tienen por qué coincidir — volveremos a ello en la decodificación a posteriori.

import numpy as np

def viterbi(hody, pi, A, B):
    T, N = len(hody), len(pi)
    delta = np.log(pi) + np.log(B[:, hody[0]])
    odkud = np.zeros((T, N), dtype=int)
    for t in range(1, T):
        kandidati = delta[:, None] + np.log(A)       # de cada i a cada j
        odkud[t] = kandidati.argmax(axis=0)
        delta = kandidati.max(axis=0) + np.log(B[:, hody[t]])
    cesta = [int(delta.argmax())]
    for t in range(T - 1, 0, -1):                     # hacia atrás por los enlaces ganadores
        cesta.append(odkud[t][cesta[-1]])
    return cesta[::-1]

5. Las 300 tiradas

realidadtiradas (puntos)ViterbiP(cargado) (0–1) 01 0100200300 tirada (orden en la simulación)
Realidad, tiradas, camino de Viterbi y probabilidad del dado cargado

El dado cargado estuvo en juego 88 veces, en nueve tramos. Viterbi marcó como cargadas 62 tiradas, 56 de ellas correctamente, y en total acertó el dado en el 87,3 % de las tiradas. Los tramos largos de engaño los encontró, pero los cortos los pasó por alto o los fundió — en lugar de nueve tramos ve dos. En un tramo corto simplemente no salen suficientes seises como para que compense un «caro» cambio de dado (la probabilidad de cambio es solo 0,05).

Definición — probabilidad a posteriori del estado

El algoritmo hacia delante-atrás calcula además βt(i) = P(Ot+1, …, OT | Xt = i) desde el final y de ambos obtiene γt(i) = P(Xt = i | O) ∝ αt(i) βt(i).

Dicho de forma sencilla

Viterbi da una única respuesta: «fue este dado». La probabilidad a posteriori te dice cuán seguros estamos — para cada tirada por separado, teniendo en cuenta todo lo que salió antes y después. Fíjate en la curva inferior de la figura: donde sube por encima de la mitad, lo más probable es que se esté haciendo trampa.

γt(i) = αt(i) · βt(i) / P(O | λ),   βt(i) = ∑j aij bj(Ot+1) βt+1(j),   βT(i) = 1

γt(i)
la probabilidad de que en el instante t estuviera en juego el dado i, conociendo todas las tiradas — para el dado cargado es la curva roja de la figura
αt(i)
las pruebas del pasado: las tiradas 1 a t y el estado i en el instante t
βt(i)
las pruebas del futuro: lo bien que el estado i explica las tiradas t + 1 a T. Se calcula desde el final con el mismo truco que α — un paso de la cadena, la emisión, el resto del futuro. Podemos multiplicar α y β porque, conocido el estado Xt, las tiradas pasadas y las futuras son independientes
P(O | λ)
el producto α·β es la probabilidad conjunta P(Xt = i, O); al dividirla por la probabilidad de todas las tiradas la convertimos en condicionada. Es el mismo número que dio el algoritmo hacia delante, y se cumple ∑i αt(i) βt(i) = P(O | λ) en cada t
Ejemplo — la segunda tirada: lo que aporta el futuro

Sigamos con las tiradas 1, 6, 3 y preguntemos por la segunda tirada (el seis). El paso hacia atrás desde β3 = 1 con la tercera tirada (el tres):

β2(L) = 0,95 · 1/6 + 0,05 · 0,1 = 0,1633,   β2(C) = 0,1 · 1/6 + 0,9 · 0,1 = 0,1067.

γ2(C) = 0,024583 · 0,106667 / 0,004913 = 0,534.

Si solo conociéramos las dos primeras tiradas, sería P(C | O1, O2) = α2(C) / (α2(L) + α2(C)) = 0,637. El tres que salió después es menos probable con el dado cargado, y así rebaja retrospectivamente la sospecha sobre la segunda tirada a 0,534.

Definición — decodificación a posteriori y precisión

La decodificación a posteriori elige en cada instante por separado x̂t = argmaxi γt(i). La precisión de una decodificación x̂ frente a los estados reales x es la proporción de aciertos (1/T) ∑t [x̂t = xt], donde [·] vale 1 si la afirmación es cierta y 0 en caso contrario.

La decodificación a posteriori maximiza el número esperado de tiradas acertadas; Viterbi, la probabilidad de que sea correcto el camino entero de una vez. Por eso la secuencia a posteriori puede contener incluso una transición que en el modelo tiene probabilidad cero — en el casino no hay ninguna así, pero en general puede ocurrir.

Si en cada tirada eligiéramos el dado con mayor probabilidad a posteriori, acertaríamos el 87,7 % — un pelín más que Viterbi (263 tiradas de 300 frente a 262, una sola tirada de diferencia). (Viterbi busca el mejor camino completo; la decodificación a posteriori, la mejor estimación de cada tirada por separado; no es lo mismo.) Y cuidado con fiarte de una sola simulación: en doce experimentos distintos, la precisión del algoritmo de Viterbi osciló entre el 73,3 y el 90,0 %, con una media del 83,4 %, según lo largos que fueran los tramos de engaño que produjo el azar.

6. Aprendizaje: el algoritmo de Baum-Welch

Hasta ahora conocíamos los parámetros del casino. ¿Y si solo sabemos que hay dos dados y todo lo demás hay que sacarlo de las tiradas?

Algoritmo — algoritmo de Baum-Welch

Es un algoritmo EM (Baum et al., hacia 1970). Repite:

  1. paso E: con los parámetros actuales, calcula con el algoritmo hacia delante-atrás γt(i) y los números esperados de transiciones ξt(i, j) = P(Xt = i, Xt+1 = j | O);
  2. paso M: nuevo aij = ∑t ξt(i, j) / ∑t γt(i), nuevo bi(o) = proporción de γ en los instantes en que salió o.

La verosimilitud P(O | λ) no disminuye en ninguna iteración; el algoritmo converge a un máximo local.

Dicho de forma sencilla

Si supiéramos cuándo estuvo en juego cada dado, calcularíamos los parámetros simplemente contando. No lo sabemos — pero con alguna estimación de los parámetros sí sabemos calcular con qué probabilidad estuvo cada dado en cada momento. Calculamos, pues, recuentos «suaves»; a partir de ellos, mejores parámetros; a partir de estos, mejores recuentos… Cada ronda mejora el modelo.

El número esperado de transiciones se calcula con las mismas α y β que γ, solo que entre ellas se intercala un paso de la cadena:

ξt(i, j) = αt(i) aij bj(Ot+1) βt+1(j) / P(O | λ)

αt(i)
las tiradas hasta el instante t y el dado i en el instante t — el extremo izquierdo de la transición
aij
la propia transición i → j, cuya frecuencia estimamos
bj(Ot+1)
la tirada t + 1 la tiene que generar el nuevo dado j
βt+1(j)
el resto de las tiradas desde t + 2 en adelante, explicado a partir del dado j — el extremo derecho de la transición
P(O | λ)
al dividir, convertimos la probabilidad conjunta «transición y todas las tiradas» en la condicionada «transición, conocidas las tiradas»

âij = ∑t=1T−1 ξt(i, j) / ∑t=1T−1 γt(i)

âij
la nueva estimación de la probabilidad de transición — una frecuencia relativa, como si contáramos palotes
∑ ξt(i, j)
el número esperado de transiciones i → j; en lugar de «se pasó o no» (1 o 0) sumamos probabilidades, porque los estados no los vemos
∑ γt(i)
el número esperado de salidas del estado i; se suma solo hasta T − 1, porque del último estado ya no sale ninguna transición. Gracias a ello, cada fila de la nueva matriz suma 1
Si viéramos los estados, ξ y γ serían ceros y unos, y la fórmula sería la estimación de máxima verosimilitud habitual a partir de recuentos.
repite (aquí 100 veces):
    α, β, P(O) ← algoritmo hacia delante-atrás con los π, A, B actuales
    # paso E: recuentos suaves
    para cada t, i:           γ[t][i]    ← α[t][i] · β[t][i] / P(O)
    para cada t < T, i, j:    ξ[t][i][j] ← α[t][i] · a[i][j] · b[j](O[t+1]) · β[t+1][j] / P(O)
    # paso M: frecuencias relativas
    π[i]    ← γ[1][i]
    a[i][j] ← ∑_{t<T} ξ[t][i][j] / ∑_{t<T} γ[t][i]
    b[i](o) ← ∑_{t: O[t]=o} γ[t][i] / ∑_t γ[t][i]

Empezamos con una mala estimación: los dados apenas se distinguen y se cambian a menudo. Con 300 tiradas, Baum-Welch llegó a un modelo que casi nunca cambia de dado y que al dado cargado le da el seis solo con probabilidad 0,39 — 300 tiradas son pocas para una estimación fiable. Con 3 000 tiradas (de otra simulación del mismo casino) ya salió muy cerca de la verdad:

ParámetroRealidadEstimación con 3 000 tiradas
legal → cargado0,050,039
cargado → legal0,100,090
seis con el dado cargado0,500,491
seis con el dado legal0,1670,163

Por qué no bastan 300 tiradas lo muestra la verosimilitud. Durante 100 iteraciones sobre nuestras 300 tiradas creció de 10−231,26 a 10−227,14 — y eso es más que el 10−230,03 del verdadero modelo del casino. El modelo aprendido explica, pues, justo estas tiradas mejor que la verdad: se ha adaptado también a las fluctuaciones aleatorias de los datos concretos. La estimación de máxima verosimilitud solo se acerca a la verdad a medida que aumentan los datos.

7. Los modelos ocultos de Márkov en la práctica

  • Reconocimiento del habla. Desde los años ochenta hasta la llegada de las redes profundas, hacia 2010, casi todos los sistemas se basaban en HMM: los estados ocultos son partes de fonemas, las observaciones son tramos cortos del espectro sonoro y Viterbi busca la secuencia de palabras más probable.
  • Lenguaje. Etiquetado gramatical: el estado oculto es la categoría gramatical y la observación, la palabra. «Vino» puede ser sustantivo o verbo — decide el contexto.
  • Bioinformática. Búsqueda de genes en el ADN (los tramos codificantes y no codificantes son los estados ocultos) o HMM de perfil para las familias de proteínas de la base de datos Pfam.
  • Estados continuos. Cuando el estado oculto no es «dado A o B», sino la posición y la velocidad, en lugar de un HMM se usa el filtro de Kalman — tiene su propia parte en el temario.

8. Resumen

  • Un modelo oculto de Márkov es una cadena de Márkov de estados ocultos de los que solo vemos las emisiones; lo determinan π, A y B.
  • El algoritmo hacia delante calcula la probabilidad de las observaciones en tiempo O(N2T) en lugar de sumar sobre 2300 caminos; el casino con trampa explica nuestras tiradas unas 2 600 veces mejor que el juego limpio.
  • El algoritmo de Viterbi encuentra el camino de estados ocultos más probable mediante programación dinámica — en nuestra simulación acertó el dado en el 87,3 % de las tiradas, pero pasó por alto los tramos cortos.
  • El algoritmo hacia delante-atrás da la probabilidad a posteriori del estado en cada instante.
  • El algoritmo de Baum-Welch aprende los parámetros solo a partir de las observaciones — pero necesita suficientes datos: 300 tiradas no bastaron, 3 000 sí.

¿Quieres probarlo tú mismo? Pide a un agente de IA que entrene un HMM de dos estados con los rendimientos diarios de un índice bursátil — y mira si encuentra por sí solo los periodos «tranquilos» y «turbulentos» del mercado.

¿Lo ves de otra manera? Escribe a support@coden-app.com.

Un Agente en tu ordenador, controlado desde el móvil