Aprendizagem-por-reforco-1 E CLIFF WALKING

Aplicando Aprendizagem por Reforço no Cliff Walking

O link do colab: https://drive.google.com/file/d/1lzpWH0d6OsrSHFcJWi3Lzw7idTja9lwo/view?usp=sharing

No post anterior comentei sobre alguns conceitos da aprendizagem por reforço, nesse, iremos aplicar os conceitos de forma prática, no Cliff Walking. Desvende os segredos do Aprendizado por Reforço e domine o desafio do Cliff Walking!

O “gymnasium” é o nome de uma biblioteca Python amplamente utilizada no campo do aprendizado por reforço. Ela fornece uma interface padronizada (API) para interagir com diferentes ambientes de simulação.

Veja como o Gymnasium funciona:

  • Ambientes de simulação: Imagine vários cenários virtuais para treinar agentes de aprendizado por reforço, como labirintos virtuais, jogos simples e simuladores de robótica. O Gymnasium define uma interface comum para esses ambientes.
  • Agente de aprendizado por reforço: É o algoritmo que interage com o ambiente, tomando decisões e aprendendo com as recompensas recebidas.
  • API padronizada: O Gymnasium age como um tradutor entre o agente e o ambiente. Ele permite que o agente use comandos uniformes para interagir com qualquer ambiente compatível com o Gymnasium, independentemente de sua complexidade interna.

Resumindo, o Gymnasium facilita o desenvolvimento de agentes de aprendizado por reforço ao fornecer uma interface única para diversos ambientes de simulação. Isso permite aos pesquisadores focar na lógica do agente sem se preocupar com os detalhes específicos de cada ambiente.

O Problema

Agente do jogo.

O jogo começa com o jogador na localização [3, 0] da grade mundial 4×12 com o gol localizado em [3, 11]. Se o jogador atingir a meta o episódio termina.

Um penhasco corre ao longo de [3, 1..10]. Se o jogador se mover para um local de penhasco, ele retornará ao local inicial.

O jogador faz movimentos até atingir o objetivo.

Adaptado do Exemplo 6.6 (página 132) de Reinforcement Learning: An Introduction de Sutton e Barto

Ações possíveis:

  • 0: Subir
  • 1: Mover para a direita
  • 2: Mover para baixo
  • 3: Mover para a esquerda

Para vermos o gymnasium funcionando, podemos fazer algumas jogadas de forma aleatória, e salvar um gif do jogo renderizado.

# Nesse código, iremos explorar os retornos da lib Gymnasium, antes de uma aplicação objetiva.

import gymnasium as gym
import random
import imageio
from IPython.display import Image
import numpy as np
import matplotlib.pyplot as plt
from argparse import Namespace
from tqdm.notebook import tqdm


env = gym.make('CliffWalking-v0', render_mode="rgb_array") # importando o CliffWalking
env.reset()
images = []
actions_ = {
    0: "Subir",
    1: "direita",
    2:"baixo",
    3:"esquerda"
}
for i in range(100):
  random_action = env.action_space.sample() # Ações aleatórias
  new_state, reward, terminated, truncated, info = env.step(random_action)
  images.append(env.render()) # renderizando estado atual, para criar um gif.
  print(f'Açao escolhida: {actions_[random_action]} | posição: {new_state} | recompensa: {reward}') # exibindo as açoes em texto.
imageio.mimsave('/content/replay.gif', images, fps=1)
state, info = env.reset() # reiniciando o jogo para os próximos exemplos.

Aleatoriamente, ele irá fazer jogadas erradas, mas dessa forma, conseguimos entender de forma mínima como ele se comporta.

Agente andando aleatoriamente.

Q learning Implemetação

Passos Iniciais

  • Inicialziar a Q-Table com zeros.
  • Criar agente para:
    • Selecionar ação: Existindo uma tabela Q, um estado, e um épsilon ( parametro de exploração), se escolhe uma ação.
    • Fazer update na qTable: O aprendizado em si, ocorre com o registro das recompensas na tabela.
    • Atualziar Épsilon: Com o passar dos episódios, precisamos diminuir exploração, e focar no aperfeiçoamento do objetivo.
state_space = env.observation_space.n # 48  espaços
action_space = env.action_space.n # 4 açoes ( direita, esquerda, cima, baixo)

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

Agente

# Agente para jogar, e buscar a melhor ação
class CliffwalkingAgent:
    def __init__(self, args):
        self.args = args
        self.training_error = []


    def get_action(
        self,
        Qtable,
        state,
        epsilon
    ):
        if np.random.random() > epsilon:
            return np.argmax(Qtable[state][:])
        else:
            return env.action_space.sample()


    def update(
        self,
        Qtable,
        state,
        new_state,
        action
    ):
        td_target = reward + self.args.discount_factor * np.max(Qtable[new_state])
        td_error = td_target - Qtable[state][action]
        self.training_error.append(td_error)
        return Qtable[state][action] + self.args.learning_rate * td_error


    def decay_epsilon(
        self,
        episode
    ):
        exp_decay = np.exp(-self.args.decay_rate * episode)
        return self.args.min_epsilon + (self.args.max_epsilon - self.args.min_epsilon) * exp_decay

Função de treino



def train(n_training_episodes, max_steps, Qtable):
    envClif = gym.make('CliffWalking-v0', render_mode="rgb_array")
    agent = CliffwalkingAgent(configs)
    env = gym.wrappers.RecordEpisodeStatistics(envClif, deque_size=configs.n_training_episodes)

    for episode in tqdm(range(n_training_episodes)):
        # Reduce epsilon
        epsilon = agent.decay_epsilon(episode)
        # Reset the environment
        state, info = env.reset()
        step = 0
        terminated = False
        truncated = False


        # repeat
        for step in range(max_steps):
            # epsilon greedy policy
            action = agent.get_action(Qtable, state, epsilon)


            # Take action At and observe Rt+1 and St+1
            new_state, reward, terminated, truncated, info = env.step(action)


            # Update Q-value
            Qtable[state][action] = agent.update(Qtable, state, new_state, action)


            # If terminated or truncated end the episode
            if terminated or truncated:
                break


            state = new_state


    return Qtable, env, agent

Após algumas sessões de treinamento, o algoritmo tem um excelente desempenho, chegando bem próximo de zero na taxa de erros, e com poucos passos em cada episódio.

Gráfico de erros e duração dos episódios.

E temos um gif, dessa última rodada, com o agente jogando perfeitamente, sem precisar programar regras, ou ensina-lo. Apenas recompensando suas ações

Agente treinado, fazendo o melhor percurso.