Skip to content

Algoritmo Q-Learning

Definições

Material utilizado para aula expositiva:

Implementação

Depois de uma breve explicação sobre definições e principais conceitos, nós vamos implementar o primeiro agente usando aprendizagem por reforço. Por favor, siga as instruções abaixo:

Trabalhe com o arquivo TaxiDriverGym_introduction.py

  • Leia a descrição do ambiente em https://gymnasium.farama.org/environments/toy_text/taxi/.

  • Copie o arquivo TaxiDriverGym_introduction.py.

  • Execute cada um dos comandos que estão no arquivo TaxiDriverGym_introduction.py em um interpretador python para entender o que o que é environment, reward e action. Além de entender detalhes do ambiente.

  • Quantos espaços possíveis o ambiente Taxi-v3 possui?

  • Quantas ações o agente que atua no ambiente Taxi-v3 possui?

  • O que a variável reward retornada por env.step(<number>) significa?

Arquivo QLearning.py

Este arquivo implementa o algoritmo Q-Learning. A classe implementada neste arquivo possui 4 métodos:

  • __init__ (construtor): que recebe todos os hiperparâmetros do algoritmo Q-Learning e inicializa a Q-table com base no número de ações e estados informados pelo parâmetro env. Alguns destes hiperparâmetros não serão utilizados neste momento, mas vamos mantê-los.

  • select_action: dado um estado, este método seleciona uma ação que deve ser executada.

  • train: método responsável por executar as simulações e popular a Q-table. Este método retorna uma q-table, mas também atualiza um arquivo CSV com os dados da q-table e uma imagem que é um plot da quantidade de ações executadas em cada episódio.

  • plotactions: é um método que cria uma imagem com o plot da quantidade de ações executadas em cada episódio.

Atualizando os valores da Q-table

Dentro do método train tem-se o seguinte trecho de código:

for i in range(1, self.episodes+1):
    state = self.env.reset()
    reward = 0
    done = False
    actions = 0

    while not done:
        action = self.select_action(state)
        next_state, reward, done, _ = self.env.step(action) 

        # Adjust Q value for current state
        old_value = #pegar o valor na q-table para a combinacao action e state
        next_max = #pegar o valor maximo da q-table para o proximo estado
        new_value = #calcula o novo valor
        self.q_table[state, action] = new_value

        # atualiza para o novo estado
        state = next_state

que é responsável por execurtar N episódios e atualizar a variável self.q_table.

Este método é chamado pelo arquivo TaxiDriverGym.py nas linhas 11 e 12:

# only execute the following lines if you want to create a new q-table
qlearn = QLearning(env, alpha=0.1, gamma=0.6, epsilon=0.7, epsilon_min=0.05, epsilon_dec=0.99, episodes=100000)
q_table = qlearn.train('data/q-table-taxi-driver.csv', 'results/actions_taxidriver')
#q_table = loadtxt('data/q-table-taxi-driver.csv', delimiter=',')

Atividades:

  • Complete o código do método train em QLearning.py.

  • Execute o arquivo TaxiDriverGym.py com o comando:

python TaxiDriverGym.py

Lembre-se que nesta execução o programa irá criar toda a Q-table e armazenar no arquivo data/q-table-taxi-driver.csv. Depois de calcular os valores para a Q-table o programa irá resolver um dos possíveis cenários considerando um estado inicial qualquer. Além disso, o programa irá gerar um plot no diretório results que descreve a quantidade de ações executadas em cada época.

  • Abra o arquivo results/action_taxidriver.jpg e faça uma análise do mesmo. O que este gráfico representa?

  • Agora faça o algoritmo TaxiDriverGym.py ler a Q-table a partir do arquivo gerado anteriormente e veja qual é o comportamento. Execute diversas vezes.

  • Qual é o comportamento do agente? Ele sempre consegue encontrar uma solução? As soluções parecem ser ótimas?

Considerando os valores informados nos parâmetros do método train, se a sua implementação do Q-learning estiver correta então o agente TaxiDriverGym.py deve encontrar a solução para todos os casos apresentados. Se por algum motivo a sua solução não estiver convergindo então significa que tem algum bug na atualização da q-table.

Uma vez que você confirmou que a sua implementação não tem bugs então você pode ajustar alguns dos hiperparâmetros. Por exemplo, diminuindo a quantidade de episódios e analisando a Q-table gerada.

  • O arquivo results/action_taxidriver.jpg é um plot da quantidade de episódios versus a quantidade de atividades. Teria alguma outra forma de visualizar a evolução do agente? E se usarmos rewards ao invés da quantidade de atividades? A visualização fica melhor?

Q-table pronta

Como resultado da etapa de treinamento, o agente irá ter uma Q-table que mostra a melhor ação que ele deve executar em cada estado. Para usar este dado é muito simples:

(state, _) = env.reset()
done = False

while not done:
    print(state)
    action = np.argmax(q_table[state])
    state, reward, done, truncated, info = env.step(action)

Neste momento não temos mais nenhuma ação aleatória. O agente sempre irá selecionar a ação com o valor mais alto para cada estado.