Markov Chains - Hidden Markov Models
Código del curso CS50’s Introduction to Artificial Intelligence with Python, lecture 2 "uncertainty", refactorizado a la nueva api de pomegranate v1.0.4 jmschrei
Es necesario el uso del paquete Pomegranate:
Pomegranate is a python package which implements fast, efficient, and extremely flexible probabilistic models ranging from probability distributions to Bayesian networks to mixtures of hidden Markov models.
python -m venv venv
source venv/bin/activate
Instalar la versión estricta de pomegranate v1.0.4
:
pip install -r requirements.txt
o
pip install pomegranate
Vamos a construir una cadena de Markov donde las variables aleatorias siguen la suposición de Markov: el estado actual depende sólo de un número finito de estados previos.
Supongamos que podemos definir la probabilidad de que mañana sea un dia soleado o llueva en función de cómo está el tiempo hoy.
Definimos el modelo de transición de nuestro ejemplo de este modo:
Probabilidades iniciales de lluvia (R) y sol (S) en el primer día de la serie:
El modelo de transiciones es este:
Hoy | Mañana | |
---|---|---|
sol | lluvia | |
sol | 0.8 | 0.2 |
lluvia | 0.3 | 0.7 |
Calculamos un posible serie de predicciones sobre el estado del tiempo dadas la probabilidades iniciales y el modelo de transiciones:
$ python markov_chain/model.py
Numero de muestras: 50
rain -> rain -> rain -> sun -> rain -> sun -> rain -> sun ->
rain ->rain -> rain -> rain -> rain -> sun -> sun -> sun ->
sun -> sun -> sun -> sun -> sun -> rain -> rain -> sun ->
sun -> sun -> sun -> rain -> rain -> rain -> sun -> sun ->
sun -> sun -> rain -> rain -> rain -> rain -> rain -> sun ->
sun -> rain -> sun -> sun -> sun -> rain -> rain -> rain -> sun -> sun
Hidden Markov Model
En muchas ocasiones el estado del mundo es desconocido, pero de algún modo el agente inteligente es capaz de percibir información sobre el mundo mediante sus sensores. A partir de estas observaciones podemos inferir determinados aspectos del estado oculto, ya que dicho estado oculto influencia las observaciones.
Vamos a construir un modelo oculto de Markov en el que deduciremos el estado del tiempo en función de las observaciones que realiza nuestro agente inteligente sobre si las personas que entran en un edificio portan paragüas.
Las probabilidades de emisión son las siguientes:
Estado | Observación | |
---|---|---|
paraguas | sin paraguas | |
sol | 0.2 | 0.8 |
lluvia | 0.9 | 0.1 |
Estas probabilidades de emisión dependen únicamente del estado del tiempo hoy.
Proporcionamos al modelo una serie de observaciones y nos devuelve la secuencia de estados más probable (la explicación más probable).
$ python hmm/model.py
Dimensiones del array de observaciones: (1, 9, 1)
umbrella -> rain
umbrella -> rain
no_umbrella -> sun
umbrella -> rain
umbrella -> rain
umbrella -> rain
umbrella -> rain
no_umbrella -> sun
no_umbrella -> sun
Matemática de los Hidden Markov Models
Si
[1] Regla de Bayes:
[2] Probabilidad total:
donde
[3] La(s) distribuciones de probabilidad(es) del(os) estado(s) inicial(es):
Aplicando las expresiones [1], [2] y [3] del epígrafe anterior, resuelve el siguiente problema.
Se trata de uno de los problemas propuestos en el MOCC sobre IA por Sebastian Thrun para explicar cómo se calculan las probabilidades de los estados ocultos dadas las observaciones.
Supongamos que queremos construir un modelo oculto de Markov para calcular el estado del tiempo en función del estado de humor de la población. En función de las observaciones sobre si la gente está feliz o gruñona deduciremos las probabilidades de que el día esté soleado o lluvioso.
En la figura se describen las probabilidades de transición entre los estados Rainy
Se pide calcular la probabilidad de que el día 1 sea lluvioso
dadas las probabilidades iniciales de los estados:
Dispones de este ejercicio resuelto en este vídeo, como se indica en la figura:
En la regla de Bayes [1] sustituímos el estado oculto
Debemos calcular, por tanto, las probalidades:
$P(H_1 | R_1)$ $P(R_1)$ $P(H_1)$
La probabilidad de que la gente sea feliz si el día es lluvioso, o
Para el cálculo de la probabilidad de que el día 1 sea lluvioso
extrayendo las probabilidades de transición entre los estados
La probablidad de que en el día 1 la gente esté feliz
La probabilidad
Necesitamos calcular la probabilidad total de que el día 1 sea soleado
que introducida en la expresión
Disponemos ya de todos las probabilidades para sustituir en la expresión:
Observa los números en la figura:
Un proceso de Markov es un proceso aleatorio con la propiedad de que dado el valor actual del proceso
Así, una secuencia de variables aleatorias
que expresada de otro modo:
para todo
Es decir, sólo el último estado determina la probabilidad del estado actual.
Las probabilidades
Cuando estas probabilidades son independientes del tiempo (de
Así, si la probabilidad de que
$$ P^{nn+1}{ij} = P(X{n+1} = j | X_n = i) $$
En este caso, $P^{nn+1}{ij}=P{ij}$, no depende de
Supongamos que en nuestro ejercicio del clima hemos observado la siguiente secuencia de observaciones:
Numero de muestras: 10
rain -> rain -> sun -> sun -> rain -> sun -> rain -> sun -> rain -> rain
Abrevianos la notación de la forma:
Recuerda que se cumple la propiedad de Markov.
En el mundo de la ciencia de datos, existe una tendencia a emplear aproximaciones a este tipo de problemas de entradas secuenciales usando técnicas de machine learning para encontrar las relaciones en el conjunto de datos -por ejemplo las Long Short Term Memory Networks (LSTM), que son un tipo de redes neuronales recurrentes (RNN)- pero en muchos casos no disponemos de una cantidad de muestras significativas o las secuencias son demasiado largas para entrenar una RNN de manera efectiva.
En estos casos, podemos recurrir a los Hidden Markov Models (HMM) y a las Cadenas de Markov. Ambos métodos proveen de una aproximación "ligera" pero robusta que utiliza estadística y distribuciones usando la maximización de la probabilidad.
¿Qué es la maximización de la probabilidad?
Intentarmos calcular la probabilidad de cada posible transición:
Rain -> Sun
Rain -> Rain
Sun -> Rain
Sun -> Sun
Para calcular estas probabilidades, muestreamos una secuencia de transiciones y calculamos la probabilidad de la transición entre cada estado basándonos en los datos muestreados. Esta es la matriz de transiciones.
Realizamos el cálculo "a mano" y luego usaremos el código en model_probabilities.py.
Dispones del enunciado de este ejercicio en este vídeo:
y de la solución en este otro:
si estás logueado con la cuenta del módulo de MIA.
La secuencia de observaciones es:
Contamos "a mano" el número de transiciones que se presentan en las observaciones y las expresamos en términos de probabilidad condicionada
Probabilidad inicial:
-
$P(R_0) = 1$ pues la secuencia de observaciones comienza en$R$ .
Las probabilidades de transición desde
-
$P(S|S) = 1/4 = 0.25$ pues observamos 4 dias soleados y sólo 1 en el que el siguiente es soleado. -
$P(R|S) = 3/4 = 0.75$ pues observamos 4 dias soleados y 3 en el que el siguiente es lluvioso.
Las probabilidades de transición desde
-
$P(S|R) = 3/6 = 0.5$ pues observamos 6 dias lluviosos y 3 transiciones a día soleado. -
$P(R|R) = 3/6 = 0.5$ pues observamos 6 dias lluviosos y 3 transiciones a día lluvioso.
La matriz de transiciones sería, por tanto:
o lo que es lo mismo:
Hoy | Mañana | |
---|---|---|
sol | lluvia | |
sol | 0.25 | 0.75 |
lluvia | 0.5 | 0.5 |
Consulta el código en model_probabilities.py.
Expresamos las observaciones:
R R S S R S R S R R
como un tensor:
samples = [ [[1], [1]],
[[1], [1]],
[[1], [0]],
[[0], [0]],
[[0], [1]],
[[1], [0]],
[[0], [1]],
[[1], [0]],
[[0], [1]],
[[1], [1]]]
X = torch.tensor(samples)
Establecemos la dependencia únicamente al estado anterior k=1
:
model_ejercicio = MarkovChain(k=1)
model_ejercicio.fit(X)
Las probabilidades iniciales o Categorical son:
model_ejercicio.distributions[0].probs[0]
>>> tensor([0.4000, 0.6000])
y la matriz de transición o probabilidades condicionadas son:
model_ejercicio.distributions[1].probs[0]
>>> tensor([[0.2500, 0.7500],
[0.5000, 0.5000]])
que coincide con la matriz de transiciones calculada anteriormente "a mano":
Dado el vector
Consideremos una cadena de Markov con $ s_1, ..., s_k $ posibles estados en los que la cadena puede estar en el tiempo de observación inicial
Para
Supongamos que en nuestro ejemplo del clima, disponemos de las probabilidades de que el primer día de la serie sea soleado o nublado. Podemos expresarlas en un vector de probailidades iniciales de la forma:
En nuestro caso:
El vector de probabilidades iniciales
Si las probabilidades de los diversos estados en el instante
Vamos a calcular estas probabilidades en nuestro ejemplo.
Dado el vector de probailidades iniciales:
y la matriz de transición:
las probabilidades del segundo día de la serie son:
Para este cálculo podemos hacer uso de la librería pytorch según vemos en el script model_stationary.py
o en model_stationary_markov_chain
.
# vector de probabilidades iniciales
v = torch.tensor([[0.5, 0.5]])
# matriz de transicion
P = torch.tensor([
[0.8, 0.2],
[0.4, 0.6]
])
# Probabilidades en el segundo dia de la serie
w = torch.matmul(v, P)
# w = tensor([[0.6000, 0.4000]])
La probabilidad de que el segundo dia de la serie sea soleado es
Observa cómo se satisface el axioma de la teoría de la probabilidad que establece que la probabilidad total del conjunto de los posibles estados es
# Probabilidades en el tercer dia de la serie
u = torch.matmul(w, P)
# tensor([[0.6400, 0.3600]])
# Probabilidades en el cuarto dia de la serie
t = torch.matmul(u, P)
# t = tensor([[0.6560, 0.3440]])
En los scripts model_robot_0x.py
encontrarás el código correspondiente a una cadena de Markov estacionaria que modela el posible movimiento de un robot aspirador en una vivienda como la siguiente:
Se plantean 6 diferentes supuestos en función de la distribución de la probabilidad inicial y de las probabilidades de transición entre las habitaciones (estados).
Describimos el caso model_robot_06
Disponemos de una vivienda en la que hay 6 habitaciones. El espacio de estados es, por tanto,
Se cumple la condición de Markov, pues el estado en
La probabilidad de transición del estado
y la matriz de transición es de la forma:
Dado el mapa de la vivienda, las probabilidades de transición quedan determinadas por los movimientos posibles entre las habitaciones comunicadas y la distribución de probabilidad que programemos en nuestro agente inteligente.
-
La probabilidad de transición entre habitaciones que no están directamente comunicadas es
$0$ . -
Supongamos que indicamos al robot que la probabilidad de permanecer en la misma habitación es de un 20% respecto al total de los posibles movimientos a las habitaciones adyacentes para abandonar esa habitación.
Realizamos los cálculos para la habitación 1. Distribuímos la probabilidad entre los posibles
Cálculo de las probabilidades de la matriz de transición:
Procediendo de igual modo con el resto de transiciones entre los estados
P = [[1/5, 2/5, 0, 2/5, 0, 0],
[2/5, 1/5, 2/5, 0, 0, 0],
[0, 2/5, 1/5, 0, 0, 2/5],
[2/5, 0, 0, 1/5, 2/5, 0],
[0, 0, 0, 4/5, 1/5, 0],
[0, 0, 4/5, 0, 0, 1/5]]
El vector de probabilidades en el instante inicial es el siguiente:
Como las probabilidades de transición son estacionarias, podemos calcular las probabilidades en el instante de tiempo
Repetimos este cálculo para calcular las probabilidades en los siguientes instantes.
En los scripts model_robot_0x.py
dispones de distintos ejemplos cambiando las distribuciones de probabilidades iniciales y de transición, y estableciendo el mapa de modo que las habitaciones adyacentes sean 1 - 2 - 4 y 3 - 5 - 6:
"A brief primer on Hidden Markov Models", Berkeley D-Lab, 3 de mayo de 2024. https://dlab.berkeley.edu/news/brief-primer-hidden-markov-models