def plot_trial(trial_spec, info_space): '''Plot the trial graph, 1 pane: mean and error envelope of reward graphs from all sessions. Each aeb_df gets its own color''' prepath = util.get_prepath(trial_spec, info_space) predir, _, _, _, _, _ = util.prepath_split(prepath) session_datas = session_datas_from_file(predir, trial_spec, info_space.get('trial')) rand_session_data = session_datas[list(session_datas.keys())[0]] max_tick_unit = ps.get(trial_spec, 'env.0.max_tick_unit') aeb_count = len(rand_session_data) palette = viz.get_palette(aeb_count) fig = None for idx, (a, e, b) in enumerate(rand_session_data): aeb = (a, e, b) aeb_str = f'{a}{e}{b}' color = palette[idx] aeb_rewards_df = gather_aeb_rewards_df(aeb, session_datas, max_tick_unit) aeb_fig = build_aeb_reward_fig(aeb_rewards_df, aeb_str, color, max_tick_unit) if fig is None: fig = aeb_fig else: fig.add_traces(aeb_fig.data) fig.layout.update( title= f'trial graph: {trial_spec["name"]} t{info_space.get("trial")}, {len(session_datas)} sessions', width=500, height=600) viz.plot(fig) return fig
def session_data_dict_for_dist(spec, info_space): '''Method to retrieve session_datas (fitness df, so the same as session_data_dict above) when a trial with distributed sessions is done, to avoid messy multiprocessing data communication''' prepath = util.get_prepath(spec, info_space) predir, _, _, _, _, _ = util.prepath_split(prepath) session_datas = session_data_dict_from_file(predir, info_space.get('trial')) session_datas = [session_datas[k] for k in sorted(session_datas.keys())] return session_datas
def session_retro_eval(session): '''retro_eval but for session at the end to rerun failed evals''' prepath = util.get_prepath(session.spec, session.info_space, unit='session') predir, _, _, _, _, _ = util.prepath_split(prepath) retro_eval(predir, session.index)
def get_spec(spec_file, spec_name, lab_mode, pre_): '''Get spec using args processed from inputs''' if lab_mode in TRAIN_MODES: if pre_ is None: # new train trial spec = spec_util.get(spec_file, spec_name) else: # for resuming with train@{predir} # e.g. train@latest (fill find the latest predir) # e.g. train@data/reinforce_cartpole_2020_04_13_232521 predir = pre_ if predir == 'latest': predir = sorted(glob(f'data/{spec_name}*/'))[ -1] # get the latest predir with spec_name _, _, _, _, experiment_ts = util.prepath_split( predir) # get experiment_ts to resume train spec logger.info(f'Resolved to train@{predir}') spec = spec_util.get(spec_file, spec_name, experiment_ts) elif lab_mode == 'enjoy' or lab_mode == 'record': # for enjoy@{session_spec_file} # e.g. enjoy@data/reinforce_cartpole_2020_04_13_232521/reinforce_cartpole_t0_s0_spec.json session_spec_file = pre_ assert session_spec_file is not None, 'enjoy/record mode must specify a `enjoy/record@{session_spec_file}`' spec = util.read(f'{session_spec_file}') else: raise ValueError( f'Unrecognizable lab_mode not of {TRAIN_MODES} or {EVAL_MODES}') return spec
def test_prepath_split(): prepath = 'data/dqn_pong_2018_12_02_082510/dqn_pong_t0_s0' predir, prefolder, prename, spec_name, experiment_ts = util.prepath_split(prepath) assert predir == 'data/dqn_pong_2018_12_02_082510' assert prefolder == 'dqn_pong_2018_12_02_082510' assert prename == 'dqn_pong_t0_s0' assert spec_name == 'dqn_pong' assert experiment_ts == '2018_12_02_082510'
def get_eval_spec(spec_file, prename): '''Get spec for eval mode''' predir, _, _, _, _, _ = util.prepath_split(spec_file) prepath = f'{predir}/{prename}' spec = util.prepath_to_spec(prepath) spec['meta']['ckpt'] = 'eval' spec['meta']['eval_model_prepath'] = util.insert_folder(prepath, 'model') return spec
def save_trial_data(spec, info_space, trial_fitness_df, trial_fig): '''Save the trial data: spec, trial_fitness_df.''' prepath = util.get_prepath(spec, info_space, unit='trial') logger.info(f'Saving trial data to {prepath}') util.write(trial_fitness_df, f'{prepath}_trial_fitness_df.csv') viz.save_image(trial_fig, f'{prepath}_trial_graph.png') if util.get_lab_mode() == ('train', 'eval'): predir, _, _, _, _, _ = util.prepath_split(prepath) shutil.make_archive(predir, 'zip', predir) logger.info(f'All trial data zipped to {predir}.zip')
def retro_analyze_experiment(predir): '''Retro-analyze all experiment level datas.''' logger.info('Retro-analyzing experiment from file') from slm_lab.experiment.control import Experiment _, _, _, spec_name, _, _ = util.prepath_split(predir) prepath = f'{predir}/{spec_name}' spec, info_space = util.prepath_to_spec_info_space(prepath) experiment = Experiment(spec, info_space) experiment.trial_data_dict = trial_data_dict_from_file(predir) return analyze_experiment(experiment)
def save_experiment_data(spec, info_space, experiment_df, experiment_fig): '''Save the experiment data: best_spec, experiment_df, experiment_graph.''' prepath = util.get_prepath(spec, info_space, unit='experiment') logger.info(f'Saving experiment data to {prepath}') util.write(experiment_df, f'{prepath}_experiment_df.csv') viz.save_image(experiment_fig, f'{prepath}_experiment_graph.png') # zip for ease of upload predir, _, _, _, _, _ = util.prepath_split(prepath) shutil.make_archive(predir, 'zip', predir) logger.info(f'All experiment data zipped to {predir}.zip')
def run_online_eval(spec, info_space, ckpt): ''' Calls a subprocess to run lab in eval mode with the constructed ckpt prepath, same as how one would manually run the bash cmd e.g. python run_lab.py data/dqn_cartpole_2018_12_19_224811/dqn_cartpole_t0_spec.json dqn_cartpole eval@dqn_cartpole_t0_s1_ckpt-epi10-totalt1000 ''' prepath_t = util.get_prepath(spec, info_space, unit='trial') prepath_s = util.get_prepath(spec, info_space, unit='session') predir, _, prename, spec_name, _, _ = util.prepath_split(prepath_s) cmd = f'python run_lab.py {prepath_t}_spec.json {spec_name} eval@{prename}_ckpt-{ckpt}' logger.info(f'Running online eval for ckpt-{ckpt}') return util.run_cmd(cmd)
def analyze_experiment(spec, trial_data_dict): '''Analyze experiment and save data''' info_prepath = spec['meta']['info_prepath'] util.write(trial_data_dict, f'{info_prepath}_trial_data_dict.json') # calculate experiment df experiment_df = calc_experiment_df(trial_data_dict, info_prepath) # plot graph viz.plot_experiment(spec, experiment_df, METRICS_COLS) # zip files predir, _, _, _, _, _ = util.prepath_split(info_prepath) shutil.make_archive(predir, 'zip', predir) logger.info(f'All experiment data zipped to {predir}.zip') return experiment_df
def analyze_trial(trial_spec, session_metrics_list): '''Analyze trial and save data, then return metrics''' info_prepath = trial_spec['meta']['info_prepath'] # calculate metrics trial_metrics = calc_trial_metrics(session_metrics_list, info_prepath) # plot graphs viz.plot_trial(trial_spec, trial_metrics) # zip files if util.get_lab_mode() == 'train': predir, _, _, _, _, _ = util.prepath_split(info_prepath) shutil.make_archive(predir, 'zip', predir) logger.info(f'All trial data zipped to {predir}.zip') return trial_metrics
def mock_spec_info_space(predir, trial_index=None, session_index=None): '''Helper for retro analysis to build mock info_space and spec''' from slm_lab.experiment.monitor import InfoSpace _, _, _, spec_name, experiment_ts, _ = util.prepath_split(predir) info_space = InfoSpace() info_space.experiment_ts = experiment_ts info_space.set('experiment', 0) if trial_index is None: filepath = f'{predir}/{spec_name}_spec.json' else: info_space.set('trial', trial_index) filepath = f'{predir}/{spec_name}_t{trial_index}_spec.json' if session_index is not None: info_space.set('session', session_index) spec = util.read(filepath) return spec, info_space
def analyze_experiment(spec, trial_data_dict): '''Analyze experiment and save data''' info_prepath = spec['meta']['info_prepath'] util.write(trial_data_dict, f'{info_prepath}_trial_data_dict.json') # calculate experiment df experiment_df = calc_experiment_df(trial_data_dict, info_prepath) # plot graph viz.plot_experiment(spec, experiment_df, METRICS_COLS) viz.plot_experiment_trials(spec, experiment_df, METRICS_COLS) # manually shut down orca server to avoid zombie processes viz.pio.orca.shutdown_server() # zip files predir, _, _, _, _, _ = util.prepath_split(info_prepath) zipdir = util.smart_path(predir) shutil.make_archive(zipdir, 'zip', zipdir) logger.info(f'All experiment data zipped to {predir}.zip') return experiment_df
def analyze_trial(trial_spec, session_metrics_list): '''Analyze trial and save data, then return metrics''' info_prepath = trial_spec['meta']['info_prepath'] # calculate metrics trial_metrics = calc_trial_metrics(session_metrics_list, info_prepath) # plot graphs viz.plot_trial(trial_spec, trial_metrics) viz.plot_trial(trial_spec, trial_metrics, ma=True) # manually shut down orca server to avoid zombie processes viz.pio.orca.shutdown_server() # zip files if util.get_lab_mode() == 'train': predir, _, _, _, _, _ = util.prepath_split(info_prepath) zipdir = util.smart_path(predir) shutil.make_archive(zipdir, 'zip', zipdir) logger.info(f'All trial data zipped to {predir}.zip') return trial_metrics
def calc_trial_df(trial_spec, info_space): '''Calculate trial_df as mean of all session_df''' from slm_lab.experiment import retro_analysis prepath = util.get_prepath(trial_spec, info_space) predir, _, _, _, _, _ = util.prepath_split(prepath) session_datas = retro_analysis.session_datas_from_file(predir, trial_spec, info_space.get('trial'), ps.get(info_space, 'ckpt')) aeb_transpose = {aeb: [] for aeb in session_datas[list(session_datas.keys())[0]]} max_tick_unit = ps.get(trial_spec, 'meta.max_tick_unit') for s, session_data in session_datas.items(): for aeb, aeb_df in session_data.items(): aeb_transpose[aeb].append(aeb_df.sort_values(by=[max_tick_unit]).set_index(max_tick_unit, drop=False)) trial_data = {} for aeb, df_list in aeb_transpose.items(): trial_data[aeb] = pd.concat(df_list).groupby(level=0).mean().reset_index(drop=True) trial_df = pd.concat(trial_data, axis=1) return trial_df
def analyze_session(session, eager_analyze_trial=False, tmp_space_session_sub=False): ''' Gather session data, plot, and return fitness df for high level agg. @returns {DataFrame} session_fitness_df Single-row df of session fitness vector (avg over aeb), indexed with session index. ''' logger.info('Analyzing session') session_data = get_session_data(session, body_df_kind='train') session_fitness_df = _analyze_session(session, session_data, body_df_kind='train') session_data = get_session_data(session, body_df_kind='eval', tmp_space_session_sub=tmp_space_session_sub) session_fitness_df = _analyze_session(session, session_data, body_df_kind='eval') if eager_analyze_trial: # for live trial graph, analyze trial after analyzing session, this only takes a second from slm_lab.experiment import retro_analysis prepath = util.get_prepath(session.spec, session.info_space, unit='session') # use new ones to prevent side effects spec, info_space = util.prepath_to_spec_info_space(prepath) predir, _, _, _, _, _ = util.prepath_split(prepath) retro_analysis.analyze_eval_trial(spec, info_space, predir) return session_fitness_df
def plot_session_from_file(session_df_filepath): ''' Method to plot session from its session_df file @example from slm_lab.experiment import analysis filepath = 'data/reinforce_cartpole_2018_01_22_211751/reinforce_cartpole_t0_s0_session_df.csv' analysis.plot_session_from_file(filepath) ''' from slm_lab.experiment.monitor import InfoSpace _, _, _, spec_name, _, _ = util.prepath_split(session_df_filepath) session_spec = {'name': spec_name} session_df = util.read(session_df_filepath, header=[0, 1, 2, 3], index_col=0, dtype=np.float32) session_data = util.session_df_to_data(session_df) tn, sn = session_df_filepath.replace('_session_df.csv', '').split('_')[-2:] info_space = InfoSpace() info_space.set('experiment', 0) info_space.set('trial', int(tn[1:])) info_space.set('session', int(sn[1:])) session_fig = plot_session(session_spec, info_space, session_data) viz.save_image(session_fig, session_df_filepath.replace('_session_df.csv', '_session_graph.png'))
def run_old_mode(spec_file, spec_name, lab_mode): '''Run using existing data with `enjoy, eval`. The eval mode is also what train mode's online eval runs in a subprocess via bash command''' # reconstruct spec and info_space from existing data lab_mode, prename = lab_mode.split('@') predir, _, _, _, _, _ = util.prepath_split(spec_file) prepath = f'{predir}/{prename}' spec, info_space = util.prepath_to_spec_info_space(prepath) # see InfoSpace def for more on these info_space.ckpt = 'eval' info_space.eval_model_prepath = prepath # no info_space.tick() as they are reconstructed if lab_mode == 'enjoy': spec = spec_util.override_enjoy_spec(spec) Session(spec, info_space).run() elif lab_mode == 'eval': spec = spec_util.override_eval_spec(spec) Session(spec, info_space).run() util.clear_periodic_ckpt(prepath) # cleanup after itself analysis.analyze_eval_trial(spec, info_space, predir) else: raise ValueError('Unrecognizable lab_mode not of `enjoy, eval`')
def run_old_mode(spec_file, spec_name, lab_mode): '''Run using existing data with `enjoy, eval`. The eval mode is also what train mode's online eval runs in a subprocess via bash command''' # reconstruct spec and info_space from existing data lab_mode, prename = lab_mode.split('@') predir, _, _, _, _, _ = util.prepath_split(spec_file) prepath = f'{predir}/{prename}' spec, info_space = util.prepath_to_spec_info_space(prepath) # see InfoSpace def for more on these info_space.ckpt = 'eval' info_space.eval_model_prepath = prepath # no info_space.tick() as they are reconstructed if lab_mode == 'enjoy': spec = spec_util.override_enjoy_spec(spec) Session(spec, info_space).run() elif lab_mode == 'eval': # example eval command: # python run_lab.py data/dqn_cartpole_2018_12_19_224811/dqn_cartpole_t0_spec.json dqn_cartpole eval@dqn_cartpole_t0_s1_ckpt-epi10-totalt1000 spec = spec_util.override_eval_spec(spec) Session(spec, info_space).run() util.clear_periodic_ckpt(prepath) # cleanup after itself retro_analysis.analyze_eval_trial(spec, info_space, predir) else: raise ValueError(f'Unrecognizable lab_mode not of {EVAL_MODES}')