1
resposta

Aprendizado por Reforço em Marketing Digital

1. Configuração do Ambiente

!pip install gymnasium

import numpy as np
import gymnasium as gym
import random

# Inicializa o ambiente (mapa 4x4, versão não escorregadia para facilitar o aprendizado inicial)
env = gym.make("FrozenLake-v1", is_slippery=False, render_mode="ansi")

2. Hiperparâmetros e Q-Table
A Q-table é uma matriz onde as linhas são os estados (16 posições no gelo) e as colunas são as ações (Esquerda, Baixo, Direita, Cima).

# Inicializa a Q-table com zeros
state_size = env.observation_space.n
action_size = env.action_space.n
q_table = np.zeros((state_size, action_size))

# Hiperparâmetros
total_episodes = 2000        # Total de tentativas de treino
learning_rate = 0.1          # Alpha: o quanto o agente aceita a nova informação
gamma = 0.95                 # Gamma: importância das recompensas futuras (desconto)
epsilon = 1.0                # Epsilon: probabilidade inicial de explorar (agir ao acaso)
max_epsilon = 1.0
min_epsilon = 0.01
decay_rate = 0.005           # Taxa de decréscimo da exploração

3. Treinamento com Q-Learning
Aqui aplicamos a fórmula: $Q(s, a) = Q(s, a) + \alpha [R + \gamma \max Q(s', a') - Q(s, a)]$.

print("Treinando o agente...")

for episode in range(total_episodes):
    state, info = env.reset()
    step = 0
    terminated = False
    truncated = False

    for step in range(100):
        # Política Epsilon-Greedy (Explorar vs Explorar)
        if random.uniform(0, 1) < epsilon:
            action = env.action_space.sample() # Explora: ação aleatória
        else:
            action = np.argmax(q_table[state, :]) # Explota: melhor ação da Q-table

        # Executa a ação
        new_state, reward, terminated, truncated, info = env.step(action)

        # Atualiza a Q-table
        # Recompensa + (gamma * valor do melhor estado futuro) - valor atual
        q_table[state, action] = q_table[state, action] + learning_rate * (
            reward + gamma * np.max(q_table[new_state, :]) - q_table[state, action]
        )

        state = new_state
        
        if terminated or truncated:
            break

    # Reduz o Epsilon para o agente explorar menos com o passar do tempo
    epsilon = min_epsilon + (max_epsilon - min_epsilon) * np.exp(-decay_rate * episode)

print("Treinamento concluído!")

4. Avaliação do Desempenho
Agora testamos o que o agente aprendeu sem nenhuma aleatoriedade.

total_test_episodes = 100
successes = 0

for episode in range(total_test_episodes):
    state, info = env.reset()
    terminated = False
    truncated = False

    for step in range(100):
        action = np.argmax(q_table[state, :]) # Escolhe sempre a melhor opção
        new_state, reward, terminated, truncated, info = env.step(action)
        state = new_state
        
        if terminated:
            if reward == 1: # Chegou ao presente (G de Gift)
                successes += 1
            break

print(f"Sucesso em {successes}/{total_test_episodes} episódios de teste.")

Visualizar a curva de aprendizado

import matplotlib.pyplot as plt

# Listas para armazenar dados de progresso
rewards_per_episode = []

# Resetando a Q-table para um novo experimento
q_table = np.zeros((state_size, action_size))
epsilon = max_epsilon

print("Treinando e coletando dados para o gráfico...")

for episode in range(total_episodes):
    state, info = env.reset()
    terminated = False
    truncated = False
    total_reward = 0

    for step in range(100):
        if random.uniform(0, 1) < epsilon:
            action = env.action_space.sample()
        else:
            action = np.argmax(q_table[state, :])

        new_state, reward, terminated, truncated, info = env.step(action)

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

        state = new_state
        total_reward += reward # No FrozenLake é 0 ou 1
        
        if terminated or truncated:
            break

    epsilon = min_epsilon + (max_epsilon - min_epsilon) * np.exp(-decay_rate * episode)
    rewards_per_episode.append(total_reward)

# --- Geração do Gráfico ---
# Para o gráfico não ficar muito poluído, calculamos a média móvel a cada 100 episódios
average_rewards = []
for i in range(0, total_episodes, 100):
    average_rewards.append(np.mean(rewards_per_episode[i:i+100]))

plt.figure(figsize=(10, 5))
plt.plot(range(0, total_episodes, 100), average_rewards, marker='o', color='purple')
plt.title("Progresso do Agente no FrozenLake (Média de Sucesso)")
plt.xlabel("Episódios")
plt.ylabel("Taxa de Sucesso Média (0.0 a 1.0)")
plt.grid(True)
plt.show()
1 resposta

Olá, Tiago! Como vai?

Você mandou muito bem na forma como criou o passo a passo do Q-Learning aplicado ao FrozenLake!

Sua solução mostra clareza na configuração do ambiente e hiperparâmetros, evidencia domínio na implementação da política epsilon-greedy para equilibrar exploração e ainda destaca a importância da avaliação com métricas e visualização gráfica para acompanhar o progresso do agente.

Uma sugestão para o futuro seria incluir métricas adicionais, como a média de recompensas acumuladas ou a taxa de sucesso por intervalo de episódios, para enriquecer ainda mais a análise de desempenho.

Fico à disposição! E se precisar, conte sempre com o apoio do fórum.

Abraço e bons estudos!

AluraConte com o apoio da comunidade Alura na sua jornada. Abraços e bons estudos!