Cadenas de Markov y el dilema exploración-explotación en Python
La IA a menudo tiene que actuar con incertidumbre. Una cadena de Markov modela cómo un sistema pasa de un estado a otro con probabilidades fijas, y un bandido multibrazo muestra la decisión central del aprendizaje por refuerzo: probar algo nuevo o usar lo que mejor ha funcionado hasta ahora.
El concepto en palabras sencillas
La IA a menudo tiene que actuar con incertidumbre. Una cadena de Markov modela cómo un sistema pasa de un estado a otro con probabilidades fijas, y un bandido multibrazo muestra la decisión central del aprendizaje por refuerzo: probar algo nuevo o usar lo que mejor ha funcionado hasta ahora.
Predice estados futuros con una cadena de Markov y equilibra exploración y explotación con un bandido epsilon-greedy.
Ideas clave
- En una cadena de Markov, el siguiente estado solo depende del estado actual.
- Las probabilidades de transición que salen de un estado siempre suman 1.
- Explorar encuentra mejores opciones; explotar obtiene recompensas con la mejor opción conocida.
- Epsilon controla el equilibrio: cuanto mayor es, más se explora.
¿Cuándo se utiliza?
- Entender qué pasa dentro de las redes neuronales y las bibliotecas de IA.
- Aprender la idea antes de implementarla en los retos correspondientes.
- Prepararte para cursos de aprendizaje automático, entrevistas y proyectos.
Pruébalo en acción
Cambia las probabilidades de transición del tiempo para ver dónde se estabiliza la cadena. Pulsa Reproducir para que el bandido aprenda qué máquina paga más.
Código de ejemplo
import random
# Markov chain: tomorrow's weather depends only on today's.
transitions = {"sunny": {"sunny": 0.8, "rainy": 0.2}, "rainy": {"sunny": 0.4, "rainy": 0.6}}
dist = {"sunny": 1.0, "rainy": 0.0}
for day in range(1, 4):
dist = {s: sum(dist[p] * transitions[p][s] for p in dist) for s in dist}
print(f"day {day}:", {s: round(v, 3) for s, v in dist.items()})
# Epsilon-greedy bandit: usually pick the best arm so far, sometimes explore.
random.seed(1)
true_payouts = [0.3, 0.7]
counts, totals = [0, 0], [0.0, 0.0]
epsilon = 0.1
for _ in range(500):
if random.random() < epsilon or 0 in counts:
arm = random.randrange(2) # explore
else:
arm = max(range(2), key=lambda a: totals[a] / counts[a]) # exploit
reward = 1 if random.random() < true_payouts[arm] else 0
counts[arm] += 1
totals[arm] += reward
print("pulls per arm:", counts)
print("estimated payouts:", [round(t / c, 2) for t, c in zip(totals, counts)])
Resultado esperado
day 1: {'sunny': 0.8, 'rainy': 0.2}
day 2: {'sunny': 0.72, 'rainy': 0.28}
day 3: {'sunny': 0.688, 'rainy': 0.312}
pulls per arm: [25, 475]
estimated payouts: [0.16, 0.7]
Cómo funciona
Cada día, las nuevas probabilidades son las anteriores multiplicadas por las probabilidades de transición, así que «soleado» baja de 1.0 a 0.688 en tres días. El bandido elige un brazo al azar el 10 % de las veces y, si no, tira del brazo con mejor media hasta el momento; pronto dedica la mayoría de tiradas al mejor brazo y estima su premio en torno a 0.7.
Cambia los valores y ejecuta el programa en el compilador Python online de CodeUtility sin instalar Python.
Ejercicios prácticos
Modifica las entradas y prueba casos límite antes de usar conjuntos de datos mayores.
- Cambia las entradas o los pesos y predice la salida antes de ejecutar.
- Imprime los valores intermedios para seguir cada paso del cálculo.
- Resuelve los retos enlazados abajo para implementar la idea por tu cuenta.
Practica con un reto
Usa lo que cubre esta lección para resolver un problema real. Cada reto se ejecuta en el navegador, con pruebas al instante y una revisión de IA.
- Distribución de estados de una cadena de Markov Propaga una distribución de probabilidad a través de la matriz de transición de una cadena de Markov durante varios pasos. Fácil
- Bandido multibrazo epsilon-greedy Equilibra exploración y explotación en un bandido multibrazo con selección de acciones epsilon-greedy. Fácil