← Back to list

Ensinei uma IA a Jogar Sonic — e Aprendi Muito Sobre Aprendizado por Reforço no Processo

Como cientista de dados, boa parte do meu trabalho envolve ensinar máquinas a reconhecer padrões em dados históricos. Mas existe uma…

Lincoln Romais · 2026-05-15 12:27 · 51 claps · 6.0 min read
#ai #machine-learning-ai #sonic-the-hedgehog #sonic
Open on Medium ↗
Wiki topics: ML · Machine Learning AI · AI · General EDU · Education & Learning

Ensinei uma IA a Jogar Sonic — e Aprendi Muito Sobre Aprendizado por Reforço no Processo

Como cientista de dados, boa parte do meu trabalho envolve ensinar máquinas a reconhecer padrões em dados históricos. Mas existe uma categoria de problemas onde não temos dados históricos — onde o agente precisa descobrir sozinho o que fazer, tentando, errando e aprendendo com as consequências. Isso é Aprendizado por Reforço, e é exatamente o que usei para treinar um agente para jogar Sonic The Hedgehog do zero.

Neste artigo vou te explicar os conceitos fundamentais do Aprendizado por Reforço (RL) e mostrar como implementei um agente do zero usando Python, Stable-Baselines3 e o algoritmo PPO. Sem enrolação — vamos direto ao que importa.

O que é Aprendizado por Reforço?

Imagine que você quer ensinar um cachorro a sentar. Você não mostra exemplos rotulados de “cachorros sentados” — você dá um comando, o cachorro reage, e você recompensa quando ele acerta. Com o tempo, ele aprende que sentar gera recompensa.

O Aprendizado por Reforço funciona exatamente assim, só que com matemática.

Os três componentes centrais são:

  • Agente: quem toma as decisões (no nosso caso, o Sonic controlado pela IA)
  • Ambiente: o mundo com o qual o agente interage (o jogo)
  • Recompensa: o sinal que diz se a ação foi boa ou ruim

O ciclo funciona assim: o agente observa o estado atual do ambiente, escolhe uma ação, recebe uma recompensa (positiva ou negativa) e observa o novo estado. Esse loop se repete milhões de vezes até o agente aprender uma política — uma estratégia de comportamento — que maximize a recompensa acumulada.

O objetivo do agente não é maximizar a recompensa imediata, mas a recompensa total ao longo do tempo. Às vezes vale sacrificar um ponto agora para ganhar muito mais depois.

Por que jogos são o ambiente perfeito para RL?

Jogos são ideais para pesquisa em RL por três motivos:

  1. Feedback imediato: o jogo já fornece pontuação, que serve como recompensa natural
  2. Simulação rápida: podemos rodar milhares de partidas em horas, coisa impossível no mundo real
  3. Ambiente controlado: as regras são fixas, sem variáveis externas imprevisíveis

Foi assim que a DeepMind treinou o AlphaGo, que a OpenAI treinou agentes no Dota 2, e que eu treinei o Sonic — a lógica é a mesma, a escala é diferente.

O Algoritmo: PPO (Proximal Policy Optimization)

Existem dezenas de algoritmos de RL. Para esse projeto usei o PPO, desenvolvido pela OpenAI em 2017 e até hoje um dos mais usados na prática. O motivo é simples: ele é estável, eficiente e funciona bem em uma grande variedade de problemas.

A ideia central do PPO é aprender uma política — uma função que mapeia observações em ações — de forma conservadora. A cada atualização, ele limita o quanto a política pode mudar, evitando que o agente “desaprenda” tudo por causa de uma atualização muito agressiva.

Matematicamente, o PPO otimiza um objetivo com clipping:

L = min(r * A, clip(r, 1-ε, 1+ε) * A)

Onde r é a razão entre a nova e a antiga política, A é a vantagem estimada da ação, e ε (epsilon) controla o quanto a política pode mudar — geralmente 0.2.

Na prática, isso significa que o agente aprende de forma gradual e consistente, sem colapsar no meio do treino.

Preparando o Ambiente

Para o projeto usei:

  • Python 3.10 via pyenv
  • stable-retro: fork mantido do gym-retro para emulação de jogos clássicos
  • Stable-Baselines3: implementação de alta qualidade de algoritmos de RL
  • Gymnasium: interface padrão para ambientes de RL
  • PyTorch com suporte a CUDA para treinar na GPU

A ROM do Sonic precisa ser importada manualmente para o emulador. Após isso, o ambiente já expõe observações (frames do jogo) e aceita ações (botões do controle).

Processando as Observações

O agente recebe como entrada os pixels da tela — uma imagem de 224x320 pixels com 3 canais de cor. Isso é muita informação para processar diretamente. Por isso apliquei uma sequência de transformações:

  1. Frame Skip: repete cada ação por 4 frames. O jogo muda lentamente entre frames consecutivos, então não precisamos decidir a cada frame — isso acelera muito o treino
  2. Escala de Cinza: remove os canais de cor, que não são necessários para tomar decisões. Reduz de 3 canais para 1
  3. Redimensionamento: reduz de 224x320 para 84x84 pixels, padrão na literatura de RL com jogos
  4. Frame Stacking: empilha os últimos 4 frames em um único input. Isso dá ao agente noção de movimento — ele consegue inferir a direção e velocidade do Sonic

O resultado final é um tensor de shape (4, 84, 84) — 4 frames em escala de cinza de 84x84 pixels. Esse é o input que a rede neural recebe.

A Recompensa Customizada

A recompensa padrão do jogo (pontuação) não é ideal para treino de RL. O Sonic pode ficar parado e não perder pontos, o que não incentiva progresso.

Por isso implementei uma função de recompensa customizada com três componentes:

  • +1.0 cada vez que o Sonic avança para uma nova posição máxima no eixo X — incentiva exploração e progresso
  • -0.01 quando fica parado ou recua — penaliza comportamento passivo
  • +0.001 a cada step que sobrevive — pequeno bônus por continuar vivo

Essa engenharia de recompensa é um dos aspectos mais críticos e subestimados do RL. Uma recompensa mal definida pode fazer o agente aprender comportamentos completamente indesejados — como ficar pulando no mesmo lugar para acumular bônus de sobrevivência sem avançar.

A Rede Neural: CnnPolicy

Como a entrada é uma imagem, usei uma política baseada em CNN (Convolutional Neural Network) — a CnnPolicy do Stable-Baselines3, inspirada na arquitetura da DeepMind usada no paper original do DQN.

A arquitetura consiste em três camadas convolucionais para extrair features visuais do jogo, seguidas de camadas densas que mapeiam essas features em valores de ação. A rede aprende a reconhecer padrões visuais relevantes — inimigos, plataformas, obstáculos — sem que precisemos programar isso explicitamente.

Os Hiperparâmetros

Os principais hiperparâmetros que usei:

learning_rate = 0.00025   # taxa de aprendizado
n_steps = 2048            # frames coletados antes de cada atualização
batch_size = 64           # tamanho do mini-batch
n_epochs = 10             # passagens pelo buffer a cada atualização
gamma = 0.99              # fator de desconto para recompensas futuras
clip_range = 0.2          # epsilon do PPO
ent_coef = 0.01           # coeficiente de entropia (incentiva exploração)

O gamma merece atenção especial. Ele controla o quanto o agente valoriza recompensas futuras versus imediatas. Com gamma = 0.99, uma recompensa 100 steps no futuro vale 0.99^100 ≈ 0.37 do valor de uma recompensa imediata. Valores próximos de 1 fazem o agente pensar mais a longo prazo.

O Treino

O treino rodou por 1.000.000 de timesteps em uma RTX 4060. O processo é iterativo:

  1. O agente coleta 2048 frames interagindo com o ambiente
  2. Calcula as vantagens de cada ação (foi melhor ou pior do que o esperado?)
  3. Atualiza a política com 10 épocas de gradiente descendente sobre o buffer coletado
  4. Repete

Nos primeiros episódios o Sonic fica praticamente parado — as ações são quase aleatórias. Após algumas dezenas de milhares de steps ele começa a ir consistentemente para a direita. Com centenas de milhares de steps começa a desviar de obstáculos e inimigos.

Ver o agente evoluir de completamente aleatório para competente é uma das experiências mais fascinantes que já tive como cientista de dados. É difícil não antropomorfizar — parece que ele está pensando.

O que aprendi com esse projeto

Alguns insights práticos que não aparecem nos tutoriais:

  • Engenharia de recompensa é tudo: o algoritmo é só uma ferramenta. A recompensa define o comportamento. Errou na recompensa, o agente aprende a errar de formas criativas.
  • Ordem dos wrappers importa: aplicar o frame stacking antes ou depois do wrapper de recompensa pode quebrar silenciosamente o shape das observações.
  • Debugging em RL é difícil: o agente pode parecer que está aprendendo (loss caindo) mas estar convergindo para um comportamento subótimo. Monitorar o reward médio por episódio é essencial.
  • GPU faz diferença: treinar em CPU levaria horas para o que a GPU faz em minutos — mas o driver precisa estar atualizado e o PyTorch instalado com suporte a CUDA correto.

Próximos Passos

Esse projeto é um ponto de partida. Algumas direções naturais para evoluir:

  • Treinar em múltiplas fases simultaneamente para generalização
  • Experimentar com outros algoritmos como SAC ou A3C
  • Usar curiosity-driven exploration para fases mais complexas
  • Implementar curriculum learning — começar em fases fáceis e aumentar a dificuldade progressivamente

Conclusão

Aprendizado por Reforço é uma das áreas mais fascinantes da IA — e também uma das mais desafiadoras. Diferente do aprendizado supervisionado, onde você tem respostas certas para aprender, no RL você só tem consequências. O agente precisa descobrir o que “certo” significa através da experiência.

Implementar um projeto como esse do zero, lidando com todos os problemas práticos — compatibilidade de bibliotecas, formato de observações, engenharia de recompensa, bugs de emulação — ensina muito mais do que qualquer curso teórico.

Se você é cientista de dados e ainda não experimentou RL, recomendo fortemente. O campo está evoluindo rápido, e a intuição que você desenvolve implementando esses projetos é cada vez mais valiosa.

O código completo do projeto está disponível no GitHub. Qualquer dúvida, deixa nos comentários.


메타데이터
post_id
59611bddf681
slug
ensinei-uma-ia-a-jogar-sonic-e-aprendi-muito-sobre-aprendizado-por-reforço-no-processo-59611bddf681
url
https://medium.com/@linkolnsr/ensinei-uma-ia-a-jogar-sonic-e-aprendi-muito-sobre-aprendizado-por-refor%C3%A7o-no-processo-59611bddf681
canonical_url
https://medium.com/@linkolnsr/ensinei-uma-ia-a-jogar-sonic-e-aprendi-muito-sobre-aprendizado-por-refor%C3%A7o-no-processo-59611bddf681
author_url
https://medium.com/@linkolnsr
status
ok
fetched_at
2026-07-10 15:20:15