O blog da AWS

Treinando um agente de aprendizado por reforço com Unity e Amazon SageMaker RL

Por Yohei Nakayama, Henry Wang e Yijie Zhuang

 

 

Unity é um dos motores de jogos mais populares que foi adotado não só para o desenvolvimento de videogames, mas também por indústrias como a cinematográfica e automotiva. Unity oferece ferramentas para criar ambientes virtuais simulados com física, paisagens e personagens customizáveis. O Unity Machine Learning Agents Toolkit (ML-Agents) é um projeto de código aberto que permite aos desenvolvedores treinar agentes de aprendizado por reforço (Reinforcement Learning – RL) nos ambientes criados no Unity.

O aprendizado por reforço é uma área do aprendizado de máquina (ML) que ensina um agente de software a tomar ações em um ambiente para maximizar um objetivo de longo prazo. Para obter mais informações, consulte Amazon SageMaker RL — Aprendizado por reforço gerenciado com o Amazon SageMaker. ML-Agents está se tornando uma ferramenta cada vez mais popular entre muitas empresas de jogos para casos de uso como design de dificuldade de nível de jogo, correção de bugs e detecção de fraude. Atualmente, o ML-Agents é usado para treinar agentes localmente e não consegue escalar para usar eficientemente mais recursos computacionais. Você tem que treinar agentes de RL com a Unity engine localmente por um longo período de tempo antes de obter o modelo treinado. O processo é demorado e não escalável para processar grandes quantidades de dados.

Neste post, demonstramos uma solução integrando a interface Unity do ML-Agents com o Amazon SageMaker RL, permitindo treinar agentes de RL no Amazon SageMaker de forma totalmente gerenciada e escalável.

 

Visão geral da solução

O SageMaker é um serviço totalmente gerenciado que permite o rápido desenvolvimento de modelos. Ele fornece muitos recursos integrados para ajudá-lo com treinamento, ajuste, depuração e implantação de modelos. O SageMaker RL se baseia no SageMaker, adicionando bibliotecas de RL pré-configuradas e facilitando a integração com diferentes ambientes de simulação. Você pode usar frameworks integrados de aprendizado profundo, como TensorFlow e PyTorch, com vários algoritmos RL integrados da biblioteca RLLib para treinar políticas de RL. A infraestrutura para treinamento e inferência é totalmente gerenciada pelo SageMaker, para que você possa se concentrar na formulação do problemas de RL. O SageMaker RL também fornece um conjunto de notebooks Jupyter, demonstrando variedades de aplicações de RL em domínios como robótica, pesquisa operacional, finanças e muito mais.

O diagrama a seguir ilustra nossa arquitetura da solução.

 

 

Neste post, analisamos as especificidades do treinamento de um agente de RL no SageMaker interagindo com o ambiente Unity de exemplo. Para acessar o notebook completo deste post, consulte o exemplo de notebook do SageMaker no GitHub.

 

Configurando seus ambientes

Para começar, importamos as bibliotecas Python necessárias e configuramos ambientes e permissões. O código a seguir contém as etapas para configurar um bucket do Amazon Simple Storage Service (Amazon S3), definir o prefixo do trabalho de treinamento, especificar o local do trabalho de treinamento e criar uma role do AWS Identity and Access Management (IAM):

import sagemaker
import boto3
 
# set up the linkage and authentication to the S3 bucket
sage_session = sagemaker.session.Session()
s3_bucket = sage_session.default_bucket()  
s3_output_path = 's3://{}/'.format(s3_bucket)
print("S3 bucket path: {}".format(s3_output_path))

# create a descriptive job name
job_name_prefix = 'rl-unity-ray'

# configure where training happens – local or SageMaker instance
local_mode = False

if local_mode:
    instance_type = 'local'
else:
    # If on SageMaker, pick the instance type
    instance_type = "ml.c5.2xlarge"

# create an IAM role
try:
    role = sagemaker.get_execution_role()
except:
    role = get_execution_role()

print("Using IAM role arn: {}".format(role))

 

Criando um contêiner Docker

O SageMaker usa contêineres do Docker para executar scripts, treinar algoritmos e implantar modelos. Um contêiner Docker é um pacote independente de software que gerencia todo o código e dependências, e inclui tudo o que é necessário para executar um aplicativo. Começamos criando em cima de uma imagem Docker pré-criada do SageMaker que contém dependências para o Ray e, em seguida, instalamos os pacotes principais necessários:

  • gym-unity — Unity fornece um wrapper para envolver o ambiente Unity em uma interface do gym, uma biblioteca de código aberto que oferece acesso a um conjunto de ambientes RL clássicos
  • mlagents-envs — Pacote que fornece uma API Python para permitir interação direta com o motor de jogo Unity

Dependendo da máquina, o processo de build do Docker pode levar até 10 minutos. Para todas as imagens do SageMaker RL Docker pré-criadas, consulte o repositório do GitHub.

 

Exemplo de ambiente Unity

Neste post, usamos um exemplo simples ambiente Unity chamado Basic. Na visualização a seguir, o agente que estamos controlando é a caixa azul que se move para a esquerda ou para a direita. Cada passo que é tomado custa ao agente alguma energia, incorrendo em pequenas recompensas negativas (-0,01). Bolas verdes são os alvos com locais fixos. O agente é inicializado aleatoriamente entre as bolas verdes, e recolhe recompensas quando colide com as bolas verdes. A bola verde grande oferece uma recompensa de +1, e a pequena bola verde oferece uma recompensa de +0,1. O objetivo desta tarefa é treinar o agente para se mover em direção à bola que oferece as recompensas maiores.

 

 

Treinamento, avaliação e implantação de modelos

Nesta seção, vamos ajudar você a navegar pelas etapas de treino, avaliação e implantação de modelos.

Escrevendo um script de treinamento

Antes de iniciar o trabalho de treinamento no SageMaker RL, precisamos especificar as configurações do processo de treinamento. Isso é geralmente é feito em um script fora do notebook. O script de treinamento define a entrada (o ambiente Unity) e o algoritmo para treinamento RL. O código a seguir mostra como é o script:

import json
import os

import gym
import ray
from ray.tune import run_experiments
from ray.tune.registry import register_env

from sagemaker_rl.ray_launcher import SageMakerRayLauncher
from mlagents_envs.environment import UnityEnvironment
from mlagents_envs.exception import UnityWorkerInUseException
from mlagents_envs.registry import default_registry
from gym_unity.envs import UnityToGymWrapper

class UnityEnvWrapper(gym.Env):
    def __init__(self, env_config):
        self.worker_index = env_config.worker_index
        if 'SM_CHANNEL_TRAIN' in os.environ:
            env_name = os.environ['SM_CHANNEL_TRAIN'] +'/'+ env_config['env_name']
            os.chmod(env_name, 0o755)
            print("Changed environment binary into executable mode.")
            # Try connecting to the Unity3D game instance.
            while True:
                try:
                    unity_env = UnityEnvironment(
                                    env_name, 
                                    no_graphics=True, 
                                    worker_id=self.worker_index, 
                                    additional_args=['-logFile', 'unity.log'])
                except UnityWorkerInUseException:
                    self.worker_index += 1
                else:
                    break
        else:
            env_name = env_config['env_name']
            while True:
                try:
                    unity_env = default_registry[env_name].make(
                        no_graphics=True,
                        worker_id=self.worker_index,
                        additional_args=['-logFile', 'unity.log'])
                except UnityWorkerInUseException:
                    self.worker_index += 1
                else:
                    break
            
        self.env = UnityToGymWrapper(unity_env) 
        self.action_space = self.env.action_space
        self.observation_space = self.env.observation_space

    def reset(self):
        return self.env.reset()

    def step(self, action):
        return self.env.step(action)

class MyLauncher(SageMakerRayLauncher):

    def register_env_creator(self):
        register_env("unity_env", lambda config: UnityEnvWrapper(config))

    def get_experiment_config(self):
        return {
          "training": {
            "run": "PPO",
            "stop": {
              "timesteps_total": 10000,
            },
            "config": {
              "env": "unity_env",
              "gamma": 0.995,
              "kl_coeff": 1.0,
              "num_sgd_iter": 20,
              "lr": 0.0001,
              "sgd_minibatch_size": 100,
              "train_batch_size": 500,
              "monitor": True,  # Record videos.
              "model": {
                "free_log_std": True
              },
              "env_config":{
                "env_name": "Basic"
              },
              "num_workers": (self.num_cpus-1),
              "ignore_worker_failures": True,
            }
          }
        }

if __name__ == "__main__":
    MyLauncher().train_main()

 

O script de treinamento tem dois componentes:

  • UnityEnvWrapper — O ambiente Unity é armazenado como um arquivo binário. Para carregar o ambiente, precisamos usar a API Python do Unity ML-Agents. UnityEnvironment recebe como entrada o nome do ambiente e retorna um objeto de ambiente interativo. Em seguida, criamos um wrapper ao objeto com UnityToGymWrapper e retornamos um objeto que é treinável usando Ray-RLLib e SageMaker RL.
  • MyLauncher — Essa classe herda a classe base SageMakerRayLauncher para aplicativos SageMaker RL que usam o Ray-RLLib. Dentro da classe, registramos o ambiente para ser reconhecido pelo Ray e especificamos as configurações que queremos durante o treinamento. Os hiperparâmetros de exemplo incluem o nome do ambiente, o fator de desconto em recompensas cumulativas, a taxa de aprendizado do modelo e o número de iterações para executar o modelo. Para obter uma lista completa de hiperparâmetros comumente usados, consulte Parâmetros comuns.

Treinando o modelo

Depois de criar a configuração e customizar o modelo, estamos prontos para iniciar o trabalho de treinamento do SageMaker RL. Veja o seguinte código:

 

metric_definitions = RLEstimator.default_metric_definitions(RLToolkit.RAY)
    
estimator = RLEstimator(entry_point="train-unity.py",
                        source_dir='src',
                        dependencies=["common/sagemaker_rl"],
                        image_name=custom_image_name,
                        role=role,
                        train_instance_type=instance_type,
                        train_instance_count=1,
                        output_path=s3_output_path,
                        base_job_name=job_name_prefix,
                        metric_definitions=metric_definitions,
                        hyperparameters={
				# customize Ray parameters here
                        }
                    )

estimator.fit(wait=local_mode)
job_name = estimator.latest_training_job.job_name
print("Training job: %s" % job_name)

 

  • Dentro do código, especificamos alguns parâmetros:
    • entry_point — O caminho para o script de treinamento que escrevemos que especifica o processo de treinamento
    • source_dir — O caminho para o diretório com outras dependências do código-fonte de treinamento, além do arquivo de entry point
    • dependencies — Uma lista de caminhos para diretórios com bibliotecas adicionais a serem exportadas para o contêiner

    Além disso, nós configuramos o nome da imagem do contêiner, as informações da instância de treinamento, o caminho de saída e as métricas selecionadas. Também temos permissão para personalizar quaisquer parâmetros relacionados ao Ray usando o argumento hyperparameters. Lançamos o trabalho de treinamento do SageMaker RL chamando estimator.fit e iniciamos o processo de treinamento do modelo com base nas especificações do script de treinamento.

    Em um nível alto, o trabalho de treinamento inicia uma rede neural e atualiza a rede gradualmente para a direção em que o agente coleta recompensas mais altas. Após várias interações, o agente eventualmente aprende como navegar para o local de altas recompensas de forma eficiente. O SageMaker RL lida com todo o processo e permite visualizar o status do trabalho de treinamento na página Trabalhos de treinamento na console do SageMaker.

    Também é possível monitorar o desempenho do modelo examinando os logs de treinamento no Amazon CloudWatch. Devido à simplicidade da tarefa, o modelo completa o treinamento (10.000 movimentos do agente) com aproximadamente 800 episódios (número de vezes que o agente atinge uma bola alvo) em menos de 1 minuto. O gráfico a seguir mostra que a recompensa média coletada converge em torno de 0,9. A recompensa máxima que o agente pode obter neste ambiente é 1, e cada passo custa 0,01, portanto, uma recompensa média em torno de 0,9 parece ser o resultado de uma política ideal, indicando que nosso processo de treinamento é bem sucedido!

 

Avaliando o modelo

Quando o treinamento do modelo estiver completo, podemos carregar o modelo treinado para avaliar seu desempenho. Semelhante à configuração no script de treinamento, criamos um wrapper do Gym sobre o ambiente Unity. Em seguida, criamos um agente carregando o modelo treinado.

Para avaliar o modelo, executamos o agente treinado várias vezes no ambiente com um agente fixo e objetivo inicializado, e adicionamos as recompensas cumulativas que o agente coleta em cada etapa para cada episódio.

Dos cinco episódios, a recompensa média do episódio é de 0,92 com a recompensa máxima de 0,93 e recompensa a mínima de 0,89, sugerindo que o modelo treinado realmente tem um bom desempenho.

Implantando o modelo

Podemos implantar a política de RL treinada com apenas algumas linhas de código usando a API de implantação do modelo no SageMaker. Você pode enviar uma entrada e obter as ações ideais com base na política. A forma da entrada precisa seguir o formato de entrada de observação do ambiente.

Para o ambiente Basic, implementamos o modelo e passamos uma entrada para o predictor:

 

from sagemaker.tensorflow.model import TensorFlowModel

model = TensorFlowModel(model_data=estimator.model_data,
              framework_version='2.1.0',
              role=role)

predictor = model.deploy(initial_instance_count=1, 
                         instance_type=instance_type)

input = {"inputs": {'observations': np.ones(shape=(1, 20)).tolist(),
                    'prev_action': [0, 0],
                    'is_training': False,
                    'prev_reward': -1,
                    'seq_lens': -1
                   }
        }    

result = predictor.predict(input)
print(result['outputs']['actions'])

 

O modelo prevê um movimento para a esquerda ou para a direita. A direção de movimento recomendada para o agente caixa azul sempre aponta para a bola verde maior.

 

Limpando o que foi criado

Quando terminar de executar o modelo, chame predictor.delete_endpoint() para excluir o endpoint de implantação do modelo e evitar cobranças futuras.

 

Customizando algoritmos, modelos e ambientes de treinamento

Além do caso de uso anterior, recomendamos que você explore as funcionalidades de customização que essa solução oferece suporte.

No exemplo de código anterior, especificamos a Proximal Policy Optimization (PPO) para ser o algoritmo de treinamento. A PPO é um algoritmo RL popular que tem performance comparável às abordagens estado da arte, mas é muito mais simples de implementar e fazer tuning. Dependendo do seu caso de uso, você pode escolher o algoritmo mais apropriado para treinamento de uma lista abrangente de algoritmos já implementados no RLLib ou construindo um algoritmo personalizado a partir do zero.

Por padrão, o RLLib aplica uma rede neural convolucional pré-definida ou rede neural totalmente conectada. No entanto, você pode criar um modelo personalizado para treinamento e teste. Seguindo os exemplos do RLLib, você pode registrar o modelo personalizado chamando ModelCatalog.register_custom_model e, em seguida, usar o modelo recém-registrado usando o argumento custom_model.

Em nosso exemplo de código, invocamos um ambiente Unity pré-definido chamado Basic, mas você pode experimentar outros ambientes Unity pré-criados. No momento de escrita deste post, nossa solução suporta apenas um ambiente de agente único. Quando novos ambientes são construídos, registre-os chamando register_env  e use o ambiente com o parâmetro env.

 

Conclusão

Neste post, examinamos como treinar um agente de RL para interagir com ambientes de jogos Unity usando o SageMaker RL. Usamos um exemplo de ambiente Unity pré-criado para a demonstração, mas encorajamos você a explorar usando ambientes Unity personalizados ou outros pré-criados.

O SageMaker RL oferece uma maneira escalável e eficiente de treinar agentes de RL a jogar em ambientes Unity. Para o notebook que contém o código completo, consulte Unity 3D Game com Amazon SageMaker RL.

Se você quiser ajuda para acelerar seu uso de ML em seus produtos e processos, entre em contato com o Amazon ML Solutions Lab.

 

Esse artigo foi tadruzido do Blog da AWS em Inglês

 


Sobre los Autores

Yohei Nakayama é arquiteto de Deep Learning no Amazon Machine Learning Solutions Lab, onde trabalha com clientes em diferentes verticais para acelerar seu uso de inteligência artificial e serviços de nuvem AWS para resolver seus desafios de negócios. Ele está interessado em aplicar tecnologias ML/AI para a indústria espacial.

 

 

 

Henry Wang é Cientista de Dados no Amazon Machine Learning Solutions Lab. Antes de ingressar na AWS, ele foi estudante de pós-graduação em Harvard em Ciência e Engenharia Computacional, onde trabalhou em pesquisa em saúde com aprendizado por reforço. Em seu tempo livre, ele gosta de jogar tênis e golfe, ler e assistir torneios de StarCraft II.

 

 

 

Yijie Zhuang é Engenheiro de Software do Amazon SageMaker. Ele fez seu mestrado em Engenharia da Computação na Duke. Seus interesses estão na construção de algoritmos escaláveis e sistemas de aprendizagem por reforço. Ele contribuiu no desenvolvimento de algoritmos pré-configurados no Amazon SageMaker e Amazon SageMaker RL.

 

 

 

Revisor

Marcelo Cunha é um arquiteto de soluções da AWS especialista em AI/ML. Em sua função, ele ajuda os clientes a criar soluções de ML para resolver os seus desafios de negócio utilizando a plataforma AWS. De uma família de médicos e profissionais da saúde, ele também tem interesse em aplicações de ML nesse setor.