Ir al contenido principal

Introducción a Q-learning: tutorial para principiantes

Conoce el algoritmo de aprendizaje por refuerzo sin modelo más popular con un tutorial en Python.
Actualizado 22 jul 2026  · 11 min leer

Explorar con IA

Abrir en ChatGPTAbrir en ClaudeAbrir en Perplexity

Q Learning Header

El aprendizaje por refuerzo (RL) es la parte del ecosistema del aprendizaje automático donde un agente aprende interactuando con el entorno para encontrar la estrategia óptima que le permita alcanzar sus objetivos. Es bastante distinto de los algoritmos supervisados, que requieren ingerir y procesar datos etiquetados. El aprendizaje por refuerzo no necesita datos de entrenamiento previos: aprende del propio entorno y de su sistema de recompensas para tomar mejores decisiones.

Por ejemplo, en el videojuego de Mario, si el personaje realiza una acción aleatoria (p. ej., moverse a la izquierda), en función de esa acción puede recibir una recompensa. Tras actuar, el agente (Mario) pasa a un nuevo estado, y el proceso se repite hasta que llega al final de la fase o muere.

Este episodio se repite muchas veces hasta que Mario aprende a moverse por el entorno maximizando las recompensas.

Reinforcement Learning

Imagen del autor

Podemos descomponer el aprendizaje por refuerzo en cinco pasos sencillos:

  1. El agente parte de un estado cero en un entorno.
  2. Toma una acción siguiendo una estrategia concreta.
  3. Recibe una recompensa o un castigo según esa acción.
  4. Aprende de los movimientos previos y va optimizando la estrategia.
  5. El proceso se repite hasta encontrar una estrategia óptima.

Descubre más en nuestro tutorial, una introducción al aprendizaje por refuerzo. Verás con ejemplos de código cómo funciona el aprendizaje por refuerzo.

En este tutorial, aprenderás qué es Q-learning y por qué necesitamos Deep Q-learning. Además, crearemos y entrenaremos algoritmos de Q-learning desde cero usando Numpy y Gymnasium.

Nota: si estás empezando en machine learning, te recomendamos el itinerario Machine Learning Scientist with Python para entender mejor el aprendizaje por refuerzo y Q-learning.

Conviértete en un Científico ML

Mejora tus conocimientos de Python para convertirte en un científico del aprendizaje automático.
Empieza a Aprender Gratis

¿Qué es Q-learning?

Q-learning es un algoritmo sin modelo, basado en valores y off-policy que encuentra la mejor secuencia de acciones según el estado actual del agente. La "Q" viene de quality (calidad). La calidad representa lo valiosa que es una acción para maximizar recompensas futuras.

Los algoritmos con modelo usan funciones de transición y recompensa para estimar la política óptima y construir el modelo. En cambio, los algoritmos sin modelo aprenden las consecuencias de sus acciones a partir de la experiencia, sin funciones explícitas de transición y recompensa.

El método basado en valores entrena una función de valor para aprender qué estados son más valiosos y, a partir de ahí, decidir. Por otro lado, los métodos basados en políticas entrenan directamente la política para aprender qué acción tomar en cada estado.

En los métodos off-policy, el algoritmo evalúa y actualiza una política distinta de la que usa para actuar. Por el contrario, un algoritmo on-policy evalúa y mejora la misma política con la que actúa.

Terminología clave en Q-learning

Antes de ver cómo funciona Q-learning, conviene aclarar algunos términos para entender sus fundamentos.

  • States (s): la posición o situación actual del agente en el entorno.
  • Action (a): un paso que da el agente en un estado concreto.
  • Rewards: por cada acción, el agente recibe una recompensa o una penalización.
  • Episodes: final de la fase, cuando el agente ya no puede actuar. Ocurre al lograr el objetivo o fallar.
  • Q(St+1, a): valor Q óptimo esperado de realizar la acción a en un estado dado.
  • Q(St, At): estimación actual de Q(St+1, a).
  • Q-Table: tabla que mantiene el agente con los conjuntos de estados y acciones.
  • Temporal Differences (TD): técnica para estimar el valor esperado de Q(St+1, a) usando estado y acción actuales y anteriores.

¿Cómo funciona Q-learning?

Vamos a verlo con el ejemplo del lago helado. En este entorno, el agente debe cruzar el lago desde el inicio hasta la meta sin caer en los agujeros. La mejor estrategia es llegar a la meta por el camino más corto.

Q-Learning Visualization

Gif del autor

Q-table

El agente usa una Q-table para elegir la mejor acción posible según la recompensa esperada en cada estado del entorno. En pocas palabras, una Q-table es una estructura de datos con estados y acciones, y el algoritmo de Q-learning se encarga de actualizar sus valores.

Función Q

La función Q usa la ecuación de Bellman y toma como entrada el estado (s) y la acción (a). La ecuación simplifica el cálculo del valor de estado y del valor estado-acción.Bellman Equation

Imagen de freecodecamp.org

Algoritmo de Q-learning

Q-Learning Process

Imagen del autor

Inicializar la Q-table

Primero inicializamos la Q-table. La construiremos con columnas según el número de acciones y filas según el número de estados.

En nuestro ejemplo, el personaje puede moverse arriba, abajo, izquierda y derecha. Tenemos cuatro acciones posibles y cuatro estados (inicio, inactivo, camino erróneo y final). También puedes considerar el camino erróneo como caer en un agujero. Inicializaremos la Q-table con valores a 0.

Q-Table 1

Imagen del autor

Elegir una acción

El segundo paso es simple. Al principio, el agente tomará una acción aleatoria (abajo o derecha) y, en la segunda pasada, usará la Q-table actualizada para seleccionar la acción.

Ejecutar la acción

Elegir y ejecutar acciones se repetirá muchas veces hasta que termine el bucle de entrenamiento. La primera acción y estado se seleccionan usando la Q-table. En nuestro caso, todos los valores empiezan en cero.

Después, el agente se moverá hacia abajo y actualizará la Q-table con la ecuación de Bellman. Con cada movimiento, iremos actualizando los valores de la Q-table y usándolos para decidir el mejor curso de acción.

Al principio, el agente está en modo exploración y elige acciones aleatorias para conocer el entorno. La estrategia epsilon-greedy es una forma sencilla de equilibrar exploración y explotación. Epsilon representa la probabilidad de explorar; cuando disminuye, aumenta la explotación.

Al inicio, epsilon es alto, es decir, el agente explora. A medida que explora el entorno, epsilon disminuye y el agente empieza a explotar lo aprendido. Con cada iteración durante la exploración, el agente gana confianza al estimar los valores Q.

Q-Table 2

Imagen del autor

En el lago helado, el agente desconoce el entorno, así que comienza con una acción aleatoria (moverse abajo). Como se ve en la imagen, la Q-table se actualiza con la ecuación de Bellman.

Medir las recompensas

Tras actuar, medimos el resultado y la recompensa.

  • La recompensa por llegar a la meta es +1
  • La recompensa por tomar un camino erróneo (caer en un agujero) es 0
  • La recompensa por estar inactivo o moverte por el lago helado también es 0.

Actualizar la Q-table

Actualizaremos la función Q(St, At) usando la ecuación. Emplea los valores Q estimados en el episodio anterior, la tasa de aprendizaje y el error de diferencias temporales (TD). El error TD se calcula con la recompensa inmediata, la recompensa futura máxima esperada con descuento y la estimación previa del valor Q.

El proceso se repite muchas veces hasta actualizar la Q-table y maximizar la función de valor Q.

Q-learning equation

Imagen del autor | Visualización de la ecuación por Thomas Simonini

Al principio, el agente explora el entorno para actualizar la Q-table. Cuando la Q-table ya está informada, el agente pasa a explotar y empieza a tomar mejores decisiones.Q-Table 3

Imagen del autor

En el caso del lago helado, el agente aprenderá a tomar el camino más corto hasta la meta evitando los agujeros.

Tutorial de Q-learning en Python

En esta sección, construiremos nuestro modelo de Q-learning desde cero usando el entorno Gymnasium, Pygame y Numpy. El tutorial en Python es una versión adaptada del Notebook de Thomas Simonini. Incluye inicializar el entorno y la Q-table, definir la política greedy, fijar hiperparámetros, crear y ejecutar el bucle de entrenamiento y la evaluación, y visualizar resultados.

Si tienes problemas al crear y ejecutar tu bucle de entrenamiento, puedes consultar el código fuente con la salida.

Puesta en marcha

Configurar una pantalla virtual

Primero instalaremos las dependencias para generar un vídeo de repetición (gif). Necesitamos una pantalla virtual (pyvirtualdisplay) para renderizar el entorno y grabar los fotogramas.

Nota: usando %%capture suprimimos la salida de la celda de Jupyter.

%%capture
!pip install pyglet==1.5.1
!apt install python-opengl
!apt install ffmpeg
!apt install xvfb
!pip3 install pyvirtualdisplay

# Virtual display
from pyvirtualdisplay import Display

virtual_display = Display(visible=0, size=(1400, 900))
virtual_display.start()

Instalar dependencias

Ahora instalaremos las dependencias que nos ayudarán a crear, ejecutar y evaluar el bucle de entrenamiento.

  • gymnasium: para inicializar el entorno FrozenLake-v1.
  • pygame: para la interfaz de FrozenLake-v1.
  • numpy: para crear y manejar la Q-table.
%%capture
!pip install gymnasium
!pip install pygame
!pip install numpy

!pip install imageio imageio_ffmpeg

Importar paquetes

Importamos ahora las librerías necesarias.

  • Imageio se usa para crear la animación.
  • tqdm se usa para las barras de progreso.
import numpy as np
import gymnasium as gym
import random
import imageio
from tqdm.notebook import trange

Entorno Frozen Lake de Gymnasium

Vamos a crear un entorno 4x4 sin deslizamiento usando la librería Frozen Lake de Gymnasium.

  • Hay dos versiones de la cuadrícula: "4x4" y "8x8".
  • Si is_slippery=True, el agente puede no moverse en la dirección deseada por la naturaleza resbaladiza del lago.

Tras inicializar el entorno, haremos un análisis del mismo.

env = gym.make("FrozenLake-v1",map_name="4x4",is_slippery=False)

print("Observation Space", env.observation_space)
print("Sample observation", env.observation_space.sample()) # display a random observation

Hay 16 espacios únicos en el entorno que se muestran en posiciones aleatorias.

Observation Space Discrete(16)
Sample observation 15

Vamos a ver cuántas acciones hay y a mostrar una acción aleatoria.

Espacio de acciones:

  • 0: moverse a la izquierda
  • 1: moverse hacia abajo
  • 2: moverse a la derecha
  • 3: moverse hacia arriba

Función de recompensa:

  • Alcanzar la meta: +1
  • Caer en un agujero: 0
  • Permanecer sobre el lago helado: 0
print("Action Space Shape", env.action_space.n)
print("Action Space Sample", env.action_space.sample())
Action Space Shape 4
Action Space Sample 1

Crear e inicializar la Q-table

La Q-table tiene las acciones como columnas y los estados como filas. Podemos usar Gymnasium para obtener el espacio de acciones y el de estados y, con ello, crear la Q-table.

state_space = env.observation_space.n
print("There are ", state_space, " possible states")

action_space = env.action_space.n
print("There are ", action_space, " possible actions")
There are  16  possible states
There are  4  possible actions

Para inicializar la Q-table, crearemos un array de Numpy con los espacios de estados y acciones. Será una matriz de 16 x 4.

def initialize_q_table(state_space, action_space):
  Qtable = np.zeros((state_space, action_space))
  return Qtable

Qtable_frozenlake = initialize_q_table(state_space, action_space)

Política epsilon-greedy

En la sección anterior vimos la estrategia epsilon-greedy, que gestiona el equilibrio entre exploración y explotación. Con probabilidad 1 - ɛ explotamos, y con probabilidad ɛ exploramos.

En epsilon_greedy_policy haremos lo siguiente:

  1. Generar un número aleatorio entre 0 y 1.
  2. Si el número es mayor que epsilon, explotamos: el agente toma la acción con mayor valor dado un estado.
  3. En caso contrario, exploramos (acción aleatoria).
def epsilon_greedy_policy(Qtable, state, epsilon):
  random_int = random.uniform(0,1)
  if random_int > epsilon:
    action = np.argmax(Qtable[state])
  else:
    action = env.action_space.sample()
  return action

Definir la política greedy

Q-learning es un algoritmo off-policy, es decir, la política con la que actúa y la que se usa para actualizar la función son distintas.

En este ejemplo, la política epsilon-greedy es la política de actuación, y la política greedy es la de actualización.

La política greedy también será la final cuando el agente haya sido entrenado. Selecciona el mayor valor estado-acción de la Q-table.

def greedy_policy(Qtable, state):
  action = np.argmax(Qtable[state])
  return action

Hiperparámetros del modelo

Estos hiperparámetros se usan en el bucle de entrenamiento; ajustarlos bien te dará mejores resultados.

El agente necesita explorar suficiente espacio de estados para aprender buenas aproximaciones de valor; por eso usamos una disminución progresiva de epsilon. Si la tasa de decaimiento es alta, el agente puede quedarse atascado por no haber explorado lo bastante.

  • Hay 10.000 episodios de entrenamiento y 100 de evaluación.
  • La tasa de aprendizaje es 0,7.
  • Usamos "FrozenLake-v1" con 99 pasos máximos por episodio.
  • El gamma (factor de descuento) es 0,95.
  • eval_seed: semilla de evaluación para el entorno.
  • La probabilidad epsilon de exploración inicial es 1,0 y la mínima será 0,05.
  • La tasa de decaimiento exponencial de epsilon es 0,0005.
# Training parameters
n_training_episodes = 10000
learning_rate = 0.7        

# Evaluation parameters
n_eval_episodes = 100      

# Environment parameters
env_id = "FrozenLake-v1"   
max_steps = 99             
gamma = 0.95               
eval_seed = []             

# Exploration parameters
max_epsilon = 1.0           
min_epsilon = 0.05           
decay_rate = 0.0005           

Entrenamiento del modelo

En el bucle de entrenamiento vamos a:

  1. Crear un bucle de episodios de entrenamiento.
  2. Reducir epsilon: con cada episodio necesitamos menos exploración y más explotación.
  3. Reiniciar el entorno.
  4. Crear un bucle anidado para el número máximo de pasos.
  5. Elegir la acción con la política epsilon-greedy.
  6. Tomar la acción (At) y observar la recompensa esperada (Rt+1) y el estado (St+1).
  7. Tomar la acción (a) y observar el nuevo estado (s') y la recompensa (r).
  8. Actualizar la función Q con la fórmula.
  9. Si done = True, terminar el episodio y salir del bucle.
  10. Cambiar el estado actual por el nuevo estado.
  11. Al finalizar todos los episodios de entrenamiento, la función devuelve la Q-table actualizada.
def train(n_training_episodes, min_epsilon, max_epsilon, decay_rate, env, max_steps, Qtable):
  for episode in trange(n_training_episodes):
 
    epsilon = min_epsilon + (max_epsilon - min_epsilon)*np.exp(-decay_rate*episode)
    # Reset the environment
    state = env.reset()
    step = 0
    done = False

    # repeat
    for step in range(max_steps):
   
      action = epsilon_greedy_policy(Qtable, state, epsilon)

   
      new_state, reward, done, info = env.step(action)

   
      Qtable[state][action] = Qtable[state][action] + learning_rate * (reward + gamma * np.max(Qtable[new_state]) - Qtable[state][action])

      # If done, finish the episode
      if done:
        break
     
      # Our state is the new state
      state = new_state
  return Qtable

Tardamos 3 segundos en completar 10.000 episodios de entrenamiento.

Qtable_frozenlake = train(n_training_episodes, min_epsilon, max_epsilon, decay_rate, env, max_steps, Qtable_frozenlake)

Training Episodes Outcome

Como se aprecia, la Q-table entrenada ya tiene valores y el agente los usará para navegar por el entorno y alcanzar la meta.

Qtable_frozenlake
array([[0.73509189, 0.77378094, 0.77378094, 0.73509189],
      [0.73509189, 0.        , 0.81450625, 0.77378094],
      [0.77378094, 0.857375  , 0.77378094, 0.81450625],
      [0.81450625, 0.        , 0.77378094, 0.77378094],
      [0.77378094, 0.81450625, 0.        , 0.73509189],
      [0.        , 0.        , 0.        , 0.        ],
      [0.        , 0.9025    , 0.        , 0.81450625],
      [0.        , 0.        , 0.        , 0.        ],
      [0.81450625, 0.        , 0.857375  , 0.77378094],
      [0.81450625, 0.9025    , 0.9025    , 0.        ],
      [0.857375  , 0.95      , 0.        , 0.857375  ],
      [0.        , 0.        , 0.        , 0.        ],
      [0.        , 0.        , 0.        , 0.        ],
      [0.        , 0.9025    , 0.95      , 0.857375  ],
      [0.9025    , 0.95      , 1.        , 0.9025    ],
      [0.        , 0.        , 0.        , 0.        ]])

Evaluación

La función evaluate_agent se ejecuta durante n_eval_episodes episodios y devuelve la media y la desviación estándar de la recompensa.

  1. En el bucle, primero comprobamos si hay semilla de evaluación. Si no, reiniciamos sin semilla.
  2. El bucle interno corre hasta max_steps.
  3. El agente toma, usando la Q-table, la acción con la mayor recompensa futura esperada en el estado dado.
  4. Calculamos la recompensa.
  5. Cambiamos el estado.
  6. Si termina (el agente cae en un agujero o llega a la meta), salimos del bucle.
  7. Guardamos los resultados.
  8. Al final, calculamos media y desviación estándar.
def evaluate_agent(env, max_steps, n_eval_episodes, Q, seed):

  episode_rewards = []
  for episode in range(n_eval_episodes):
    if seed:
      state = env.reset(seed=seed[episode])
    else:
      state = env.reset()
    step = 0
    done = False
    total_rewards_ep = 0
   
    for step in range(max_steps):
      # Take the action (index) that have the maximum reward
      action = np.argmax(Q[state][:])
      new_state, reward, done, info = env.step(action)
      total_rewards_ep += reward
       
      if done:
        break
      state = new_state
    episode_rewards.append(total_rewards_ep)
  mean_reward = np.mean(episode_rewards)
  std_reward = np.std(episode_rewards)

  return mean_reward, std_reward

Como ves, obtuvimos la puntuación perfecta con desviación estándar cero. Significa que nuestro agente alcanzó la meta en los 100 episodios.

# Evaluate our Agent
mean_reward, std_reward = evaluate_agent(env, max_steps, n_eval_episodes, Qtable_frozenlake, eval_seed)
print(f"Mean_reward={mean_reward:.2f} +/- {std_reward:.2f}")
Mean_reward=1.00 +/- 0.00

Visualizar el resultado

Hasta ahora hemos estado trabajando con números. Para la demo, vamos a crear un gif animado del agente desde el inicio hasta que alcanza la meta.

  1. Primero creamos el estado reiniciando el entorno con un entero aleatorio entre 0 y 500.
  2. Renderizamos el entorno con rdb_array para crear un array de imagen.
  3. Añadimos img al array images.
  4. En el bucle, daremos pasos usando la Q-table y renderizaremos la imagen en cada paso.
  5. Al final, usamos este array e imageio para crear un gif de un fotograma por segundo.
def record_video(env, Qtable, out_directory, fps=1):
  images = [] 
  done = False
  state = env.reset(seed=random.randint(0,500))
  img = env.render(mode='rgb_array')
  images.append(img)
  while not done:
    # Take the action (index) that have the maximum expected future reward given that state
    action = np.argmax(Qtable[state][:])
    state, reward, done, info = env.step(action) # We directly put next_state = state for recording logic
    img = env.render(mode='rgb_array')
    images.append(img)
  imageio.mimsave(out_directory, [np.array(img) for i, img in enumerate(images)], fps=fps)

Si estás en un cuaderno de Jupyter, puedes mostrar el gif con la función Image de IPython.display.

video_path="/content/replay.gif"
video_fps=1
record_video(env, Qtable_frozenlake, video_path, video_fps)

from IPython.display import Image
Image('./replay.gif')

Ahora puedes compartir estos resultados con tu equipo y compañeros de clase o publicarlos en redes sociales.

Obtén una certificación superior en IA

Demuestra que puedes utilizar la IA de forma eficaz y responsable.

Preguntas frecuentes sobre Q-learning

¿Cuál es la desventaja de Q-learning?

El proceso de aprendizaje en Q-learning es costoso para el agente, sobre todo al principio. ¿Por qué? Para converger a la política óptima, cada par estado-acción debe visitarse con frecuencia.

¿Por qué se llama Q-learning?

En Q-learning, la "Q" significa quality (calidad). Representa lo útil que es una acción para obtener recompensas futuras y se usa para crear un mapa de estados y acciones que maximice las recompensas esperadas.

¿Por qué Q-learning es off-policy?

En Q-learning, la política que se actualiza es distinta de la política de comportamiento (la que usa para actuar); por eso se llama un algoritmo off-policy.

¿Q-learning siempre converge?

Sí. Durante el entrenamiento, el algoritmo converge siempre a la política óptima.

¿Por qué necesitamos deep Q-learning?

Q-learning es un algoritmo sencillo pensado para entornos pequeños y discretos. En un entorno grande, necesitaríamos una Q-table enorme de estados y acciones que consumiría mucha memoria y cómputo para entrenar. Deep Q-learning, en cambio, sustituye la Q-table por una red neuronal para manejar entornos grandes con acciones y estados continuos.

Temas

Cursos de machine learning

Curso

Diseño de flujos de trabajo de Machine Learning en Python

4 h
12.6K
Aprende a crear procesos que resistan el paso del tiempo.
Ver detallesRight Arrow
Iniciar Curso
Ver másRight Arrow
Relacionado

Tutorial

Aprendizaje automático de datos categóricos con el tutorial de Python

Aprenda los trucos más comunes para manejar datos categóricos y preprocesarlos para construir modelos de aprendizaje automático.
Moez Ali's photo

Moez Ali

Tutorial

Tutorial del Optimizador Adam: Intuición e implementación en Python

Comprender y aplicar el optimizador Adam en Python. Aprende la intuición, las matemáticas y las aplicaciones prácticas del aprendizaje automático con PyTorch
Bex Tuychiev's photo

Bex Tuychiev

Tutorial

Tutorial sobre el uso de XGBoost en Python

Descubre la potencia de XGBoost, uno de los marcos de machine learning más populares entre los científicos de datos, con este tutorial paso a paso en Python.
Bekhruz Tuychiev's photo

Bekhruz Tuychiev

Python

Tutorial

Comprender la regresión logística en el tutorial de Python

Aprende sobre la regresión logística, sus propiedades básicas, y construye un modelo de machine learning sobre una aplicación del mundo real en Python.
Avinash Navlani's photo

Avinash Navlani

Clustering k-means

Tutorial

Introducción a k-Means Clustering con scikit-learn en Python

En este tutorial, aprenda a aplicar k-Means Clustering con scikit-learn en Python

Kevin Babitz

Tutorial

Guía para principiantes de la API de OpenAI: Tutorial práctico y prácticas recomendadas

Este tutorial te presenta la API de OpenAI, sus casos de uso, un enfoque práctico para utilizar la API y todas las prácticas recomendadas que debes seguir.
Arunn Thevapalan's photo

Arunn Thevapalan

Ver MásVer Más