x_label = { 'steps': 'Timesteps', 'episodes': 'Episodes', 'time': 'Walltime (in hours)' }[args.x_axis] dirs = [ os.path.join(log_path, folder) for folder in os.listdir(log_path) if env in folder and os.path.isdir(os.path.join(log_path, folder)) ] plt.figure('Training Success Rate', figsize=args.figsize) plt.title('Training Success Rate', fontsize=args.fontsize) plt.xlabel(f'{x_label}', fontsize=args.fontsize) plt.ylabel('Success Rate', fontsize=args.fontsize) for folder in dirs: data_frame = load_results(folder) if args.max_timesteps is not None: data_frame = data_frame[data_frame.l.cumsum() <= args.max_timesteps] success = np.array(data_frame['is_success']) x, _ = ts2xy(data_frame, x_axis) # Do not plot the smoothed curve at all if the timeseries is shorter than window size. if x.shape[0] >= args.episode_window: # Compute and plot rolling mean with window of size args.episode_window x, y_mean = window_func(x, success, args.episode_window, np.mean) plt.plot(x, y_mean, linewidth=2) plt.tight_layout() plt.show()
def generate_plots(dirs, xaxis=X_TIMESTEPS, yaxis='r', title=None, labels=None, num_timesteps=None, subsample=None, individual=False): for i in range(len(dirs)): if not dirs[i].startswith('/'): dirs[i] = os.path.join(BASE, dirs[i]) # If pointing to a single folder and that folder has many results, use that as dir if len(dirs) == 1 and len(get_subdirs(dirs[0])) > 1: dirs = [ os.path.join(dirs[0], subdir) for subdir in get_subdirs(dirs[0]) ] dirs = sorted(dirs) # Make everything reproducible by sorting. Can comment out later for organization. if labels is None: labels = [os.path.basename(os.path.normpath(d)) for d in dirs] dirs, labels = zip(*sorted(zip(dirs, labels), key=lambda x: x[0])) plt.gcf().dpi = 100.0 print("Dirs", dirs) for i, folder in enumerate(dirs): if not 'params.yaml' in os.listdir(folder): # If directory contains 1 folder, and none of those folders have params.yaml, move down. while True: contents = get_subdirs(folder) if any([ 'params.yaml' in os.listdir(os.path.join(folder, c)) for c in contents ]): break folder = os.path.join(folder, contents[0]) if not 'params.yaml' in os.listdir(folder): runs = sorted( [os.path.join(folder, r) for r in get_subdirs(folder)]) else: runs = [folder] print("Different seeds for folder", folder, ":") print(runs) print("----") sns.set_context(context="paper", font_scale=1.5) sns.set_style("darkgrid", {'font.family': 'serif'}) xlist, ylist = [], [] for run in runs: timesteps = load_results(run) if num_timesteps is not None: timesteps = timesteps[timesteps.l.cumsum() <= num_timesteps] x, y = ts2xy(timesteps, xaxis, yaxis=yaxis) if x.shape[0] >= EPISODES_WINDOW: x, y = window_func(x, y, EPISODES_WINDOW, np.mean) xlist.append(x) ylist.append(y) if individual: for i, (xs, ys, run) in enumerate(zip(xlist, ylist, runs)): g = sns.lineplot(x=xs, y=ys, label=os.path.basename(run)) else: # Zero-order hold to align the data for plotting joint_x = sorted(list(set(np.concatenate(xlist)))) combined_x, combined_y = [], [] for xs, ys in zip(xlist, ylist): cur_ind = 0 zoh_y = [] for x in joint_x: # The next value matters if cur_ind < len(ys) - 1 and x >= xs[cur_ind + 1]: cur_ind += 1 zoh_y.append(ys[cur_ind]) if subsample: combined_x.extend(joint_x[::subsample]) combined_y.extend(zoh_y[::subsample]) else: combined_x.extend(joint_x) combined_y.extend(zoh_y) data = pd.DataFrame({xaxis: combined_x, yaxis: combined_y}) g = sns.lineplot(x=xaxis, y=yaxis, data=data, ci=None, sort=True, label=labels[i]) print("Completed folder", folder) if title: plt.title(title) plt.xlabel(xaxis) plt.ylabel(yaxis) plt.tight_layout(pad=0)
] ) plt.figure(y_label, figsize=args.figsize) plt.title(y_label, fontsize=args.fontsize) plt.xlabel(f"{x_label}", fontsize=args.fontsize) plt.ylabel(y_label, fontsize=args.fontsize) for folder in dirs: try: data_frame = load_results(folder) except LoadMonitorResultsError: continue if args.max_timesteps is not None: data_frame = data_frame[data_frame.l.cumsum() <= args.max_timesteps] try: y = np.array(data_frame[y_axis]) except KeyError: print(f"No data available for {folder}") continue x, _ = ts2xy(data_frame, x_axis) # Do not plot the smoothed curve at all if the timeseries is shorter than window size. if x.shape[0] >= args.episode_window: # Compute and plot rolling mean with window of size args.episode_window x, y_mean = window_func(x, y, args.episode_window, np.mean) plt.plot(x, y_mean, linewidth=2, label=folder.split("/")[-1]) plt.legend() plt.tight_layout() plt.show()
def percentile_plot(dirs, title=None, labels=None, curve=False): for i in range(len(dirs)): if not dirs[i].startswith('/'): dirs[i] = os.path.join(BASE, dirs[i]) if labels is None: labels = [os.path.basename(os.path.normpath(d)) for d in dirs] categorical_x = [] categorical_y = [] for i, directory in enumerate(dirs): all_runs = [] folders = [ os.path.join(directory, subdir) for subdir in get_subdirs(directory) ] rewards = [] for folder in folders: runs = [] for item in os.listdir(folder): item_path = os.path.join(folder, item) if os.path.isdir(item_path) and '0.monitor.csv' in os.listdir( item_path): runs.append(item_path) returns = [] print( "Different evals for folder", folder, "Please ensure this has ALL intended environments or results may skew:" ) print(runs) print("----") for run in runs: timesteps = load_results(run) x, y = ts2xy(timesteps, X_TIMESTEPS, yaxis='r') if x.shape[0] >= EPISODES_WINDOW: x, y = window_func(x, y, EPISODES_WINDOW, np.mean) if len(y) > 0: returns.append(max(y)) else: print("Was Error on run", run) avg_reward = np.mean(returns) print(folder, avg_reward) rewards.append(avg_reward) print("Seeds for", directory, ":", len(rewards), "of", len(folders)) print("Stats:") rounded_mean = round(np.mean(rewards), 1) rounded_confidence = round(np.std(rewards) / np.sqrt(len(rewards)), 1) print("$" + str(rounded_mean) + " \pm " + str(rounded_confidence) + "$") if curve: x = np.sort(rewards) y = 1 - (np.arange(0, len(x)) / len(x)) sns.set_context(context="paper", font_scale=1.5) sns.set_style("darkgrid", {'font.family': 'serif'}) sns.scatterplot(x=x, y=y, label=labels[i]) else: categorical_x.extend([labels[i]] * len(rewards)) categorical_y.extend(rewards) if curve: plt.xlabel('reward') plt.ylabel('% Above threshold') else: sns.set(rc={'figure.figsize': (6.4, 4.8)}) sns.set_context(context="paper", font_scale=1.4) sns.set_style("darkgrid", {'font.family': 'serif'}) sns.boxplot(x=categorical_x, y=categorical_y, whis=1.5, showcaps=False, showfliers=True, saturation=0.7, width=0.9) sns.swarmplot(x=categorical_x, y=categorical_y, color="0.25") plt.ylabel('Reward') if title: plt.title(title) plt.tight_layout(pad=0)
for folder in sorted(dirs): npz = np.load(os.path.join(folder, 'evaluations.npz')) timesteps = npz['timesteps'] results = npz['results'] if args.max_timesteps is not None: results = results[timesteps <= args.max_timesteps] timesteps = timesteps[timesteps <= args.max_timesteps] # Take mean for each of the evaluations results = np.mean(results, axis=1) # Do not plot the smoothed curve at all if the timeseries is shorter than window size. if timesteps.shape[0] >= args.episode_window: name = folder.split('/')[-1] # Compute and plot rolling mean with window of size args.episode_window x, y_mean = window_func(timesteps, results, args.episode_window, np.mean) almost_there = np.where(y_mean >= 0.95 * y_mean.max())[0][0] print(name, '– 5% Deviation of maximum is first reached at timestep', x[almost_there]) plt.figure(y_label, figsize=args.figsize) plt.title(y_label, fontsize=args.fontsize) plt.xlabel(f"{x_label}", fontsize=args.fontsize) plt.ylabel(y_label, fontsize=args.fontsize) plt.ylim(0, 60) plt.plot(x / 1e6, y_mean, linewidth=2) plt.tight_layout() #plt.show() plt.savefig(name + '_eval') plt.close() #plt.show()