Saltar al contenido

# procesos-estocasticos-discretos-simulacion-estados-y-tiempos-de-absorcion-con-pydtmc

Procesos Estocásticos Discretos: Simulación, Estados y Tiempos de Absorción con PyDTMC

Volver a la portada del curso
Lectura (Markdown)

Técnicas de Evaluación de Modelos de Markov

Sección 5 · Evaluación de Modelos

Técnicas de evaluación de modelos de Markov

Ajustar una cadena de Markov a datos siempre funciona: fit_sequence devuelve una matriz aunque los datos no tengan nada de markoviano. Por eso la evaluación tiene dos partes. Primero compruebas los supuestos (¿el proceso es de primer orden?, ¿la matriz es la misma en todo el periodo?). Después mides el desempeño fuera de muestra contra una línea base. Si alguna de las dos falla, los tiempos de absorción que calcules no son confiables.

Estimación por máxima verosimilitud

Dada una secuencia observada, el estimador de máxima verosimilitud de cada probabilidad es la proporción de transiciones observadas:

$$\hat p_{ij} = \frac{n_{ij}}{\sum_k n_{ik}}$$

donde $n_{ij}$ cuenta cuántas veces se pasó de $i$ a $j$. La log-verosimilitud de una secuencia es $\ell = \sum_t \log \hat p_{x_t x_{t+1}}$. Sirve para comparar modelos con los mismos datos: mayor $\ell$ por paso significa que el modelo predice mejor.

Pruebas de supuestos en PyDTMC

PyDTMC incluye pruebas de hipótesis basadas en $\chi^2$. Todas devuelven una tupla (rechaza, p_valor, detalle). rechaza=True significa que se rechaza la hipótesis nula con la significancia indicada (0.05 por defecto).

  • assess_markov_property(estados, secuencia): la nula es que la secuencia cumple la propiedad de Markov.
  • assess_first_order(estados, secuencia): la nula es que un modelo de primer orden basta.
  • assess_homogeneity(estados, [seq1, seq2]): la nula es que varias secuencias vienen del mismo proceso. Sirve para comparar periodos o segmentos de clientes.
  • assess_theoretical_compatibility(modelo, secuencia): la nula es que la secuencia es compatible con una cadena dada. Úsala para validar un modelo ajustado contra datos nuevos.

Aplicación: validar un modelo de actividad de usuarios

Simulamos 3,000 días de un usuario con tres estados, separamos el 80% para ajustar y el 20% para probar:

from pydtmc import MarkovChain, assess_markov_property, assess_homogeneity
from pydtmc import assess_theoretical_compatibility

estados = ["Activo", "Ocasional", "Inactivo"]
real = MarkovChain([[0.80, 0.15, 0.05], [0.30, 0.50, 0.20],
                    [0.10, 0.20, 0.70]], estados)
seq = real.simulate(3000, initial_state="Activo", seed=42)
train, test = seq[:2400], seq[2400:]
modelo = MarkovChain.fit_sequence("mle", estados, train)
print(modelo.p.round(3))
print(assess_markov_property(estados, seq)[:2])            # (False, 0.984)
print(assess_homogeneity(estados, [train, test])[:2])      # (False, 0.74)
print(assess_theoretical_compatibility(modelo, test)[:2])  # (False, 0.949)

Ninguna prueba rechaza: la secuencia es markoviana, el proceso no cambió entre entrenamiento y prueba, y el modelo ajustado es compatible con los datos nuevos. La matriz estimada queda a menos de 0.02 de la real.

Desempeño fuera de muestra

Pasar las pruebas no basta; también tiene que predecir mejor que algo simple. Dos métricas fáciles sobre el conjunto de prueba:

  • Log-verosimilitud por paso contra un modelo que ignora el estado actual (frecuencias marginales). Aquí: $-0.774$ contra $-1.066$.
  • Exactitud del siguiente estado prediciendo el más probable de cada fila contra predecir siempre el estado más común. Aquí: 0.697 contra 0.453.

La mejora confirma que el estado actual sí contiene información. Si las dos métricas empatan, una cadena de Markov no aporta nada sobre un modelo de frecuencias.

Validar las cantidades que vas a reportar

Si tu objetivo son tiempos de absorción, evalúalos directamente. Calcula $t$ y $B$ con el modelo ajustado y compáralos con lo observado en trayectorias reales que ya terminaron (fracción que llegó a cada estado final, pasos promedio). Una diferencia grande indica que la matriz es correcta en promedio pero falla justo en lo que te interesa.

Trampas comunes

  • Leer al revés el primer valor. False no significa "el modelo falla"; significa que no hay evidencia para rechazar la nula.
  • Ceros estructurales. Si una transición nunca ocurre (por ejemplo, de Soleado a Lluvioso), varias pruebas devuelven (None, nan) porque la tabla de contingencia tiene celdas vacías. No es un error de tu código.
  • assess_stationarity casi nunca rechaza. En PyDTMC 9.0 compara proporciones por bloque en lugar de conteos; en nuestras pruebas no detectó ni un cambio total de matriz (p ≈ 1.0), mientras que assess_homogeneity con las dos mitades lo detectó con p = 0. Para buscar cambios de régimen, divide la secuencia y usa assess_homogeneity.
  • Evaluar con los mismos datos del ajuste. La compatibilidad con train siempre sale bien; usa datos que el modelo no vio.

Cierre

Antes de presentar cualquier tiempo de absorción, deja por escrito tres resultados: la prueba de propiedad de Markov, la prueba de homogeneidad entre periodos y la mejora fuera de muestra sobre una línea base. Si los tres salen bien, el modelo merece confianza.

Recursos