diff --git a/experiments/solves/solve_simple64_veryeasy.py b/experiments/solves/solve_simple64_veryeasy.py index a11c3fb7..b5b0c13c 100644 --- a/experiments/solves/solve_simple64_veryeasy.py +++ b/experiments/solves/solve_simple64_veryeasy.py @@ -12,13 +12,16 @@ from urnai.models.ddqn_keras import DDQNKeras from urnai.models.model_builder import ModelBuilder from urnai.trainers.trainer import Trainer +from urnai.models.algorithms.ddql import DoubleDeepQLearning + def declare_trainer(): - env = SC2Env(map_name='Simple64', render=True, + env = SC2Env(map_name='Simple64', render=False, step_mul=16, player_race='terran', - enemy_race='random', difficulty='very_easy') - + enemy_race='random', difficulty='very_easy', self_play=True) + + action_wrapper = SimpleTerranWrapper() state_builder = Simple64GridState(grid_size=4) @@ -27,28 +30,29 @@ def declare_trainer(): helper.add_fullyconn_layer(50) helper.add_output_layer() - dq_network = DDQNKeras(action_wrapper=action_wrapper, - state_builder=state_builder, - build_model=helper.get_model_layout(), - per_episode_epsilon_decay=False, - gamma=0.99, learning_rate=0.001, - epsilon_decay=0.99999, epsilon_min=0.005, - memory_maxlen=100000, min_memory_size=2000) + dq_network = DoubleDeepQLearning(action_wrapper=action_wrapper, + state_builder=state_builder, + build_model=helper.get_model_layout(), + per_episode_epsilon_decay=False, + gamma=0.99, learning_rate=0.0001, + epsilon_decay=0.99999, epsilon_min=0.005, + memory_maxlen=100000, min_memory_size=2000, + lib="keras") agent = SC2Agent(dq_network, KilledUnitsReward()) trainer = Trainer(env, agent, save_path='urnai/models/saved', - file_name='terran_ddqn_vs_random_v_easy', - save_every=50, enable_save=True, relative_path=True, - max_training_episodes=5, max_steps_training=1200, - max_test_episodes=5, max_steps_testing=1200) + file_name='terran_selfplay_v3_lr03', + save_every=1, enable_save=True, relative_path=True, + max_training_episodes=3000, max_steps_training=1200, + max_test_episodes=150, max_steps_testing=1200) return trainer def main(unused_argv): try: trainer = declare_trainer() - trainer.train() + #trainer.train() trainer.play() except KeyboardInterrupt: @@ -57,3 +61,8 @@ def main(unused_argv): if __name__ == '__main__': app.run(main) + + + +##### COMANDO PARA RODAR ESSE CÓDIGO: +# python c:/Users/thuan/urnai-tools-master/experiments/solves/solve_simple64_veryeasy.py diff --git a/tests/unit_tests/test_logger.py b/tests/unit_tests/test_logger.py new file mode 100644 index 00000000..7c1d2b63 --- /dev/null +++ b/tests/unit_tests/test_logger.py @@ -0,0 +1,263 @@ +import inspect +import os +import sys +import gym +import unittest +import GPUtil +from time import time +from multiprocessing import Process +import psutil + +from urnai.utils.logger import Logger +from urnai.agents.generic_agent import GenericAgent +from urnai.agents.rewards.gym import FrozenlakeReward +from urnai.agents.states.gym import FrozenLakeState +from urnai.envs.gym import GymEnv +from urnai.models.ddqn_keras import DDQNKeras +from urnai.models.model_builder import ModelBuilder +from urnai.trainers.trainer import Trainer + + +# class GymAgent: +# def __init__(self, env_name): +# self.env = gym.make(env_name) +# self.observation_space = self.env.observation_space +# self.action_space = self.env.action_space +# self.observation = None +# self.action = None +# self.reward = None +# self.done = False +# self.ep_count = 0 + + +# def reset(self): +# self.observation = self.env.reset() +# self.action = None +# self.reward = None +# self.done = False +# return self.observation + +# def act(self, action): +# self.action = action +# self.observation, self.reward, self.done, _ = self.env.step(self.action) +# return self.reward + +# def observe(self, reward=None): +# return self.observation, self.reward, self.done + +# def record_episode(self, ep_reward, has_won, steps_count, agent_info, ep_actions): +# self.ep_count += 1 + + +# #registra as ações tomadas pelo agente e calcula a média das ações tomadas até aquele ponto. +# for i in range(self.agent_action_size): + +# #adiciona a ação do episódio atual +# self.ep_agent_actions[i].append(ep_actions[i]) +# #calcula e adiciona a média das ações tomadas até este ponto. +# self.avg_ep_agent_actions[i].append(sum(self.ep_agent_actions[i]) / self.ep_count) + + +# #armazena a recompensa obtida no episódio atual +# self.ep_rewards.append(ep_reward) +# #calcula e armazena a média das recompensas obtidas até este episódio +# self.ep_avg_rewards.append(sum(self.ep_rewards) / self.ep_count) + +# #adciona a contagem e a média da contagem de etapas que indica a quantidade de ações que o agente tomou durante um episódio. +# self.ep_steps_count.append(steps_count) +# self.ep_avg_steps.append(sum(self.ep_steps_count) / self.ep_count) + +# # time and sps stuff +# #Essas métricas podem ajudar a avaliar o desempenho do agente ao longo do tempo e a identificar possíveis +# # problemas ou melhorias que precisam ser feitas no modelo +# #Essa parte do método calcula e armazena as métricas relacionadas +# # à duração e ao desempenho do agente durante o episódio. + +# #mede quanto tempo o episódio levou para ser concluído (diferença entre o tempo atual e o tempo de início do ep). +# episode_duration = time() - self.episode_temp_start_time +# #armazena a duração do episódio na lista que armazena a duração de cada episódio +# self.episode_duration_list.append(round(episode_duration, 1)) + +# if episode_duration != 0: +# #número de etapas do agente por segundo em cada episódio +# self.episode_sps_list.append(round(steps_count / episode_duration, 2)) +# else: +# self.episode_sps_list.append(0) + +# #armazena a média do número de etapas por segundo para todos os episódios concluídos até agora. +# self.avg_sps_list.append(round(sum(self.episode_sps_list) / self.ep_count, 2)) + + + +# # performance stuff +# #uso da biblioteca psutil para coletar +# # informações de uso do sistema em relação à CPU e à memória. + +# #coleta a porcentagem de uso de memória atual do sistema. +# memory_usage_percent = psutil.virtual_memory().percent + +# #calcula a porcentagem de memória disponível em relação ao total. +# memory_avail_percent = (psutil.virtual_memory().available * 100 / +# psutil.virtual_memory().total) + +# #calcula a quantidade de memória em uso em gigabytes. +# memory_usage_gigs = psutil.virtual_memory().used / 1024 ** 3 +# #calcula a quantidade de memória disponível em gigabytes. +# memory_avail_gigs = psutil.virtual_memory().free / 1024 ** 3 +# #coleta a porcentagem de uso da CPU no momento. +# cpu_usage_percent = psutil.cpu_percent() + +# # has GPU available +# #Essa parte do código é responsável por tentar obter informações sobre a utilização da GPU (unidade de processamento gráfico) no sistema. +# # Ele usa a biblioteca GPUtil para tentar acessar informações sobre a memória e a carga da GPU. +# # Se conseguir acessar essas informações, ele armazena a porcentagem de uso de memória da GPU, o uso de memória da GPU em gigabytes e a porcentagem de uso da GPU. +# # Caso contrário, ele define todos esses valores como 0. +# try: +# gpu_memory_usage_percent = GPUtil.getGPUs()[0].memoryUtil * 100 +# gpu_memory_usage_gigs = GPUtil.getGPUs()[0].memoryUsed / 1000 +# gpu_usage_percent = GPUtil.getGPUs()[0].load * 100 + +# except Exception: +# gpu_memory_usage_percent = 0 +# gpu_memory_usage_gigs = 0 +# gpu_usage_percent = 0 + + +# # uso percentual atual da memória RAM; +# self.memory_usage_percent_inst.append(memory_usage_percent) +# #uso percentual atual da memória da GPU (placa de vídeo); +# self.gpu_memory_usage_percent_inst.append(gpu_memory_usage_percent) +# #uso atual de memória RAM em gigabytes; +# self.memory_usage_gigs_inst.append(memory_usage_gigs) +# #uso atual de memória da GPU em gigabytes; +# self.gpu_memory_usage_gigs_inst.append(gpu_memory_usage_gigs) +# #porcentagem de memória RAM disponível; +# self.memory_avail_percent_inst.append(memory_avail_percent) +# #quantidade de memória RAM disponível em gigabytes; +# self.memory_avail_gigs_inst.append(memory_avail_gigs) +# #uso percentual atual da CPU; +# self.cpu_usage_percent_inst.append(cpu_usage_percent) +# #uso percentual atual da GPU (placa de vídeo). +# self.gpu_usage_percent_inst.append(gpu_usage_percent) + +# #calcula a média de todas as informações acima; +# self.memory_usage_percent_avg.append(sum(self.memory_usage_percent_inst) / self.ep_count) +# self.gpu_memory_usage_percent_avg.append( +# sum(self.gpu_memory_usage_percent_inst) / self.ep_count) +# self.memory_usage_gigs_avg.append(sum(self.memory_usage_gigs_inst) / self.ep_count) +# self.gpu_memory_usage_gigs_avg.append(sum(self.gpu_memory_usage_gigs_inst) / self.ep_count) +# self.memory_avail_percent_avg.append(sum(self.memory_avail_percent_inst) / self.ep_count) +# self.memory_avail_gigs_avg.append(sum(self.memory_avail_gigs_inst) / self.ep_count) +# self.cpu_usage_percent_avg.append(sum(self.cpu_usage_percent_inst) / self.ep_count) +# self.gpu_usage_percent_avg.append(sum(self.gpu_usage_percent_inst) / self.ep_count) + +# #Essa parte do código verifica se o episódio atual tem uma recompensa (ep_reward) melhor do que +# #a melhor recompensa registrada até agora (self.best_reward) e, se for o caso, +# #atualiza a melhor recompensa (self.best_reward) +# #e o episódio em que ela ocorreu (self.best_reward_episode) para o episódio atual (self.ep_count). +# # Isso é útil para acompanhar o melhor desempenho alcançado pelo agente durante o treinamento. +# if ep_reward > self.best_reward: +# self.best_reward = ep_reward +# self.best_reward_episode = self.ep_count + + +# #Essa parte do código é responsável por monitorar a taxa de vitórias +# # do agente em um ambiente de aprendizado episódico. +# # A variável has_won é um booleano que indica se o agente venceu ou não o episódio atual. +# # Se has_won for verdadeiro, então o valor 1 é adicionado à lista ep_victories, caso contrário, o valor 0 é adicionado. +# # A lista ep_avg_victories é uma lista de média móvel que armazena a média das vitórias episódicas para cada episódio. +# if self.is_episodic: +# victory = 1 if has_won else 0 +# self.ep_victories.append(victory) +# self.ep_avg_victories.append(sum(self.ep_victories) / self.ep_count) + +# #Essa parte inicializa o dicionário self.agent_info com as chaves presentes no dicionário agent_info, se self.agent_info for None (ou seja, não foi inicializado antes). Em seguida, +# #itera sobre as chaves em self.agent_info e define uma lista vazia como valor para cada uma dessas chaves. +# if self.agent_info is None: +# self.agent_info = dict.fromkeys(agent_info) +# for key in self.agent_info: +# self.agent_info[key] = [] + +# #Essa parte do método adiciona os valores dos dicionários do agent_info atual +# #para a lista de histórico self.agent_info. O loop percorre cada chave +# #do dicionário agent_info e adiciona o valor correspondente para a lista self.agent_info[key]. +# for key in agent_info: +# self.agent_info[key].append(agent_info[key]) + +# # batch episode calculation +# #Essa parte do código verifica se o número de episódios coletados é o primeiro ou um múltiplo +# #de um parâmetro definido episode_batch_avg_calculation. +# # Se for, a média das recompensas dos últimos episode_batch_avg_calculation episódios é calculada +# # e adicionada à lista ep_avg_batch_rewards. +# # Se for o primeiro episódio, a recompensa do episódio atual é adicionada à lista ep_avg_batch_rewards. +# #A lista ep_avg_batch_rewards_episodes guarda os episódios em que a média das recompensas foi calculada. +# if self.ep_count == 1 or self.ep_count % self.episode_batch_avg_calculation == 0: +# if self.ep_count == 1: +# self.ep_avg_batch_rewards_episodes.append(self.ep_count) +# self.ep_avg_batch_rewards.append(ep_reward) +# else: +# avg_rwd = sum(self.ep_rewards[(self.ep_avg_batch_rewards_episodes[-1] - 1):-1]) \ +# / self.episode_batch_avg_calculation +# self.ep_avg_batch_rewards_episodes.append(self.ep_count) +# self.ep_avg_batch_rewards.append(avg_rwd) + + +class TestLoggerMethods (unittest.TestCase): + def test_record_episode(self): + env = GymEnv(id='FrozenLakeNotSlippery-v0') + action_wrapper = env.get_action_wrapper() + state_builder = FrozenLakeState() + + helper = ModelBuilder() + helper.add_input_layer() + helper.add_fullyconn_layer(256) + helper.add_fullyconn_layer(256) + helper.add_fullyconn_layer(256) + helper.add_fullyconn_layer(256) + helper.add_output_layer() + + dq_network = DDQNKeras(action_wrapper=action_wrapper, state_builder=state_builder, + learning_rate=0.005, gamma=0.90, use_memory=False, + per_episode_epsilon_decay=True, build_model=helper.get_model_layout()) + # Criar um objeto do tipo da classe que possui o método record_episode + agent = GenericAgent(dq_network, FrozenlakeReward()) + + # Definir valores de entrada para o método record_episode + ep_reward = 100 + ep_actions = [0, 1, 2] + has_won = True + agent_info = {'param1': 0.5, 'param2': 'string'} + steps_count = 100 + + + # Chamar o método record_episode com os valores de entrada definidos + agent.record_episode(ep_reward, has_won, steps_count, agent_info, ep_actions) + + # Verificar se os valores de saída são iguais aos valores esperados + self.assertEqual(agent.ep_count, 1) + self.assertEqual(agent.ep_rewards, [100]) + self.assertEqual(agent.ep_avg_rewards, [100]) + self.assertEqual(agent.ep_agent_actions, [[0, 1, 2]]) + self.assertEqual(agent.avg_ep_agent_actions, [[0.0, 0.5, 1.0]]) + self.assertEqual(agent.ep_victories, [1]) + self.assertEqual(agent.ep_avg_victories, [1.0]) + self.assertEqual(agent.agent_info, {'param1': [0.5], 'param2': ['string']}) + + + # def setUp(self): + # self.logger = GymAgent("CartPole-v1") + # self.ep_count = 10 + # self.play_rewards = [1, 2, 3, 4, 5] + # self.play_victories = 3 + # self.num_matches = 5 + + # def test_record_play_test(self): + # self.logger.record_play_test(self.ep_count, self.play_rewards, self.play_victories, self.num_matches) + + # self.assertIn(self.ep_count, self.logger.play_ep_count) + # self.assertIn(self.num_matches, self.logger.play_match_count) + # self.assertEqual(self.play_victories / self.num_matches, self.logger.play_win_rates[-1]) + # self.assertEqual(sum(self.play_rewards) / self.num_matches, self.logger.play_rewards_avg[-1]) + +if __name__ == '__main__': + unittest.main() diff --git a/urnai/agents/actions/sc2_wrapper.py b/urnai/agents/actions/sc2_wrapper.py index b077fa09..3451d5b9 100644 --- a/urnai/agents/actions/sc2_wrapper.py +++ b/urnai/agents/actions/sc2_wrapper.py @@ -1404,7 +1404,7 @@ def __init__(self, use_atk_grid=False, atk_grid_x=4, atk_grid_y=4): ACTION_MORPH_UNSIEGE_TANK, ACTION_TRAIN_SCV, - ACTION_CALLDOWN_MULE, + #ACTION_CALLDOWN_MULE, ACTION_TRAIN_MARINE, ACTION_TRAIN_MARAUDER, diff --git a/urnai/utils/logger.py b/urnai/utils/logger.py index 9d7a997c..e894fce8 100644 --- a/urnai/utils/logger.py +++ b/urnai/utils/logger.py @@ -54,7 +54,9 @@ def __init__(self, ep_total, agent_name, model_name, model, self.best_reward_episode = -1 self.episode_batch_avg_calculation = episode_batch_avg_calculation self.rolling_avg_window_size = rolling_avg_window_size + #contém a recompensa obtida em cada episódio executado self.ep_rewards = [] + #contém a média de recompensas obtidas em cada episódio self.ep_avg_rewards = [] self.ep_avg_batch_rewards = [] self.ep_avg_batch_rewards_episodes = [] @@ -70,8 +72,10 @@ def __init__(self, ep_total, agent_name, model_name, model, # Agent Action count self.agent_action_names = agent_action_names + #número de ações tomadas pelo agente self.agent_action_size = agent_action_size self.ep_agent_actions = [[] for i in range(agent_action_size)] + #lista utilizada para plotar um gráfico da evolução das ações tomadas pelo agente ao longo dos episódios. self.avg_ep_agent_actions = [[] for i in range(agent_action_size)] # Play testing count @@ -124,53 +128,92 @@ def __init__(self, ep_total, agent_name, model_name, model, self.log_training_start_information() + # garante que todos os atributos de armazenamento de informações de treinamento sejam reiniciados, + # permitindo que um novo treinamento comece do zero. def reset(self): - self.ep_count = 0 + self.ep_count = 0 #define o número de episódios como zero - self.ep_rewards = [] - self.ep_avg_rewards = [] + self.ep_rewards = [] #limpa a lista de recompensas obtidas em cada episódio + self.ep_avg_rewards = [] #limpa a lista de recompensas médias obtidas em cada episódio - self.ep_steps_count = [] - self.ep_avg_steps = [] + self.ep_steps_count = [] #limpa a lista de contagens de passos executados em cada episódio + self.ep_avg_steps = [] #limpa a lista de contagens médias de passos executados em cada episódio - self.ep_victories = [] - self.ep_avg_victories = [] + self.ep_victories = [] #limpa a lista do número de vitórias obtido em cada episódio + self.ep_avg_victories = [] #limpa a lista do número médio de vitórias obtidos em cada episódio + # armazena a hora de início do episódio em questão.Isso é útil para calcular a duração de cada episódio de treinamento posteriormente. def record_episode_start(self): - self.episode_temp_start_time = time() + self.episode_temp_start_time = time() #variável que armazena o horário do início do episódio. def record_episode(self, ep_reward, has_won, steps_count, agent_info, ep_actions): + #contador do número total de episódios. self.ep_count += 1 + + #registra as ações tomadas pelo agente e calcula a média das ações tomadas até aquele ponto. for i in range(self.agent_action_size): - self.ep_agent_actions[i].append(ep_actions[i]) + + #adiciona a ação do episódio atual + self.ep_agent_actions[i].append(ep_actions[i]) + #calcula e adiciona a média das ações tomadas até este ponto. self.avg_ep_agent_actions[i].append(sum(self.ep_agent_actions[i]) / self.ep_count) + + #armazena a recompensa obtida no episódio atual self.ep_rewards.append(ep_reward) + #calcula e armazena a média das recompensas obtidas até este episódio self.ep_avg_rewards.append(sum(self.ep_rewards) / self.ep_count) + #adciona a contagem e a média da contagem de etapas que indica a quantidade de ações que o agente tomou durante um episódio. self.ep_steps_count.append(steps_count) self.ep_avg_steps.append(sum(self.ep_steps_count) / self.ep_count) # time and sps stuff - episode_duration = time() - self.episode_temp_start_time + #Essas métricas podem ajudar a avaliar o desempenho do agente ao longo do tempo e a identificar possíveis + # problemas ou melhorias que precisam ser feitas no modelo + #Essa parte do método calcula e armazena as métricas relacionadas + # à duração e ao desempenho do agente durante o episódio. + + #mede quanto tempo o episódio levou para ser concluído (diferença entre o tempo atual e o tempo de início do ep). + episode_duration = time() - self.episode_temp_start_time + #armazena a duração do episódio na lista que armazena a duração de cada episódio self.episode_duration_list.append(round(episode_duration, 1)) + if episode_duration != 0: + #número de etapas do agente por segundo em cada episódio self.episode_sps_list.append(round(steps_count / episode_duration, 2)) else: self.episode_sps_list.append(0) + #armazena a média do número de etapas por segundo para todos os episódios concluídos até agora. self.avg_sps_list.append(round(sum(self.episode_sps_list) / self.ep_count, 2)) + + # performance stuff + #uso da biblioteca psutil para coletar + # informações de uso do sistema em relação à CPU e à memória. + + #coleta a porcentagem de uso de memória atual do sistema. memory_usage_percent = psutil.virtual_memory().percent + + #calcula a porcentagem de memória disponível em relação ao total. memory_avail_percent = (psutil.virtual_memory().available * 100 / psutil.virtual_memory().total) + + #calcula a quantidade de memória em uso em gigabytes. memory_usage_gigs = psutil.virtual_memory().used / 1024 ** 3 + #calcula a quantidade de memória disponível em gigabytes. memory_avail_gigs = psutil.virtual_memory().free / 1024 ** 3 + #coleta a porcentagem de uso da CPU no momento. cpu_usage_percent = psutil.cpu_percent() # has GPU available + #Essa parte do código é responsável por tentar obter informações sobre a utilização da GPU (unidade de processamento gráfico) no sistema. + # Ele usa a biblioteca GPUtil para tentar acessar informações sobre a memória e a carga da GPU. + # Se conseguir acessar essas informações, ele armazena a porcentagem de uso de memória da GPU, o uso de memória da GPU em gigabytes e a porcentagem de uso da GPU. + # Caso contrário, ele define todos esses valores como 0. try: gpu_memory_usage_percent = GPUtil.getGPUs()[0].memoryUtil * 100 gpu_memory_usage_gigs = GPUtil.getGPUs()[0].memoryUsed / 1000 @@ -181,15 +224,25 @@ def record_episode(self, ep_reward, has_won, steps_count, agent_info, ep_actions gpu_memory_usage_gigs = 0 gpu_usage_percent = 0 + + # uso percentual atual da memória RAM; self.memory_usage_percent_inst.append(memory_usage_percent) + #uso percentual atual da memória da GPU (placa de vídeo); self.gpu_memory_usage_percent_inst.append(gpu_memory_usage_percent) + #uso atual de memória RAM em gigabytes; self.memory_usage_gigs_inst.append(memory_usage_gigs) + #uso atual de memória da GPU em gigabytes; self.gpu_memory_usage_gigs_inst.append(gpu_memory_usage_gigs) + #porcentagem de memória RAM disponível; self.memory_avail_percent_inst.append(memory_avail_percent) + #quantidade de memória RAM disponível em gigabytes; self.memory_avail_gigs_inst.append(memory_avail_gigs) + #uso percentual atual da CPU; self.cpu_usage_percent_inst.append(cpu_usage_percent) + #uso percentual atual da GPU (placa de vídeo). self.gpu_usage_percent_inst.append(gpu_usage_percent) + #calcula a média de todas as informações acima; self.memory_usage_percent_avg.append(sum(self.memory_usage_percent_inst) / self.ep_count) self.gpu_memory_usage_percent_avg.append( sum(self.gpu_memory_usage_percent_inst) / self.ep_count) @@ -200,24 +253,46 @@ def record_episode(self, ep_reward, has_won, steps_count, agent_info, ep_actions self.cpu_usage_percent_avg.append(sum(self.cpu_usage_percent_inst) / self.ep_count) self.gpu_usage_percent_avg.append(sum(self.gpu_usage_percent_inst) / self.ep_count) + #Essa parte do código verifica se o episódio atual tem uma recompensa (ep_reward) melhor do que + #a melhor recompensa registrada até agora (self.best_reward) e, se for o caso, + #atualiza a melhor recompensa (self.best_reward) + #e o episódio em que ela ocorreu (self.best_reward_episode) para o episódio atual (self.ep_count). + # Isso é útil para acompanhar o melhor desempenho alcançado pelo agente durante o treinamento. if ep_reward > self.best_reward: self.best_reward = ep_reward self.best_reward_episode = self.ep_count + + #Essa parte do código é responsável por monitorar a taxa de vitórias + # do agente em um ambiente de aprendizado episódico. + # A variável has_won é um booleano que indica se o agente venceu ou não o episódio atual. + # Se has_won for verdadeiro, então o valor 1 é adicionado à lista ep_victories, caso contrário, o valor 0 é adicionado. + # A lista ep_avg_victories é uma lista de média móvel que armazena a média das vitórias episódicas para cada episódio. if self.is_episodic: victory = 1 if has_won else 0 self.ep_victories.append(victory) self.ep_avg_victories.append(sum(self.ep_victories) / self.ep_count) + #Essa parte inicializa o dicionário self.agent_info com as chaves presentes no dicionário agent_info, se self.agent_info for None (ou seja, não foi inicializado antes). Em seguida, + #itera sobre as chaves em self.agent_info e define uma lista vazia como valor para cada uma dessas chaves. if self.agent_info is None: self.agent_info = dict.fromkeys(agent_info) for key in self.agent_info: self.agent_info[key] = [] + #Essa parte do método adiciona os valores dos dicionários do agent_info atual + #para a lista de histórico self.agent_info. O loop percorre cada chave + #do dicionário agent_info e adiciona o valor correspondente para a lista self.agent_info[key]. for key in agent_info: self.agent_info[key].append(agent_info[key]) # batch episode calculation + #Essa parte do código verifica se o número de episódios coletados é o primeiro ou um múltiplo + #de um parâmetro definido episode_batch_avg_calculation. + # Se for, a média das recompensas dos últimos episode_batch_avg_calculation episódios é calculada + # e adicionada à lista ep_avg_batch_rewards. + # Se for o primeiro episódio, a recompensa do episódio atual é adicionada à lista ep_avg_batch_rewards. + #A lista ep_avg_batch_rewards_episodes guarda os episódios em que a média das recompensas foi calculada. if self.ep_count == 1 or self.ep_count % self.episode_batch_avg_calculation == 0: if self.ep_count == 1: self.ep_avg_batch_rewards_episodes.append(self.ep_count)