colosseum.analysis.plots
1import os 2import re 3from string import ascii_lowercase 4from typing import ( 5 TYPE_CHECKING, 6 Callable, 7 List, 8 Tuple, 9 Union, 10 Dict, 11 Type, 12 Iterable, 13 Optional, 14) 15 16import gin 17import matplotlib 18import numpy as np 19import seaborn as sns 20from adjustText import adjust_text 21from matplotlib import pyplot as plt 22from tqdm import tqdm 23 24from colosseum import config 25from colosseum.analysis.tables import get_latex_table_of_average_indicator 26from colosseum.analysis.utils import get_available_mdps_agents_prms_and_names 27from colosseum.analysis.utils import get_formatted_name 28from colosseum.analysis.utils import get_logs_data, add_time_exceed_sign_to_plot 29from colosseum.experiment.agent_mdp_interaction import MDPLoop 30from colosseum.experiment.folder_structuring import get_experiment_config 31from colosseum.experiment.folder_structuring import get_mdp_agent_gin_configs 32from colosseum.experiment.utils import apply_gin_config 33from colosseum.hardness.analysis import compute_hardness_measure 34from colosseum.utils import ensure_folder 35from colosseum.utils.formatter import clear_agent_mdp_class_name 36 37if TYPE_CHECKING: 38 from colosseum.mdp import BaseMDP 39 from matplotlib.figure import Figure 40 41sns.set_theme() 42 43 44def _get_index(x): 45 return clear_agent_mdp_class_name(x[0].__name__), x[1] 46 47 48def agent_performances_per_mdp_plot( 49 experiment_folder: str, 50 indicator: str, 51 figsize_scale: int = 8, 52 standard_error: bool = False, 53 color_palette: List[str] = matplotlib.colors.TABLEAU_COLORS.keys(), 54 n_rows=None, 55 savefig_folder=None, 56 baselines=MDPLoop.get_baselines(), 57) -> "Figure": 58 """ 59 produces a plot in which the performance indicator of the agents is shown for each MDP for the given experiment 60 results. 61 62 Parameters 63 ---------- 64 experiment_folder : str 65 The folder that contains the experiment logs, MDP configurations and agent configurations. 66 indicator : str 67 The code name of the performance indicator that will be shown in the plot. Check `MDPLoop.get_indicators()` to 68 get a list of the available indicators. 69 figsize_scale : int 70 The scale for size of the figure in the resulting plot. The default value is 8. 71 standard_error : bool 72 If True standard errors are computed instead of the bootstrapping estimates in seaborn. 73 color_palette : List[str] 74 The colors to be assigned to the agents. By default, the tableau colors are used. 75 n_rows : int 76 The number of rows for the grid of plots. By default, it is computed to create a square grid. 77 savefig_folder : str 78 The folder where the figure will be saved. By default, the figure it is not saved. 79 baselines : List[str] 80 The baselines to be included in the plot. Check `MDPLoop.get_baselines()` to get a list of the available 81 baselines. By default, all baselines are shown. 82 83 Returns 84 ------- 85 Figure 86 The matplotlib figure. 87 """ 88 89 # Check the inputs 90 assert ( 91 indicator in MDPLoop.get_indicators() 92 ), f"Please check that the indicator given in input is one from {MDPLoop.get_indicators()}." 93 assert all( 94 b in MDPLoop.get_baselines() for b in baselines 95 ), f"Please check that the baselines given in input are available." 96 97 # Retrieve the MDPs and agents configurations from the experiment folder 98 available_mdps, available_agents = get_available_mdps_agents_prms_and_names( 99 experiment_folder 100 ) 101 102 # Variables for the plots 103 colors_dict_agents = dict(zip(available_agents, color_palette)) 104 n_plots = len(available_mdps) 105 h = int(np.ceil(n_plots ** 0.5)) if n_rows is None else n_rows 106 w = int(np.ceil(n_plots / h)) 107 fig, axes = plt.subplots( 108 h, 109 w, 110 figsize=(w * figsize_scale, h * figsize_scale), 111 sharex=True, 112 # If the indicator is normalized we can also share the indicator axis 113 sharey="normaliz" in indicator, 114 ) 115 if config.VERBOSE_LEVEL != 0: 116 available_mdps = tqdm( 117 sorted(available_mdps, key=lambda x: "".join(x)), 118 desc="Plotting the results", 119 ) 120 else: 121 available_mdps = sorted(available_mdps, key=lambda x: "".join(x)) 122 123 for i, available_mdp in enumerate(available_mdps): 124 ax = axes.ravel()[i] 125 mdp_formatted_name = get_formatted_name(*available_mdp) 126 group_by_mdp_individual_plot( 127 experiment_folder, 128 ax, 129 indicator, 130 *available_mdp, 131 available_agents, 132 colors_dict_agents, 133 standard_error=standard_error, 134 baselines=baselines, 135 ) 136 ax.set_title(mdp_formatted_name) 137 ax.legend() 138 ax.ticklabel_format(style="sci", scilimits=(0, 4)) 139 140 # Remove unused axes 141 for j in range(i + 1, len(axes.ravel())): 142 fig.delaxes(axes.ravel()[j]) 143 144 # Last touches 145 plt.ticklabel_format(style="sci", scilimits=(0, 4)) 146 plt.tight_layout() 147 148 if savefig_folder is not None: 149 os.makedirs(savefig_folder, exist_ok=True) 150 exp_name = os.path.basename(os.path.dirname(ensure_folder(experiment_folder))) 151 plt.savefig( 152 f"{ensure_folder(savefig_folder)}{indicator}-for-{exp_name}.pdf", 153 bbox_inches="tight", 154 ) 155 156 plt.show() 157 158 return fig 159 160 161def get_hardness_measures_from_experiment_folder( 162 experiment_folder: str, 163 hardness_measures: Iterable[str] = ("diameter", "value_norm", "suboptimal_gaps"), 164 reduce_seed: Callable[[List[float]], float] = np.mean, 165) -> Dict[Tuple[Type["BaseMDP"], str], Dict[str, float]]: 166 """ 167 retrieves the given measures of hardness for each mdp and mdp gin config in the experiment folder. 168 169 Parameters 170 ---------- 171 experiment_folder : str 172 The folder that contains the experiment logs, MDP configurations and agent configurations. 173 hardness_measures : Iterable[str] 174 The list containing the measures of hardness to compute. 175 reduce_seed : Callable[[List[float]], float], optional 176 The function that reduces the values of the measures for different seed to a single scalar. By default, the 177 mean function is employed. 178 179 Returns 180 ------- 181 Dict[Tuple[Type["BaseMDP"], str], Dict[str, float]] 182 The dictionary that assigns to each MDP class and gin config index the corresponding dictionary containing the 183 hardness measures names and values. 184 """ 185 186 # Retrieve the gin configurations of the agents and MDPs 187 ( 188 mdp_classes_scopes, 189 agent_classes_scopes, 190 gin_config_files_paths, 191 ) = get_mdp_agent_gin_configs(experiment_folder) 192 193 # Retrieve the number of seeds 194 n_seeds = get_experiment_config(experiment_folder).n_seeds 195 196 res = dict() 197 for mdp_class, mdp_scopes in tqdm( 198 mdp_classes_scopes.items(), desc=os.path.basename(experiment_folder) 199 ): 200 for mdp_scope in mdp_scopes: 201 apply_gin_config(gin_config_files_paths) 202 with gin.config_scope(mdp_scope): 203 res[mdp_class, mdp_scope] = { 204 hm: reduce_seed( 205 [ 206 compute_hardness_measure(mdp_class, dict(seed=seed), hm) 207 for seed in range(n_seeds) 208 ] 209 ) 210 for hm in hardness_measures 211 } 212 return res 213 214 215def plot_labels_on_benchmarks_hardness_space( 216 experiment_folder: str, 217 text_f: Callable[[Tuple[str, str]], str], 218 color_f: Callable[[Tuple[str, str]], Union[str, None]] = lambda x: None, 219 label_f: Callable[[Tuple[str, str]], Union[str, None]] = lambda x: None, 220 ax: plt.Axes = None, 221 multiplicative_factor_xlim=1.0, 222 multiplicative_factor_ylim=1.0, 223 legend_ncol=1, 224 underneath_x_label: str = None, 225 set_ylabel=True, 226 set_legend=True, 227 xaxis_measure: Union[str, Tuple[str, Callable[["BaseMDP"], float]]] = "diameter", 228 yaxis_measure: Union[str, Tuple[str, Callable[["BaseMDP"], float]]] = "value_norm", 229 fontsize: int = 22, 230 fontsize_xlabel_underneath: int = 32, 231 text_label_fontsize=16, 232): 233 """ 234 for each agent configuration in the experiment folder, it produces a plot such that it is possible to place a text 235 label in the position corresponding to the value of the x-axis measure and indicator-axis measure. In addition to the text, 236 it is also possible choose the color assigned to the point in such position. 237 238 Parameters 239 ---------- 240 experiment_folder : str 241 The folder that contains the experiment logs, MDP configurations and agent configurations. 242 text_f : Callable[[Tuple[str, str]], str] 243 The function that returns a text label for a given MDP class name and gin config index. For example, 244 ('DeepSeaEpisodic', 'prms_0') -> "DeepSeaEpisodic (0)". 245 color_f : Callable[[Tuple[str, str]], str] 246 The function that returns the color for the point in the position corresponding to a given MDP class name and 247 gin config index. For example, ('DeepSeaEpisodic', 'prms_0') -> "DeepSeaEpisodic (0)". By default, no particular 248 color is specified. 249 label_f : Callable[[Tuple[str, str]], str] 250 The function that returns the label to be put in the legend for the point in the position corresponding to a 251 given MDP class name and gin config index. For example, ('DeepSeaEpisodic', 'prms_0') -> "DeepSea family". 252 By default, the legend is not included in the plot. 253 ax : plt.Axes 254 The ax object where the plot will be put. By default, a new axis is created. 255 multiplicative_factor_xlim : float 256 The additional space to add on the right side of the figure. It can be useful to add space for the legend. By 257 default, it is set to one. 258 multiplicative_factor_ylim : float 259 The additional space to add on the top side of the figure. It can be useful to add space for the legend. By 260 default, it is set to one. 261 legend_ncol : int 262 The number of columns in the legend. By default, it is set to one. 263 underneath_x_label : str 264 Text to be added underneath the x_label. By default, no text is added. 265 set_ylabel : bool 266 If True, the indicator-label is set to the name of the indicator-axis measure. By default, the indicator-label is set. 267 set_legend : bool 268 If True, the legend is set. By default, the legend is set. 269 xaxis_measure : str 270 The code name of the hardness measures available in the package. Check `BaseMDP.get_available_hardness_measures()` 271 to get to know the available ones. By default, it is set to the diameter. 272 yaxis_measure : str 273 The code name of the hardness measures available in the package. Check `BaseMDP.get_available_hardness_measures()`. 274 to get to know the available ones. By default, it is set to the value norm. 275 fontsize : int 276 The font size for x and indicator labels. By default, it is set to :math:`22`. 277 fontsize_xlabel_underneath : 278 The font size for the text below the x label. By default, it is set to :math:`32`. 279 text_label_fontsize : int 280 The font size for the text labels of the points. By default, it is set to :math:`16`. 281 """ 282 283 show = ax is None 284 if ax is None: 285 fig, ax = plt.subplots(1, 1, figsize=(8, 8)) 286 set_ylabel = True 287 288 hardness_measures = get_hardness_measures_from_experiment_folder( 289 experiment_folder, (xaxis_measure, yaxis_measure) 290 ) 291 texts = [] 292 for k, r in hardness_measures.items(): 293 texts.append( 294 ax.text( 295 r[xaxis_measure], 296 r[yaxis_measure], 297 text_f(k), 298 fontdict=dict(fontsize=text_label_fontsize), 299 ) 300 ) 301 ax.scatter( 302 r[xaxis_measure], 303 r[yaxis_measure], 304 500, 305 color=color_f(k), 306 label=label_f(k), 307 edgecolor="black", 308 linewidths=0.5, 309 ) 310 311 ax.tick_params(labelsize=22) 312 if set_ylabel: 313 ax.set_ylabel( 314 yaxis_measure.capitalize().replace("_", " "), 315 fontdict=dict(fontsize=fontsize), 316 labelpad=10, 317 ) 318 ax.set_xlabel( 319 xaxis_measure.capitalize().replace("_", " "), 320 fontdict=dict(fontsize=fontsize), 321 labelpad=15, 322 ha="center", 323 ) 324 325 xlim = ax.get_xlim() 326 ax.set_xlim(xlim[0], xlim[1] * multiplicative_factor_xlim) 327 ylim = ax.get_ylim() 328 ax.set_ylim(ylim[0], ylim[1] * multiplicative_factor_ylim) 329 330 if type(underneath_x_label) == str: 331 ax.text( 332 np.mean(ax.get_xlim()), 333 ylim[0] - 0.28 * (ylim[1] - ylim[0]), 334 underneath_x_label, 335 fontdict=dict(fontsize=fontsize_xlabel_underneath), 336 ha="center", 337 ) 338 339 if set_legend: 340 h, l = ax.get_legend_handles_labels() 341 if h: 342 ax.legend(ncol=legend_ncol) 343 344 plt.tight_layout() 345 adjust_text( 346 texts, 347 ax=ax, 348 expand_text=(1.05, 1.8), 349 expand_points=(1.05, 1.5), 350 only_move={"points": "indicator", "text": "xy"}, 351 precision=0.0001, 352 lim=1000, 353 ) 354 355 if show: 356 plt.tight_layout() 357 plt.show() 358 359 360def plot_indicator_in_hardness_space( 361 experiment_folder: str, 362 indicator: str = "normalized_cumulative_regret", 363 fontsize: int = 22, 364 cmap: str = "Reds", 365 fig_size=8, 366 text_label_fontsize=14, 367 savefig_folder: Optional[str] = "tmp", 368) -> "Figure": 369 """ 370 for each agent config, it produces a plot that places the given indicator obtained by the agent config for each MDP 371 config in the position corresponding to the diameter and value norm of the MDP. 372 373 Parameters 374 ---------- 375 experiment_folder : str 376 The path of the directory containing the experiment results. 377 indicator : str 378 is a string representing the performance indicator that is shown in the plot. Check `MDPLoop.get_indicators()` 379 to get a list of the available indicators. By default, the 'normalized_cumulative_regret' is used. 380 fontsize : int 381 The font size for x and indicator labels. By default, it is set to :math:`22`. 382 cmap : str 383 The code name for the color map to be used when plotting the indicator values. By default, 384 the 'Reds' color map is used. 385 fig_size : int 386 The size of the figures in the grid of plots. By default, it is set to :math:`8`. 387 text_label_fontsize : int 388 The font size for the text labels of the points. By default, it is set to :math:`14`. 389 savefig_folder : str 390 The folder where the figure will be saved. By default, the figure it is saved in a local folder with name 'tmp'. 391 If the directory does not exist, it is created. 392 393 Returns 394 ------- 395 Figure 396 The matplotlib figure. 397 """ 398 399 color_map = matplotlib.cm.get_cmap(cmap) 400 _, df = get_latex_table_of_average_indicator( 401 experiment_folder, 402 indicator, 403 show_prm=True, 404 return_table=True, 405 mdps_on_row=False, 406 ) 407 df_numerical = df.applymap(lambda s: float(re.findall("\d+\.\d+", s)[0])) 408 fig, axes = plt.subplots( 409 1, len(df.index), figsize=(len(df.index) * fig_size + 1, fig_size), sharey=True 410 ) 411 if len(df.index) == 1: 412 axes = np.array([axes]) 413 for i, (a, ax) in enumerate(zip(df.index, axes.tolist())): 414 plot_labels_on_benchmarks_hardness_space( 415 experiment_folder, 416 label_f=lambda x: None, 417 color_f=lambda x: color_map( 418 df_numerical.loc[a, _get_index(x)] / df_numerical.loc[a].max() 419 ), 420 text_f=lambda x: f"{_get_index(x)[0].replace('MiniGrid', 'MG-')} " 421 f"({(_get_index(x)[1].replace('prms_', ''))})", 422 # text_f=lambda x: "", 423 ax=ax, 424 fontsize=fontsize, 425 text_label_fontsize=text_label_fontsize, 426 underneath_x_label=f"({ascii_lowercase[i]}) {a[0]}", 427 ) 428 # ax.set_title( 429 # f"({ascii_lowercase[i]}) {a[0]}", 430 # fontdict=dict(legend_fontsize=legend_fontsize + 4), 431 # indicator=-0.28, 432 # ) 433 434 plt.tight_layout() 435 436 if savefig_folder is not None: 437 os.makedirs(savefig_folder, exist_ok=True) 438 exp_name = os.path.basename(os.path.dirname(ensure_folder(experiment_folder))) 439 plt.savefig( 440 f"{ensure_folder(savefig_folder)}{indicator}_in_hard_space_{exp_name}.pdf", 441 bbox_inches="tight", 442 ) 443 plt.show() 444 445 return fig 446 447 448def group_by_mdp_individual_plot( 449 experiment_folder: str, 450 ax, 451 measure: str, 452 mdp_class_name: str, 453 mdp_prms: str, 454 available_agents: List[Tuple[str, str]], 455 colors_dict_agents: Dict[Tuple[str, str], str], 456 standard_error: bool = False, 457 baselines=MDPLoop.get_baselines(), 458): 459 """ 460 plots the measure for the given agents and experiment fold in the given axes. 461 462 Parameters 463 ---------- 464 experiment_folder : str 465 is the folder that contains the experiment logs, MDP configurations and agent configurations. 466 ax : plt.Axes 467 is where the plot will be shown. 468 measure : str 469 is a string representing the performance measure that is shown in the plot. Check 470 MDPLoop.get_indicators() to get a list of the available indicators. 471 mdp_prms : str 472 is a string that contains the mdp parameter gin config parameter, i.e. 'prms_0'. 473 mdp_class_name : str 474 is a string that contains the mdp class name. 475 available_agents : List[Tuple[str, str]] 476 is a list containing the agent gin config parameters and the agent class names. 477 colors_dict_agents : Dict[Tuple[str, str], str] 478 is a dict that assign to each agent gin config parameter and agent class name a different color. 479 """ 480 mdp_code = mdp_prms + config.EXPERIMENT_SEPARATOR_PRMS + mdp_class_name 481 482 for available_agent in available_agents: 483 agent_code = ( 484 available_agent[1] + config.EXPERIMENT_SEPARATOR_PRMS + available_agent[0] 485 ) 486 agent_formatted_name = get_formatted_name(*available_agent) 487 df, n_seeds = get_logs_data( 488 experiment_folder, mdp_class_name, mdp_prms, *available_agent 489 ) 490 491 for b in baselines: 492 y = measure.replace("cumulative_reward", "cumulative_expected_reward") 493 if b + "_" + y in MDPLoop.get_baseline_indicators(): 494 sns.lineplot( 495 x="steps", 496 y=b + "_" + y, 497 label=b.capitalize() + " agent", 498 data=df, 499 ax=ax, 500 errorbar=None, 501 color=MDPLoop.get_baselines_color_dict()[b], 502 linestyle=MDPLoop.get_baselines_style_dict()[b], 503 linewidth=2, 504 ) 505 506 # We plot the baselines only once 507 baselines = [] 508 509 add_time_exceed_sign_to_plot( 510 ax, 511 df, 512 colors_dict_agents[available_agent], 513 measure, 514 n_seeds, 515 experiment_folder, 516 mdp_code, 517 agent_code, 518 ) 519 sns_ax = sns.lineplot( 520 x="steps", 521 y=measure, 522 label=agent_formatted_name, 523 data=df, 524 ax=ax, 525 errorbar="se" if standard_error else ("ci", 95), 526 color=colors_dict_agents[available_agent], 527 ) 528 sns_ax.set_ylabel(" ".join(map(lambda x: x.capitalize(), measure.split("_"))))
49def agent_performances_per_mdp_plot( 50 experiment_folder: str, 51 indicator: str, 52 figsize_scale: int = 8, 53 standard_error: bool = False, 54 color_palette: List[str] = matplotlib.colors.TABLEAU_COLORS.keys(), 55 n_rows=None, 56 savefig_folder=None, 57 baselines=MDPLoop.get_baselines(), 58) -> "Figure": 59 """ 60 produces a plot in which the performance indicator of the agents is shown for each MDP for the given experiment 61 results. 62 63 Parameters 64 ---------- 65 experiment_folder : str 66 The folder that contains the experiment logs, MDP configurations and agent configurations. 67 indicator : str 68 The code name of the performance indicator that will be shown in the plot. Check `MDPLoop.get_indicators()` to 69 get a list of the available indicators. 70 figsize_scale : int 71 The scale for size of the figure in the resulting plot. The default value is 8. 72 standard_error : bool 73 If True standard errors are computed instead of the bootstrapping estimates in seaborn. 74 color_palette : List[str] 75 The colors to be assigned to the agents. By default, the tableau colors are used. 76 n_rows : int 77 The number of rows for the grid of plots. By default, it is computed to create a square grid. 78 savefig_folder : str 79 The folder where the figure will be saved. By default, the figure it is not saved. 80 baselines : List[str] 81 The baselines to be included in the plot. Check `MDPLoop.get_baselines()` to get a list of the available 82 baselines. By default, all baselines are shown. 83 84 Returns 85 ------- 86 Figure 87 The matplotlib figure. 88 """ 89 90 # Check the inputs 91 assert ( 92 indicator in MDPLoop.get_indicators() 93 ), f"Please check that the indicator given in input is one from {MDPLoop.get_indicators()}." 94 assert all( 95 b in MDPLoop.get_baselines() for b in baselines 96 ), f"Please check that the baselines given in input are available." 97 98 # Retrieve the MDPs and agents configurations from the experiment folder 99 available_mdps, available_agents = get_available_mdps_agents_prms_and_names( 100 experiment_folder 101 ) 102 103 # Variables for the plots 104 colors_dict_agents = dict(zip(available_agents, color_palette)) 105 n_plots = len(available_mdps) 106 h = int(np.ceil(n_plots ** 0.5)) if n_rows is None else n_rows 107 w = int(np.ceil(n_plots / h)) 108 fig, axes = plt.subplots( 109 h, 110 w, 111 figsize=(w * figsize_scale, h * figsize_scale), 112 sharex=True, 113 # If the indicator is normalized we can also share the indicator axis 114 sharey="normaliz" in indicator, 115 ) 116 if config.VERBOSE_LEVEL != 0: 117 available_mdps = tqdm( 118 sorted(available_mdps, key=lambda x: "".join(x)), 119 desc="Plotting the results", 120 ) 121 else: 122 available_mdps = sorted(available_mdps, key=lambda x: "".join(x)) 123 124 for i, available_mdp in enumerate(available_mdps): 125 ax = axes.ravel()[i] 126 mdp_formatted_name = get_formatted_name(*available_mdp) 127 group_by_mdp_individual_plot( 128 experiment_folder, 129 ax, 130 indicator, 131 *available_mdp, 132 available_agents, 133 colors_dict_agents, 134 standard_error=standard_error, 135 baselines=baselines, 136 ) 137 ax.set_title(mdp_formatted_name) 138 ax.legend() 139 ax.ticklabel_format(style="sci", scilimits=(0, 4)) 140 141 # Remove unused axes 142 for j in range(i + 1, len(axes.ravel())): 143 fig.delaxes(axes.ravel()[j]) 144 145 # Last touches 146 plt.ticklabel_format(style="sci", scilimits=(0, 4)) 147 plt.tight_layout() 148 149 if savefig_folder is not None: 150 os.makedirs(savefig_folder, exist_ok=True) 151 exp_name = os.path.basename(os.path.dirname(ensure_folder(experiment_folder))) 152 plt.savefig( 153 f"{ensure_folder(savefig_folder)}{indicator}-for-{exp_name}.pdf", 154 bbox_inches="tight", 155 ) 156 157 plt.show() 158 159 return fig
produces a plot in which the performance indicator of the agents is shown for each MDP for the given experiment results.
Parameters
- experiment_folder (str): The folder that contains the experiment logs, MDP configurations and agent configurations.
- indicator (str):
The code name of the performance indicator that will be shown in the plot. Check
MDPLoop.get_indicators()
to get a list of the available indicators. - figsize_scale (int): The scale for size of the figure in the resulting plot. The default value is 8.
- standard_error (bool): If True standard errors are computed instead of the bootstrapping estimates in seaborn.
- color_palette (List[str]): The colors to be assigned to the agents. By default, the tableau colors are used.
- n_rows (int): The number of rows for the grid of plots. By default, it is computed to create a square grid.
- savefig_folder (str): The folder where the figure will be saved. By default, the figure it is not saved.
- baselines (List[str]):
The baselines to be included in the plot. Check
MDPLoop.get_baselines()
to get a list of the available baselines. By default, all baselines are shown.
Returns
- Figure: The matplotlib figure.
162def get_hardness_measures_from_experiment_folder( 163 experiment_folder: str, 164 hardness_measures: Iterable[str] = ("diameter", "value_norm", "suboptimal_gaps"), 165 reduce_seed: Callable[[List[float]], float] = np.mean, 166) -> Dict[Tuple[Type["BaseMDP"], str], Dict[str, float]]: 167 """ 168 retrieves the given measures of hardness for each mdp and mdp gin config in the experiment folder. 169 170 Parameters 171 ---------- 172 experiment_folder : str 173 The folder that contains the experiment logs, MDP configurations and agent configurations. 174 hardness_measures : Iterable[str] 175 The list containing the measures of hardness to compute. 176 reduce_seed : Callable[[List[float]], float], optional 177 The function that reduces the values of the measures for different seed to a single scalar. By default, the 178 mean function is employed. 179 180 Returns 181 ------- 182 Dict[Tuple[Type["BaseMDP"], str], Dict[str, float]] 183 The dictionary that assigns to each MDP class and gin config index the corresponding dictionary containing the 184 hardness measures names and values. 185 """ 186 187 # Retrieve the gin configurations of the agents and MDPs 188 ( 189 mdp_classes_scopes, 190 agent_classes_scopes, 191 gin_config_files_paths, 192 ) = get_mdp_agent_gin_configs(experiment_folder) 193 194 # Retrieve the number of seeds 195 n_seeds = get_experiment_config(experiment_folder).n_seeds 196 197 res = dict() 198 for mdp_class, mdp_scopes in tqdm( 199 mdp_classes_scopes.items(), desc=os.path.basename(experiment_folder) 200 ): 201 for mdp_scope in mdp_scopes: 202 apply_gin_config(gin_config_files_paths) 203 with gin.config_scope(mdp_scope): 204 res[mdp_class, mdp_scope] = { 205 hm: reduce_seed( 206 [ 207 compute_hardness_measure(mdp_class, dict(seed=seed), hm) 208 for seed in range(n_seeds) 209 ] 210 ) 211 for hm in hardness_measures 212 } 213 return res
retrieves the given measures of hardness for each mdp and mdp gin config in the experiment folder.
Parameters
- experiment_folder (str): The folder that contains the experiment logs, MDP configurations and agent configurations.
- hardness_measures (Iterable[str]): The list containing the measures of hardness to compute.
- reduce_seed (Callable[[List[float]], float], optional): The function that reduces the values of the measures for different seed to a single scalar. By default, the mean function is employed.
Returns
- Dict[Tuple[Type["BaseMDP"], str], Dict[str, float]]: The dictionary that assigns to each MDP class and gin config index the corresponding dictionary containing the hardness measures names and values.
216def plot_labels_on_benchmarks_hardness_space( 217 experiment_folder: str, 218 text_f: Callable[[Tuple[str, str]], str], 219 color_f: Callable[[Tuple[str, str]], Union[str, None]] = lambda x: None, 220 label_f: Callable[[Tuple[str, str]], Union[str, None]] = lambda x: None, 221 ax: plt.Axes = None, 222 multiplicative_factor_xlim=1.0, 223 multiplicative_factor_ylim=1.0, 224 legend_ncol=1, 225 underneath_x_label: str = None, 226 set_ylabel=True, 227 set_legend=True, 228 xaxis_measure: Union[str, Tuple[str, Callable[["BaseMDP"], float]]] = "diameter", 229 yaxis_measure: Union[str, Tuple[str, Callable[["BaseMDP"], float]]] = "value_norm", 230 fontsize: int = 22, 231 fontsize_xlabel_underneath: int = 32, 232 text_label_fontsize=16, 233): 234 """ 235 for each agent configuration in the experiment folder, it produces a plot such that it is possible to place a text 236 label in the position corresponding to the value of the x-axis measure and indicator-axis measure. In addition to the text, 237 it is also possible choose the color assigned to the point in such position. 238 239 Parameters 240 ---------- 241 experiment_folder : str 242 The folder that contains the experiment logs, MDP configurations and agent configurations. 243 text_f : Callable[[Tuple[str, str]], str] 244 The function that returns a text label for a given MDP class name and gin config index. For example, 245 ('DeepSeaEpisodic', 'prms_0') -> "DeepSeaEpisodic (0)". 246 color_f : Callable[[Tuple[str, str]], str] 247 The function that returns the color for the point in the position corresponding to a given MDP class name and 248 gin config index. For example, ('DeepSeaEpisodic', 'prms_0') -> "DeepSeaEpisodic (0)". By default, no particular 249 color is specified. 250 label_f : Callable[[Tuple[str, str]], str] 251 The function that returns the label to be put in the legend for the point in the position corresponding to a 252 given MDP class name and gin config index. For example, ('DeepSeaEpisodic', 'prms_0') -> "DeepSea family". 253 By default, the legend is not included in the plot. 254 ax : plt.Axes 255 The ax object where the plot will be put. By default, a new axis is created. 256 multiplicative_factor_xlim : float 257 The additional space to add on the right side of the figure. It can be useful to add space for the legend. By 258 default, it is set to one. 259 multiplicative_factor_ylim : float 260 The additional space to add on the top side of the figure. It can be useful to add space for the legend. By 261 default, it is set to one. 262 legend_ncol : int 263 The number of columns in the legend. By default, it is set to one. 264 underneath_x_label : str 265 Text to be added underneath the x_label. By default, no text is added. 266 set_ylabel : bool 267 If True, the indicator-label is set to the name of the indicator-axis measure. By default, the indicator-label is set. 268 set_legend : bool 269 If True, the legend is set. By default, the legend is set. 270 xaxis_measure : str 271 The code name of the hardness measures available in the package. Check `BaseMDP.get_available_hardness_measures()` 272 to get to know the available ones. By default, it is set to the diameter. 273 yaxis_measure : str 274 The code name of the hardness measures available in the package. Check `BaseMDP.get_available_hardness_measures()`. 275 to get to know the available ones. By default, it is set to the value norm. 276 fontsize : int 277 The font size for x and indicator labels. By default, it is set to :math:`22`. 278 fontsize_xlabel_underneath : 279 The font size for the text below the x label. By default, it is set to :math:`32`. 280 text_label_fontsize : int 281 The font size for the text labels of the points. By default, it is set to :math:`16`. 282 """ 283 284 show = ax is None 285 if ax is None: 286 fig, ax = plt.subplots(1, 1, figsize=(8, 8)) 287 set_ylabel = True 288 289 hardness_measures = get_hardness_measures_from_experiment_folder( 290 experiment_folder, (xaxis_measure, yaxis_measure) 291 ) 292 texts = [] 293 for k, r in hardness_measures.items(): 294 texts.append( 295 ax.text( 296 r[xaxis_measure], 297 r[yaxis_measure], 298 text_f(k), 299 fontdict=dict(fontsize=text_label_fontsize), 300 ) 301 ) 302 ax.scatter( 303 r[xaxis_measure], 304 r[yaxis_measure], 305 500, 306 color=color_f(k), 307 label=label_f(k), 308 edgecolor="black", 309 linewidths=0.5, 310 ) 311 312 ax.tick_params(labelsize=22) 313 if set_ylabel: 314 ax.set_ylabel( 315 yaxis_measure.capitalize().replace("_", " "), 316 fontdict=dict(fontsize=fontsize), 317 labelpad=10, 318 ) 319 ax.set_xlabel( 320 xaxis_measure.capitalize().replace("_", " "), 321 fontdict=dict(fontsize=fontsize), 322 labelpad=15, 323 ha="center", 324 ) 325 326 xlim = ax.get_xlim() 327 ax.set_xlim(xlim[0], xlim[1] * multiplicative_factor_xlim) 328 ylim = ax.get_ylim() 329 ax.set_ylim(ylim[0], ylim[1] * multiplicative_factor_ylim) 330 331 if type(underneath_x_label) == str: 332 ax.text( 333 np.mean(ax.get_xlim()), 334 ylim[0] - 0.28 * (ylim[1] - ylim[0]), 335 underneath_x_label, 336 fontdict=dict(fontsize=fontsize_xlabel_underneath), 337 ha="center", 338 ) 339 340 if set_legend: 341 h, l = ax.get_legend_handles_labels() 342 if h: 343 ax.legend(ncol=legend_ncol) 344 345 plt.tight_layout() 346 adjust_text( 347 texts, 348 ax=ax, 349 expand_text=(1.05, 1.8), 350 expand_points=(1.05, 1.5), 351 only_move={"points": "indicator", "text": "xy"}, 352 precision=0.0001, 353 lim=1000, 354 ) 355 356 if show: 357 plt.tight_layout() 358 plt.show()
for each agent configuration in the experiment folder, it produces a plot such that it is possible to place a text label in the position corresponding to the value of the x-axis measure and indicator-axis measure. In addition to the text, it is also possible choose the color assigned to the point in such position.
Parameters
- experiment_folder (str): The folder that contains the experiment logs, MDP configurations and agent configurations.
- text_f (Callable[[Tuple[str, str]], str]): The function that returns a text label for a given MDP class name and gin config index. For example, ('DeepSeaEpisodic', 'prms_0') -> "DeepSeaEpisodic (0)".
- color_f (Callable[[Tuple[str, str]], str]): The function that returns the color for the point in the position corresponding to a given MDP class name and gin config index. For example, ('DeepSeaEpisodic', 'prms_0') -> "DeepSeaEpisodic (0)". By default, no particular color is specified.
- label_f (Callable[[Tuple[str, str]], str]): The function that returns the label to be put in the legend for the point in the position corresponding to a given MDP class name and gin config index. For example, ('DeepSeaEpisodic', 'prms_0') -> "DeepSea family". By default, the legend is not included in the plot.
- ax (plt.Axes): The ax object where the plot will be put. By default, a new axis is created.
- multiplicative_factor_xlim (float): The additional space to add on the right side of the figure. It can be useful to add space for the legend. By default, it is set to one.
- multiplicative_factor_ylim (float): The additional space to add on the top side of the figure. It can be useful to add space for the legend. By default, it is set to one.
- legend_ncol (int): The number of columns in the legend. By default, it is set to one.
- underneath_x_label (str): Text to be added underneath the x_label. By default, no text is added.
- set_ylabel (bool): If True, the indicator-label is set to the name of the indicator-axis measure. By default, the indicator-label is set.
- set_legend (bool): If True, the legend is set. By default, the legend is set.
- xaxis_measure (str):
The code name of the hardness measures available in the package. Check
BaseMDP.get_available_hardness_measures()
to get to know the available ones. By default, it is set to the diameter. - yaxis_measure (str):
The code name of the hardness measures available in the package. Check
BaseMDP.get_available_hardness_measures()
. to get to know the available ones. By default, it is set to the value norm. - fontsize (int): The font size for x and indicator labels. By default, it is set to \( 22 \).
- fontsize_xlabel_underneath :: The font size for the text below the x label. By default, it is set to \( 32 \).
- text_label_fontsize (int): The font size for the text labels of the points. By default, it is set to \( 16 \).
361def plot_indicator_in_hardness_space( 362 experiment_folder: str, 363 indicator: str = "normalized_cumulative_regret", 364 fontsize: int = 22, 365 cmap: str = "Reds", 366 fig_size=8, 367 text_label_fontsize=14, 368 savefig_folder: Optional[str] = "tmp", 369) -> "Figure": 370 """ 371 for each agent config, it produces a plot that places the given indicator obtained by the agent config for each MDP 372 config in the position corresponding to the diameter and value norm of the MDP. 373 374 Parameters 375 ---------- 376 experiment_folder : str 377 The path of the directory containing the experiment results. 378 indicator : str 379 is a string representing the performance indicator that is shown in the plot. Check `MDPLoop.get_indicators()` 380 to get a list of the available indicators. By default, the 'normalized_cumulative_regret' is used. 381 fontsize : int 382 The font size for x and indicator labels. By default, it is set to :math:`22`. 383 cmap : str 384 The code name for the color map to be used when plotting the indicator values. By default, 385 the 'Reds' color map is used. 386 fig_size : int 387 The size of the figures in the grid of plots. By default, it is set to :math:`8`. 388 text_label_fontsize : int 389 The font size for the text labels of the points. By default, it is set to :math:`14`. 390 savefig_folder : str 391 The folder where the figure will be saved. By default, the figure it is saved in a local folder with name 'tmp'. 392 If the directory does not exist, it is created. 393 394 Returns 395 ------- 396 Figure 397 The matplotlib figure. 398 """ 399 400 color_map = matplotlib.cm.get_cmap(cmap) 401 _, df = get_latex_table_of_average_indicator( 402 experiment_folder, 403 indicator, 404 show_prm=True, 405 return_table=True, 406 mdps_on_row=False, 407 ) 408 df_numerical = df.applymap(lambda s: float(re.findall("\d+\.\d+", s)[0])) 409 fig, axes = plt.subplots( 410 1, len(df.index), figsize=(len(df.index) * fig_size + 1, fig_size), sharey=True 411 ) 412 if len(df.index) == 1: 413 axes = np.array([axes]) 414 for i, (a, ax) in enumerate(zip(df.index, axes.tolist())): 415 plot_labels_on_benchmarks_hardness_space( 416 experiment_folder, 417 label_f=lambda x: None, 418 color_f=lambda x: color_map( 419 df_numerical.loc[a, _get_index(x)] / df_numerical.loc[a].max() 420 ), 421 text_f=lambda x: f"{_get_index(x)[0].replace('MiniGrid', 'MG-')} " 422 f"({(_get_index(x)[1].replace('prms_', ''))})", 423 # text_f=lambda x: "", 424 ax=ax, 425 fontsize=fontsize, 426 text_label_fontsize=text_label_fontsize, 427 underneath_x_label=f"({ascii_lowercase[i]}) {a[0]}", 428 ) 429 # ax.set_title( 430 # f"({ascii_lowercase[i]}) {a[0]}", 431 # fontdict=dict(legend_fontsize=legend_fontsize + 4), 432 # indicator=-0.28, 433 # ) 434 435 plt.tight_layout() 436 437 if savefig_folder is not None: 438 os.makedirs(savefig_folder, exist_ok=True) 439 exp_name = os.path.basename(os.path.dirname(ensure_folder(experiment_folder))) 440 plt.savefig( 441 f"{ensure_folder(savefig_folder)}{indicator}_in_hard_space_{exp_name}.pdf", 442 bbox_inches="tight", 443 ) 444 plt.show() 445 446 return fig
for each agent config, it produces a plot that places the given indicator obtained by the agent config for each MDP config in the position corresponding to the diameter and value norm of the MDP.
Parameters
- experiment_folder (str): The path of the directory containing the experiment results.
- 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. - fontsize (int): The font size for x and indicator labels. By default, it is set to \( 22 \).
- cmap (str): The code name for the color map to be used when plotting the indicator values. By default, the 'Reds' color map is used.
- fig_size (int): The size of the figures in the grid of plots. By default, it is set to \( 8 \).
- text_label_fontsize (int): The font size for the text labels of the points. By default, it is set to \( 14 \).
- savefig_folder (str): The folder where the figure will be saved. By default, the figure it is saved in a local folder with name 'tmp'. If the directory does not exist, it is created.
Returns
- Figure: The matplotlib figure.
449def group_by_mdp_individual_plot( 450 experiment_folder: str, 451 ax, 452 measure: str, 453 mdp_class_name: str, 454 mdp_prms: str, 455 available_agents: List[Tuple[str, str]], 456 colors_dict_agents: Dict[Tuple[str, str], str], 457 standard_error: bool = False, 458 baselines=MDPLoop.get_baselines(), 459): 460 """ 461 plots the measure for the given agents and experiment fold in the given axes. 462 463 Parameters 464 ---------- 465 experiment_folder : str 466 is the folder that contains the experiment logs, MDP configurations and agent configurations. 467 ax : plt.Axes 468 is where the plot will be shown. 469 measure : str 470 is a string representing the performance measure that is shown in the plot. Check 471 MDPLoop.get_indicators() to get a list of the available indicators. 472 mdp_prms : str 473 is a string that contains the mdp parameter gin config parameter, i.e. 'prms_0'. 474 mdp_class_name : str 475 is a string that contains the mdp class name. 476 available_agents : List[Tuple[str, str]] 477 is a list containing the agent gin config parameters and the agent class names. 478 colors_dict_agents : Dict[Tuple[str, str], str] 479 is a dict that assign to each agent gin config parameter and agent class name a different color. 480 """ 481 mdp_code = mdp_prms + config.EXPERIMENT_SEPARATOR_PRMS + mdp_class_name 482 483 for available_agent in available_agents: 484 agent_code = ( 485 available_agent[1] + config.EXPERIMENT_SEPARATOR_PRMS + available_agent[0] 486 ) 487 agent_formatted_name = get_formatted_name(*available_agent) 488 df, n_seeds = get_logs_data( 489 experiment_folder, mdp_class_name, mdp_prms, *available_agent 490 ) 491 492 for b in baselines: 493 y = measure.replace("cumulative_reward", "cumulative_expected_reward") 494 if b + "_" + y in MDPLoop.get_baseline_indicators(): 495 sns.lineplot( 496 x="steps", 497 y=b + "_" + y, 498 label=b.capitalize() + " agent", 499 data=df, 500 ax=ax, 501 errorbar=None, 502 color=MDPLoop.get_baselines_color_dict()[b], 503 linestyle=MDPLoop.get_baselines_style_dict()[b], 504 linewidth=2, 505 ) 506 507 # We plot the baselines only once 508 baselines = [] 509 510 add_time_exceed_sign_to_plot( 511 ax, 512 df, 513 colors_dict_agents[available_agent], 514 measure, 515 n_seeds, 516 experiment_folder, 517 mdp_code, 518 agent_code, 519 ) 520 sns_ax = sns.lineplot( 521 x="steps", 522 y=measure, 523 label=agent_formatted_name, 524 data=df, 525 ax=ax, 526 errorbar="se" if standard_error else ("ci", 95), 527 color=colors_dict_agents[available_agent], 528 ) 529 sns_ax.set_ylabel(" ".join(map(lambda x: x.capitalize(), measure.split("_"))))
plots the measure for the given agents and experiment fold in the given axes.
Parameters
- experiment_folder (str): is the folder that contains the experiment logs, MDP configurations and agent configurations.
- ax (plt.Axes): is where the plot will be shown.
- measure (str): is a string representing the performance measure that is shown in the plot. Check MDPLoop.get_indicators() to get a list of the available indicators.
- mdp_prms (str): is a string that contains the mdp parameter gin config parameter, i.e. 'prms_0'.
- mdp_class_name (str): is a string that contains the mdp class name.
- available_agents (List[Tuple[str, str]]): is a list containing the agent gin config parameters and the agent class names.
- colors_dict_agents (Dict[Tuple[str, str], str]): is a dict that assign to each agent gin config parameter and agent class name a different color.