colosseum.analysis.utils
1import os 2import re 3from glob import glob 4from typing import List, Tuple 5 6import numpy as np 7import pandas as pd 8 9from colosseum import config 10from colosseum.utils import ensure_folder 11from colosseum.utils.formatter import clear_agent_mdp_class_name 12 13 14def get_formatted_name(mdp_or_agent_class_name: str, mdp_or_agent_prms: str) -> str: 15 """ 16 provides a nice formatting for the name of an agent or MDP class and its corresponding gin config index. 17 18 Parameters 19 ---------- 20 mdp_or_agent_class_name : str 21 The str containing the name of an agent or MDP class. 22 mdp_or_agent_prms : str 23 The str containing the gin config prms of an agent or MDP. 24 25 Returns 26 ------- 27 str 28 A nicely formatted name for the MDP and the agent specification in input. 29 """ 30 return ( 31 clear_agent_mdp_class_name(mdp_or_agent_class_name) 32 + f" ({1 + int(re.findall('[0-9]+', mdp_or_agent_prms)[0])})" 33 ) 34 35 36def format_indicator_name(indicator: str) -> str: 37 """ 38 provides a nice formatting to the indicator code name in input. 39 40 Parameters 41 ---------- 42 indicator : str 43 The indicator code name. 44 45 Returns 46 ------- 47 str 48 A nicely formatted string. 49 """ 50 return indicator.replace("_", " ").replace("normalized", "norm.").capitalize() 51 52 53def get_available_mdps_agents_prms_and_names( 54 experiment_folder: str, 55) -> Tuple[List[Tuple[str, str]], List[Tuple[str, str]]]: 56 """ 57 retrieves the gin configurations for MDPs and agents from the experiment folder. 58 59 Parameters 60 ---------- 61 experiment_folder : str 62 The folder where the experiments are. 63 64 Returns 65 ------- 66 Tuple[List[Tuple[str, str]], List[Tuple[str, str]]] 67 The tuples of gin config parameters and MDPs/agents class names in the given experiment folder. 68 """ 69 logs_folders = os.listdir(f"{ensure_folder(experiment_folder)}logs{os.sep}") 70 available_mdps, available_agents = set(), set() 71 for logs_folder in logs_folders: 72 mdp_code, agent_code = logs_folder.split(config.EXPERIMENT_SEPARATOR_MDP_AGENT) 73 available_mdps.add( 74 tuple(mdp_code.split(config.EXPERIMENT_SEPARATOR_PRMS)[::-1]) 75 ) 76 available_agents.add( 77 tuple(agent_code.split(config.EXPERIMENT_SEPARATOR_PRMS)[::-1]) 78 ) 79 return sorted(available_mdps, key=lambda x: "".join(x)), sorted( 80 available_agents, key=lambda x: "".join(x) 81 ) 82 83 84def get_logs_data( 85 experiment_folder: str, 86 mdp_class_name: str, 87 mdp_prm: str, 88 agent_class_name: str, 89 agent_prm: str, 90) -> Tuple[pd.DataFrame, int]: 91 """ 92 retrieves the logging data of the experiment folder for the given mdp class, mdp gin config, agent class, and agent 93 gin config. 94 95 Parameters 96 ---------- 97 experiment_folder : str 98 The folder that contains the experiment logs, MDP configurations and agent configurations. 99 mdp_class_name : str 100 The name of the MDP class. 101 mdp_prm : str 102 The gin configuration parameter of the MDP. 103 agent_class_name 104 The name of the agent class. 105 agent_prm : str 106 The gin configuration parameter of the agent. 107 108 Returns 109 ------- 110 pd.DataFrame 111 The logging data stored as a pd.DataFrame. 112 int 113 The number of seeds of used in the experiment. 114 """ 115 116 mdp_code = mdp_prm + config.EXPERIMENT_SEPARATOR_PRMS + mdp_class_name 117 agent_code = agent_prm + config.EXPERIMENT_SEPARATOR_PRMS + agent_class_name 118 log_seed_files = glob( 119 f"{experiment_folder}{os.sep}logs{os.sep}{mdp_code}*{agent_code}{os.sep}*.csv" 120 ) 121 assert len(log_seed_files), f"No logs files found for {mdp_code}___{agent_code}" 122 dfs = [] 123 for log_seed_file in log_seed_files: 124 seed = int(log_seed_file[-10]) 125 df = pd.read_csv(log_seed_file) 126 df.loc[:, "seed"] = seed 127 df.loc[-1] = { 128 c: seed 129 if c == "seed" 130 else (df.loc[0, c] if c == "steps_per_second" else 0.0) 131 for c in df.columns 132 } 133 dfs.append(df.sort_index()) 134 return pd.concat(dfs).reset_index(drop=True), len(log_seed_files) 135 136 137def get_n_failed_interactions( 138 experiment_folder: str, 139 mdp_class_name: str, 140 mdp_prm: str, 141 agent_class_name: str, 142 agent_prm: str, 143) -> int: 144 """ 145 retrieves the number of times the agent config has failed to complete the total number of interaction in time in the 146 given MDP config. 147 148 Parameters 149 ---------- 150 experiment_folder : str 151 The folder that contains the experiment logs, MDP configurations and agent configurations. 152 mdp_class_name : str 153 The name of the MDP class. 154 mdp_prm : str 155 The gin configuration parameter of the MDP. 156 agent_class_name 157 The name of the agent class. 158 agent_prm : str 159 The gin configuration parameter of the agent. 160 161 Returns 162 ------- 163 int 164 The number of time the agent broke the computational time limit. 165 """ 166 167 mdp_code = mdp_prm + config.EXPERIMENT_SEPARATOR_PRMS + mdp_class_name 168 agent_code = agent_prm + config.EXPERIMENT_SEPARATOR_PRMS + agent_class_name 169 time_exceeded_file = ( 170 f"{ensure_folder(experiment_folder)}logs{os.sep}{mdp_code}" 171 f"{config.EXPERIMENT_SEPARATOR_MDP_AGENT}{agent_code}{os.sep}time_exceeded.txt" 172 ) 173 if os.path.isfile(time_exceeded_file): 174 with open(time_exceeded_file, "r") as f: 175 failed = set(f.readlines()) 176 return len(failed) 177 return 0 178 179 180def add_time_exceed_sign_to_plot( 181 ax, 182 df: pd.DataFrame, 183 color: str, 184 indicator: str, 185 n_seeds: int, 186 experiment_folder, 187 mdp_prm: str, 188 agent_prm: str, 189): 190 """ 191 adds the '}' symbol to the plot in the time corresponding to the average time the agent broke the computational time 192 limit. 193 194 Parameters 195 ---------- 196 ax : plt.Axes 197 The ax object where the symbol will be put. 198 df : pd.DataFrame 199 The logging data of the experiment for a given agent config and MDP config. 200 color : str 201 The code name for the color of the symbol. 202 indicator : str 203 is a string representing the performance indicator that is shown in the plot. Check `MDPLoop.get_indicators()` 204 to get a list of the available indicators. By default, the 'normalized_cumulative_regret' is used. 205 n_seeds : int 206 The total number of seed used in the experiment. 207 experiment_folder : str 208 The path of the directory containing the experiment results. 209 mdp_prm : str 210 The gin configuration parameter of the MDP. 211 agent_prm : str 212 The gin configuration parameter of the agent. 213 """ 214 215 time_exceeded_file = ( 216 f"{ensure_folder(experiment_folder)}logs{os.sep}{mdp_prm}" 217 f"{config.EXPERIMENT_SEPARATOR_MDP_AGENT}{agent_prm}{os.sep}time_exceeded.txt" 218 ) 219 if os.path.isfile(time_exceeded_file): 220 with open(time_exceeded_file, "r") as f: 221 failed = set(f.readlines()) 222 223 # Getting the average time step at which the training stopped for the different seeds 224 mean_time_step = 0 225 for fail in failed: 226 time_step = int(fail[fail.find("(") + 1 : fail.find(")")]) 227 mean_time_step += time_step / n_seeds 228 229 # Plot the stopped training symbol on the plot for the given measure 230 mean_time_step = df.loc[:, "steps"].tolist()[ 231 np.argmin(np.abs(df.loc[:, "steps"] - mean_time_step)) 232 ] 233 ax.text( 234 mean_time_step, 235 df[df.loc[:, "steps"] == mean_time_step].loc[:, indicator].mean(), 236 "}", 237 fontdict=dict(size=27), 238 verticalalignment="center", 239 color=color, 240 )
def
get_formatted_name(mdp_or_agent_class_name: str, mdp_or_agent_prms: str) -> str:
15def get_formatted_name(mdp_or_agent_class_name: str, mdp_or_agent_prms: str) -> str: 16 """ 17 provides a nice formatting for the name of an agent or MDP class and its corresponding gin config index. 18 19 Parameters 20 ---------- 21 mdp_or_agent_class_name : str 22 The str containing the name of an agent or MDP class. 23 mdp_or_agent_prms : str 24 The str containing the gin config prms of an agent or MDP. 25 26 Returns 27 ------- 28 str 29 A nicely formatted name for the MDP and the agent specification in input. 30 """ 31 return ( 32 clear_agent_mdp_class_name(mdp_or_agent_class_name) 33 + f" ({1 + int(re.findall('[0-9]+', mdp_or_agent_prms)[0])})" 34 )
provides a nice formatting for the name of an agent or MDP class and its corresponding gin config index.
Parameters
- mdp_or_agent_class_name (str): The str containing the name of an agent or MDP class.
- mdp_or_agent_prms (str): The str containing the gin config prms of an agent or MDP.
Returns
- str: A nicely formatted name for the MDP and the agent specification in input.
def
format_indicator_name(indicator: str) -> str:
37def format_indicator_name(indicator: str) -> str: 38 """ 39 provides a nice formatting to the indicator code name in input. 40 41 Parameters 42 ---------- 43 indicator : str 44 The indicator code name. 45 46 Returns 47 ------- 48 str 49 A nicely formatted string. 50 """ 51 return indicator.replace("_", " ").replace("normalized", "norm.").capitalize()
provides a nice formatting to the indicator code name in input.
Parameters
- indicator (str): The indicator code name.
Returns
- str: A nicely formatted string.
def
get_available_mdps_agents_prms_and_names( experiment_folder: str) -> Tuple[List[Tuple[str, str]], List[Tuple[str, str]]]:
54def get_available_mdps_agents_prms_and_names( 55 experiment_folder: str, 56) -> Tuple[List[Tuple[str, str]], List[Tuple[str, str]]]: 57 """ 58 retrieves the gin configurations for MDPs and agents from the experiment folder. 59 60 Parameters 61 ---------- 62 experiment_folder : str 63 The folder where the experiments are. 64 65 Returns 66 ------- 67 Tuple[List[Tuple[str, str]], List[Tuple[str, str]]] 68 The tuples of gin config parameters and MDPs/agents class names in the given experiment folder. 69 """ 70 logs_folders = os.listdir(f"{ensure_folder(experiment_folder)}logs{os.sep}") 71 available_mdps, available_agents = set(), set() 72 for logs_folder in logs_folders: 73 mdp_code, agent_code = logs_folder.split(config.EXPERIMENT_SEPARATOR_MDP_AGENT) 74 available_mdps.add( 75 tuple(mdp_code.split(config.EXPERIMENT_SEPARATOR_PRMS)[::-1]) 76 ) 77 available_agents.add( 78 tuple(agent_code.split(config.EXPERIMENT_SEPARATOR_PRMS)[::-1]) 79 ) 80 return sorted(available_mdps, key=lambda x: "".join(x)), sorted( 81 available_agents, key=lambda x: "".join(x) 82 )
retrieves the gin configurations for MDPs and agents from the experiment folder.
Parameters
- experiment_folder (str): The folder where the experiments are.
Returns
- Tuple[List[Tuple[str, str]], List[Tuple[str, str]]]: The tuples of gin config parameters and MDPs/agents class names in the given experiment folder.
def
get_logs_data( experiment_folder: str, mdp_class_name: str, mdp_prm: str, agent_class_name: str, agent_prm: str) -> Tuple[pandas.core.frame.DataFrame, int]:
85def get_logs_data( 86 experiment_folder: str, 87 mdp_class_name: str, 88 mdp_prm: str, 89 agent_class_name: str, 90 agent_prm: str, 91) -> Tuple[pd.DataFrame, int]: 92 """ 93 retrieves the logging data of the experiment folder for the given mdp class, mdp gin config, agent class, and agent 94 gin config. 95 96 Parameters 97 ---------- 98 experiment_folder : str 99 The folder that contains the experiment logs, MDP configurations and agent configurations. 100 mdp_class_name : str 101 The name of the MDP class. 102 mdp_prm : str 103 The gin configuration parameter of the MDP. 104 agent_class_name 105 The name of the agent class. 106 agent_prm : str 107 The gin configuration parameter of the agent. 108 109 Returns 110 ------- 111 pd.DataFrame 112 The logging data stored as a pd.DataFrame. 113 int 114 The number of seeds of used in the experiment. 115 """ 116 117 mdp_code = mdp_prm + config.EXPERIMENT_SEPARATOR_PRMS + mdp_class_name 118 agent_code = agent_prm + config.EXPERIMENT_SEPARATOR_PRMS + agent_class_name 119 log_seed_files = glob( 120 f"{experiment_folder}{os.sep}logs{os.sep}{mdp_code}*{agent_code}{os.sep}*.csv" 121 ) 122 assert len(log_seed_files), f"No logs files found for {mdp_code}___{agent_code}" 123 dfs = [] 124 for log_seed_file in log_seed_files: 125 seed = int(log_seed_file[-10]) 126 df = pd.read_csv(log_seed_file) 127 df.loc[:, "seed"] = seed 128 df.loc[-1] = { 129 c: seed 130 if c == "seed" 131 else (df.loc[0, c] if c == "steps_per_second" else 0.0) 132 for c in df.columns 133 } 134 dfs.append(df.sort_index()) 135 return pd.concat(dfs).reset_index(drop=True), len(log_seed_files)
retrieves the logging data of the experiment folder for the given mdp class, mdp gin config, agent class, and agent gin config.
Parameters
- experiment_folder (str): The folder that contains the experiment logs, MDP configurations and agent configurations.
- mdp_class_name (str): The name of the MDP class.
- mdp_prm (str): The gin configuration parameter of the MDP.
- agent_class_name: The name of the agent class.
- agent_prm (str): The gin configuration parameter of the agent.
Returns
- pd.DataFrame: The logging data stored as a pd.DataFrame.
- int: The number of seeds of used in the experiment.
def
get_n_failed_interactions( experiment_folder: str, mdp_class_name: str, mdp_prm: str, agent_class_name: str, agent_prm: str) -> int:
138def get_n_failed_interactions( 139 experiment_folder: str, 140 mdp_class_name: str, 141 mdp_prm: str, 142 agent_class_name: str, 143 agent_prm: str, 144) -> int: 145 """ 146 retrieves the number of times the agent config has failed to complete the total number of interaction in time in the 147 given MDP config. 148 149 Parameters 150 ---------- 151 experiment_folder : str 152 The folder that contains the experiment logs, MDP configurations and agent configurations. 153 mdp_class_name : str 154 The name of the MDP class. 155 mdp_prm : str 156 The gin configuration parameter of the MDP. 157 agent_class_name 158 The name of the agent class. 159 agent_prm : str 160 The gin configuration parameter of the agent. 161 162 Returns 163 ------- 164 int 165 The number of time the agent broke the computational time limit. 166 """ 167 168 mdp_code = mdp_prm + config.EXPERIMENT_SEPARATOR_PRMS + mdp_class_name 169 agent_code = agent_prm + config.EXPERIMENT_SEPARATOR_PRMS + agent_class_name 170 time_exceeded_file = ( 171 f"{ensure_folder(experiment_folder)}logs{os.sep}{mdp_code}" 172 f"{config.EXPERIMENT_SEPARATOR_MDP_AGENT}{agent_code}{os.sep}time_exceeded.txt" 173 ) 174 if os.path.isfile(time_exceeded_file): 175 with open(time_exceeded_file, "r") as f: 176 failed = set(f.readlines()) 177 return len(failed) 178 return 0
retrieves the number of times the agent config has failed to complete the total number of interaction in time in the given MDP config.
Parameters
- experiment_folder (str): The folder that contains the experiment logs, MDP configurations and agent configurations.
- mdp_class_name (str): The name of the MDP class.
- mdp_prm (str): The gin configuration parameter of the MDP.
- agent_class_name: The name of the agent class.
- agent_prm (str): The gin configuration parameter of the agent.
Returns
- int: The number of time the agent broke the computational time limit.
def
add_time_exceed_sign_to_plot( ax, df: pandas.core.frame.DataFrame, color: str, indicator: str, n_seeds: int, experiment_folder, mdp_prm: str, agent_prm: str):
181def add_time_exceed_sign_to_plot( 182 ax, 183 df: pd.DataFrame, 184 color: str, 185 indicator: str, 186 n_seeds: int, 187 experiment_folder, 188 mdp_prm: str, 189 agent_prm: str, 190): 191 """ 192 adds the '}' symbol to the plot in the time corresponding to the average time the agent broke the computational time 193 limit. 194 195 Parameters 196 ---------- 197 ax : plt.Axes 198 The ax object where the symbol will be put. 199 df : pd.DataFrame 200 The logging data of the experiment for a given agent config and MDP config. 201 color : str 202 The code name for the color of the symbol. 203 indicator : str 204 is a string representing the performance indicator that is shown in the plot. Check `MDPLoop.get_indicators()` 205 to get a list of the available indicators. By default, the 'normalized_cumulative_regret' is used. 206 n_seeds : int 207 The total number of seed used in the experiment. 208 experiment_folder : str 209 The path of the directory containing the experiment results. 210 mdp_prm : str 211 The gin configuration parameter of the MDP. 212 agent_prm : str 213 The gin configuration parameter of the agent. 214 """ 215 216 time_exceeded_file = ( 217 f"{ensure_folder(experiment_folder)}logs{os.sep}{mdp_prm}" 218 f"{config.EXPERIMENT_SEPARATOR_MDP_AGENT}{agent_prm}{os.sep}time_exceeded.txt" 219 ) 220 if os.path.isfile(time_exceeded_file): 221 with open(time_exceeded_file, "r") as f: 222 failed = set(f.readlines()) 223 224 # Getting the average time step at which the training stopped for the different seeds 225 mean_time_step = 0 226 for fail in failed: 227 time_step = int(fail[fail.find("(") + 1 : fail.find(")")]) 228 mean_time_step += time_step / n_seeds 229 230 # Plot the stopped training symbol on the plot for the given measure 231 mean_time_step = df.loc[:, "steps"].tolist()[ 232 np.argmin(np.abs(df.loc[:, "steps"] - mean_time_step)) 233 ] 234 ax.text( 235 mean_time_step, 236 df[df.loc[:, "steps"] == mean_time_step].loc[:, indicator].mean(), 237 "}", 238 fontdict=dict(size=27), 239 verticalalignment="center", 240 color=color, 241 )
adds the '}' symbol to the plot in the time corresponding to the average time the agent broke the computational time limit.
Parameters
- ax (plt.Axes): The ax object where the symbol will be put.
- df (pd.DataFrame): The logging data of the experiment for a given agent config and MDP config.
- color (str): The code name for the color of the symbol.
- indicator (str):
is a string representing the performance indicator that is shown in the plot. Check
MDPLoop.get_indicators()
to get a list of the available indicators. By default, the 'normalized_cumulative_regret' is used. - n_seeds (int): The total number of seed used in the experiment.
- experiment_folder (str): The path of the directory containing the experiment results.
- mdp_prm (str): The gin configuration parameter of the MDP.
- agent_prm (str): The gin configuration parameter of the agent.