El aprendizaje por refuerzo (RL, por sus siglas en inglés) es un área del aprendizaje automático donde un agente aprende a tomar decisiones mediante la interacción con un entorno. En este módulo, exploraremos cómo implementar algoritmos de aprendizaje por refuerzo utilizando PyTorch.

Contenido

Introducción al Aprendizaje por Refuerzo

El aprendizaje por refuerzo se basa en la idea de que un agente aprende a tomar acciones en un entorno para maximizar una recompensa acumulada. Los componentes clave son:

  • Agente: El aprendiz o tomador de decisiones.
  • Entorno: Todo lo que el agente interactúa con.
  • Acción: Lo que el agente puede hacer.
  • Estado: La situación actual del entorno.
  • Recompensa: La retroalimentación del entorno como resultado de una acción.

Conceptos Clave

  • Política (π): Estrategia que el agente sigue para decidir qué acción tomar en un estado dado.
  • Función de Valor (V): Valor esperado de las recompensas acumuladas a partir de un estado.
  • Función Q (Q): Valor esperado de las recompensas acumuladas a partir de un estado y una acción.

Configuración del Entorno

Antes de comenzar, asegúrate de tener PyTorch y las bibliotecas necesarias instaladas. Puedes instalar las dependencias con:

pip install torch gym numpy

Implementación de un Agente RL

Vamos a implementar un agente utilizando el algoritmo Q-Learning, uno de los algoritmos más simples y populares en RL.

Paso 1: Importar Bibliotecas

import gym
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np

Paso 2: Definir la Red Neuronal

Definimos una red neuronal simple para aproximar la función Q.

class QNetwork(nn.Module):
    def __init__(self, state_size, action_size):
        super(QNetwork, self).__init__()
        self.fc1 = nn.Linear(state_size, 64)
        self.fc2 = nn.Linear(64, 64)
        self.fc3 = nn.Linear(64, action_size)
    
    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        x = self.fc3(x)
        return x

Paso 3: Definir el Agente

class Agent:
    def __init__(self, state_size, action_size, lr=0.001, gamma=0.99, epsilon=1.0, epsilon_decay=0.995, epsilon_min=0.01):
        self.state_size = state_size
        self.action_size = action_size
        self.gamma = gamma
        self.epsilon = epsilon
        self.epsilon_decay = epsilon_decay
        self.epsilon_min = epsilon_min
        self.qnetwork = QNetwork(state_size, action_size)
        self.optimizer = optim.Adam(self.qnetwork.parameters(), lr=lr)
        self.criterion = nn.MSELoss()
    
    def act(self, state):
        if np.random.rand() <= self.epsilon:
            return np.random.choice(self.action_size)
        state = torch.FloatTensor(state).unsqueeze(0)
        with torch.no_grad():
            q_values = self.qnetwork(state)
        return np.argmax(q_values.numpy())
    
    def learn(self, state, action, reward, next_state, done):
        state = torch.FloatTensor(state).unsqueeze(0)
        next_state = torch.FloatTensor(next_state).unsqueeze(0)
        reward = torch.FloatTensor([reward])
        action = torch.LongTensor([action])
        done = torch.FloatTensor([done])
        
        q_values = self.qnetwork(state)
        next_q_values = self.qnetwork(next_state)
        
        q_value = q_values.gather(1, action.unsqueeze(1)).squeeze(1)
        next_q_value = reward + (1 - done) * self.gamma * next_q_values.max(1)[0]
        
        loss = self.criterion(q_value, next_q_value.detach())
        self.optimizer.zero_grad()
        loss.backward()
        self.optimizer.step()
        
        if self.epsilon > self.epsilon_min:
            self.epsilon *= self.epsilon_decay

Entrenamiento del Agente

Paso 4: Entrenar el Agente

env = gym.make('CartPole-v1')
state_size = env.observation_space.shape[0]
action_size = env.action_space.n
agent = Agent(state_size, action_size)

episodes = 1000
for e in range(episodes):
    state = env.reset()
    total_reward = 0
    done = False
    while not done:
        action = agent.act(state)
        next_state, reward, done, _ = env.step(action)
        agent.learn(state, action, reward, next_state, done)
        state = next_state
        total_reward += reward
    print(f"Episode {e+1}/{episodes}, Total Reward: {total_reward}")

Evaluación del Agente

Paso 5: Evaluar el Agente

total_rewards = []
for e in range(100):
    state = env.reset()
    total_reward = 0
    done = False
    while not done:
        action = agent.act(state)
        state, reward, done, _ = env.step(action)
        total_reward += reward
    total_rewards.append(total_reward)
print(f"Average Reward over 100 episodes: {np.mean(total_rewards)}")

Ejercicio Práctico

Ejercicio 1: Modificar la Red Neuronal

Modifica la arquitectura de la red neuronal para mejorar el rendimiento del agente. Prueba diferentes números de capas y neuronas.

Ejercicio 2: Implementar DQN

Implementa el algoritmo Deep Q-Network (DQN) utilizando una red neuronal con experiencia de repetición (experience replay).

Ejercicio 3: Entrenar en un Entorno Diferente

Entrena el agente en un entorno diferente de OpenAI Gym, como MountainCar-v0.

Conclusión

En este módulo, hemos cubierto los conceptos básicos del aprendizaje por refuerzo y cómo implementar un agente simple utilizando PyTorch. Hemos visto cómo definir una red neuronal, entrenar al agente y evaluar su rendimiento. Los ejercicios prácticos proporcionan una oportunidad para profundizar en el tema y experimentar con diferentes enfoques.

En el siguiente módulo, exploraremos cómo desplegar modelos PyTorch en producción.

© Copyright 2024. Todos los derechos reservados