import csv import numpy as np import matplotlib.pyplot as plt import matplotlib from math import ceil from constants import ENV_NAMES import seaborn # sets some style parameters automatically np.random.seed(1024) COLORS = [(np.random.randint(0, 255), np.random.randint(0, 255), np.random.randint(0, 255)) for x in range(20)] def switch_to_outer_plot(fig): ax0 = fig.add_subplot(111, frame_on=False) ax0.set_xticks([]) ax0.set_yticks([]) return ax0 def ema(data_in, smoothing=0): data_out = np.zeros_like(data_in) curr = np.nan for i in range(len(data_in)): x = data_in[i] if np.isnan(curr): curr = x else: curr = (1 - smoothing) * x + smoothing * curr data_out[i] = curr return data_out def plot_data_mean_std(ax, data_y, color_idx=0, data_x=None, x_scale=1, smoothing=0, first_valid=0, label=None): color = COLORS[color_idx] hexcolor = '#%02x%02x%02x' % color data_y = data_y[:, first_valid:] nx, num_datapoint = np.shape(data_y) if smoothing > 0: for i in range(nx): data_y[i, ...] = ema(data_y[i, ...], smoothing) if data_x is None: data_x = (np.array(range(num_datapoint)) + first_valid) * x_scale data_mean = np.mean(data_y, axis=0) data_std = np.std(data_y, axis=0, ddof=1) ax.plot(data_x, data_mean, color=hexcolor, label=label, linestyle='solid', alpha=1, rasterized=True) ax.fill_between(data_x, data_mean - data_std, data_mean + data_std, color=hexcolor, alpha=.25, linewidth=0.0, rasterized=True) def read_csv(filename, key_name): with open(filename) as csv_file: csv_reader = csv.reader(csv_file, delimiter=',') key_index = -1 values = [] for line_num, row in enumerate(csv_reader): row = [x.lower() for x in row] if line_num == 0: idxs = [i for i, val in enumerate(row) if val == key_name] key_index = idxs[0] else: values.append(row[key_index]) return np.array(values, dtype=np.float32) def plot_values(ax, all_values, title=None, max_x=0, label=None, **kwargs): if max_x > 0: all_values = all_values[..., :max_x] if ax is not None: plot_data_mean_std(ax, all_values, label=label, **kwargs) ax.set_title(title, fontsize=20) return all_values def plot_experiment(env_name, run_directory_prefix, titles=None, suffixes=[''], normalization_ranges=None, key_name='eprewmean', **kwargs): run_folders = [f'{run_directory_prefix}_{0}_{2020 + x}' for x in range(3)] sppo_run_folders = ['sppo-' + rf for rf in run_folders] ppo_run_folders = ['ppo-' + rf for rf in run_folders] run_folders = [sppo_run_folders, ppo_run_folders] run_names = ['SPPO', 'PPO'] num_envs = 1 will_normalize_and_reduce = normalization_ranges is not None if will_normalize_and_reduce: num_visible_plots = 1 f, axarr = plt.subplots() else: num_visible_plots = num_envs dimx = dimy = ceil(np.sqrt(num_visible_plots)) f, axarr = plt.subplots(dimx, dimy, sharex=True) color_idx = 0 for rf in range(len(run_folders)): for suffix in suffixes: all_values = [] game_weights = [1] * num_envs if len(suffixes) == 1: label = run_names[rf] else: if suffix == '': label = run_names[rf] + ' train' else: label = run_names[rf] + ' test' print(f'loading results from {env_name}...') if num_visible_plots == 1: ax = axarr else: dimy = len(axarr[0]) ax = axarr[0 // dimy][0 % dimy] csv_files = [f"checkpoints/{resid}/progress{'-' if len(suffix) > 0 else ''}{suffix}.csv" for resid in run_folders[rf]] curr_ax = None if will_normalize_and_reduce else ax raw_data = np.array([read_csv(file, key_name) for file in csv_files]) values = plot_values(curr_ax, raw_data, title=env_name, color_idx=color_idx, label=label, **kwargs) if will_normalize_and_reduce: game_range = normalization_ranges[env_name] game_min = game_range[0] game_max = game_range[1] game_delta = game_max - game_min sub_values = game_weights[0] * (np.array(values) - game_min) / (game_delta) all_values.append(sub_values) if will_normalize_and_reduce: normalized_data = np.sum(all_values, axis=0) normalized_data = normalized_data / np.sum(game_weights) title = 'Mean Normalized Score' plot_values(ax, normalized_data, title=None, color_idx=color_idx, label=suffix, **kwargs) color_idx += 1 if num_visible_plots == 1: ax.legend(loc='lower right') else: f.legend(loc='lower right', bbox_to_anchor=(.5, 0, .5, 1)) return f, axarr