Skip to content

Commit 1663b8f

Browse files
committed
created main function
1 parent b9ad471 commit 1663b8f

File tree

1 file changed

+191
-185
lines changed

1 file changed

+191
-185
lines changed

run_experiments.py

+191-185
Original file line numberDiff line numberDiff line change
@@ -20,195 +20,201 @@
2020
import pprint
2121
pp = pprint.PrettyPrinter(indent=4)
2222

23-
#TODO Different seeds for Ray Trainer (TF, numpy, Python; Torch, Env), Environment (it has multiple sources of randomness too), Ray Evaluator
24-
# docstring at beginning of the file is stored in __doc__
25-
parser = argparse.ArgumentParser(description=__doc__)
26-
parser.add_argument('-c', '--config-file', dest='config_file', action='store',
27-
default='default_config',
28-
help='Configuration file containing configuration to run '
29-
'experiments. It must be a Python file so config can be '
30-
'given programmatically. There are 2 types of configs - '
31-
'VARIABLE CONFIG across the experiments and STATIC CONFIG '
32-
'across the experiments. \nVARIABLE CONFIGS: The '
33-
'OrderedDicts var_env_configs, var_agent_configs and '
34-
'var_model_configs hold configuration options that are '
35-
'variable for the environment, agent and model across the '
36-
'current experiment. For each configuration option, the '
37-
'option is the key in the dict and its value is a list of '
38-
'values it can take for the current experiment. A '
39-
'Cartesian product of these lists is taken to generate '
40-
'various possible configurations to be run. For example, '
41-
'you might want to vary "delay" for the current '
42-
'experiment. Then "delay" would be a key in '
43-
'var_env_configs dict and its value would be a list of '
44-
'values it can take. Because Ray does not have a common '
45-
'way to address this specification of configurations for '
46-
'its agents, there are a few hacky ways to set '
47-
'var_agent_configs and var_model_configs currently. '
48-
'Please see sample experiment config files in the '
49-
'experiments directory to see how to set the values for a '
50-
'given algorithm. \n STATIC CONFIGS: env_config, '
51-
'agent_config and model_config are dicts which hold the '
52-
'static configuration for the current experiment as a '
53-
'normal Python dict.')
54-
# ####TODO Update docs regarding how to get configs to run: i.e., Cartesian
55-
# product, or random, etc.
56-
parser.add_argument('-e', '--exp-name', dest='exp_name', action='store',
57-
default='mdpp_default_experiment',
58-
help='The user-chosen name of the experiment. This is used'
59-
' as the prefix of the output files (the prefix also '
60-
'contains config_num if that is provided). It will save '
61-
'stats to 2 CSV files, with the filenames as the one given'
62-
' as argument'
63-
' and another file with an extra "_eval" in the filename '
64-
'that contains evaluation stats during the training. '
65-
'Appends to existing files or creates new ones if they '
66-
'don\'t exist.')
67-
parser.add_argument('-n', '--config-num', dest='config_num', action='store',
68-
default=None, type=int,
69-
help='Used for running the configurations of experiments '
70-
'in parallel. This is appended to the prefix of the output'
71-
' files (after exp_name).'
72-
' A Cartesian product of different configuration values '
73-
'for the experiment will be taken and ordered as a list '
74-
'and this number corresponds to the configuration number '
75-
'in this list. Please look in to the code for details.')
76-
# ###TODO Remove? #hack to run 1000 x 1000 env configs x agent configs.
77-
# Storing all million of them in memory may be too inefficient?
78-
parser.add_argument('-a', '--agent-config-num', dest='agent_config_num',
79-
action='store', default=None, type=int,
80-
help='Used for running the configurations of experiments '
81-
'in parallel. This is appended to the prefix of the output'
82-
' files (after exp_name).')
83-
parser.add_argument('-f', '--framework', dest='framework', action='store',
84-
default='ray', type=str, help='Specify framework to run '
85-
'experiments (Current options: Ray Rllib, Stable Baselines'
86-
').')
87-
parser.add_argument('-m', '--save-model', dest='save_model', action='store',
88-
default=False, type=bool,
89-
help='Option to save trained NN model and framework \
90-
generated files at the end of '
91-
'training.')
92-
parser.add_argument('-t', '--framework-dir', dest='framework_dir',
93-
action='store', default='/tmp/', type=str,
94-
help='Prefix of directory to be used by underlying '
95-
'framework (e.g. Ray Rllib, Stable Baselines 3). This '
96-
'name will be passed to the framework.')
97-
# parser.add_argument('-t', '--tune-hps', dest='tune_hps', action='store',
98-
# default=False, type=bool,
99-
# help='Used for tuning the hyperparameters that can be '
100-
# 'used for experiments later.'
101-
# ' A Cartesian product of different configuration values '
102-
# 'for the experiment will be taken and ordered as a list '
103-
# 'and this number corresponds to the configuration number'
104-
# ' in this list.'
105-
# ' Please look in to the code for details.')
106-
parser.add_argument('-l', '--log-level', default='WARNING',
107-
help='Set log level.')
108-
109-
110-
args = parser.parse_args()
111-
print("Parsed arguments:", args)
112-
113-
log_levels = {
114-
'CRITICIAL': logging.CRITICAL,
115-
'ERROR': logging.ERROR,
116-
'WARNING': logging.WARNING,
117-
'INFO': logging.INFO,
118-
'DEBUG': logging.DEBUG,
119-
'NOTSET': logging.NOTSET
120-
}
121-
122-
try:
123-
log_level_ = log_levels[args.log_level]
124-
except ValueError:
125-
logging.error("Log level {} not in {}.".format(args.log_level,
126-
log_levels.keys()))
127-
128-
config_file = args.config_file
129-
130-
if args.config_file[-3:] == '.py':
131-
config_file = args.config_file[:-3]
132-
133-
# print("config_file_path:", config_file_path)
134-
135-
stats_file_name = os.path.abspath(args.exp_name)
136-
137-
if args.config_num is not None:
138-
stats_file_name += '_' + str(args.config_num)
139-
# elif args.agent_config_num is not None: ###IMP Commented out! If we append both these nums then, that can lead to 1M small files for 1000x1000 configs which doesn't play well with our Nemo cluster.
140-
# stats_file_name += '_' + str(args.agent_config_num)
141-
142-
print("Stats file being written to:", stats_file_name)
143-
144-
config, final_configs = config_processor.process_configs(config_file, stats_file_prefix=stats_file_name, framework=args.framework, config_num=args.config_num, log_level=log_level_, framework_dir=args.framework_dir)
145-
146-
print("Configuration number(s) that will be run:", "all" if args.config_num is None else args.config_num)
147-
148-
149-
# import default_config
150-
# print("default_config:", default_config)
151-
# print(os.path.abspath(args.config_file)) # 'experiments/dqn_seq_del.py'
152-
153-
154-
import time
155-
start = time.time()
156-
157-
158-
159-
if args.config_num is None:
160-
# final_configs = config.final_configs
161-
print("Total number of configs to run:", len(final_configs))
162-
pass
163-
else:
164-
final_configs = [final_configs[args.config_num]]
165-
166-
16723

24+
def main():
25+
#TODO Different seeds for Ray Trainer (TF, numpy, Python; Torch, Env), Environment (it has multiple sources of randomness too), Ray Evaluator
26+
# docstring at beginning of the file is stored in __doc__
27+
parser = argparse.ArgumentParser(description=__doc__)
28+
parser.add_argument('-c', '--config-file', dest='config_file',
29+
action='store', default='default_config',
30+
help='Configuration file containing configuration to run '
31+
'experiments. It must be a Python file so config can be '
32+
'given programmatically. There are 2 types of configs - '
33+
'VARIABLE CONFIG across the experiments and STATIC CONFIG '
34+
'across the experiments. \nVARIABLE CONFIGS: The '
35+
'OrderedDicts var_env_configs, var_agent_configs and '
36+
'var_model_configs hold configuration options that are '
37+
'variable for the environment, agent and model across the '
38+
'current experiment. For each configuration option, the '
39+
'option is the key in the dict and its value is a list of '
40+
'values it can take for the current experiment. A '
41+
'Cartesian product of these lists is taken to generate '
42+
'various possible configurations to be run. For example, '
43+
'you might want to vary "delay" for the current '
44+
'experiment. Then "delay" would be a key in '
45+
'var_env_configs dict and its value would be a list of '
46+
'values it can take. Because Ray does not have a common '
47+
'way to address this specification of configurations for '
48+
'its agents, there are a few hacky ways to set '
49+
'var_agent_configs and var_model_configs currently. '
50+
'Please see sample experiment config files in the '
51+
'experiments directory to see how to set the values for a '
52+
'given algorithm. \n STATIC CONFIGS: env_config, '
53+
'agent_config and model_config are dicts which hold the '
54+
'static configuration for the current experiment as a '
55+
'normal Python dict.')
56+
# ####TODO Update docs regarding how to get configs to run: i.e., Cartesian
57+
# product, or random, etc.
58+
parser.add_argument('-e', '--exp-name', dest='exp_name', action='store',
59+
default='mdpp_default_experiment',
60+
help='The user-chosen name of the experiment. This is used'
61+
' as the prefix of the output files (the prefix also '
62+
'contains config_num if that is provided). It will save '
63+
'stats to 2 CSV files, with the filenames as the one given'
64+
' as argument'
65+
' and another file with an extra "_eval" in the filename '
66+
'that contains evaluation stats during the training. '
67+
'Appends to existing files or creates new ones if they '
68+
'don\'t exist.')
69+
parser.add_argument('-n', '--config-num', dest='config_num', action='store',
70+
default=None, type=int,
71+
help='Used for running the configurations of experiments '
72+
'in parallel. This is appended to the prefix of the output'
73+
' files (after exp_name).'
74+
' A Cartesian product of different configuration values '
75+
'for the experiment will be taken and ordered as a list '
76+
'and this number corresponds to the configuration number '
77+
'in this list. Please look in to the code for details.')
78+
# ###TODO Remove? #hack to run 1000 x 1000 env configs x agent configs.
79+
# Storing all million of them in memory may be too inefficient?
80+
parser.add_argument('-a', '--agent-config-num', dest='agent_config_num',
81+
action='store', default=None, type=int,
82+
help='Used for running the configurations of experiments '
83+
'in parallel. This is appended to the prefix of the output'
84+
' files (after exp_name).')
85+
parser.add_argument('-f', '--framework', dest='framework', action='store',
86+
default='ray', type=str, help='Specify framework to run '
87+
'experiments (Current options: Ray Rllib, Stable Baselines'
88+
').')
89+
parser.add_argument('-m', '--save-model', dest='save_model', action='store',
90+
default=False, type=bool,
91+
help='Option to save trained NN model and framework \
92+
generated files at the end of '
93+
'training.')
94+
parser.add_argument('-t', '--framework-dir', dest='framework_dir',
95+
action='store', default='/tmp/', type=str,
96+
help='Prefix of directory to be used by underlying '
97+
'framework (e.g. Ray Rllib, Stable Baselines 3). This '
98+
'name will be passed to the framework.')
99+
# parser.add_argument('-t', '--tune-hps', dest='tune_hps', action='store',
100+
# default=False, type=bool,
101+
# help='Used for tuning the hyperparameters that can be '
102+
# 'used for experiments later.'
103+
# ' A Cartesian product of different configuration values '
104+
# 'for the experiment will be taken and ordered as a list '
105+
# 'and this number corresponds to the configuration number'
106+
# ' in this list.'
107+
# ' Please look in to the code for details.')
108+
parser.add_argument('-l', '--log-level', default='WARNING',
109+
help='Set log level.')
110+
111+
112+
args = parser.parse_args()
113+
print("Parsed arguments:", args)
114+
115+
log_levels = {
116+
'CRITICIAL': logging.CRITICAL,
117+
'ERROR': logging.ERROR,
118+
'WARNING': logging.WARNING,
119+
'INFO': logging.INFO,
120+
'DEBUG': logging.DEBUG,
121+
'NOTSET': logging.NOTSET
122+
}
123+
124+
try:
125+
log_level_ = log_levels[args.log_level]
126+
except ValueError:
127+
logging.error("Log level {} not in {}.".format(args.log_level,
128+
log_levels.keys()))
129+
130+
config_file = args.config_file
131+
132+
if args.config_file[-3:] == '.py':
133+
config_file = args.config_file[:-3]
134+
135+
# print("config_file_path:", config_file_path)
136+
137+
stats_file_name = os.path.abspath(args.exp_name)
138+
139+
if args.config_num is not None:
140+
stats_file_name += '_' + str(args.config_num)
141+
# elif args.agent_config_num is not None: ###IMP Commented out! If we append both these nums then, that can lead to 1M small files for 1000x1000 configs which doesn't play well with our Nemo cluster.
142+
# stats_file_name += '_' + str(args.agent_config_num)
143+
144+
print("Stats file being written to:", stats_file_name)
145+
146+
config, final_configs = config_processor.process_configs(config_file, stats_file_prefix=stats_file_name, framework=args.framework, config_num=args.config_num, log_level=log_level_, framework_dir=args.framework_dir)
147+
148+
print("Configuration number(s) that will be run:", "all" if args.config_num is None else args.config_num)
149+
150+
151+
# import default_config
152+
# print("default_config:", default_config)
153+
# print(os.path.abspath(args.config_file)) # 'experiments/dqn_seq_del.py'
154+
155+
156+
import time
157+
start = time.time()
158+
159+
160+
161+
if args.config_num is None:
162+
# final_configs = config.final_configs
163+
print("Total number of configs to run:", len(final_configs))
164+
pass
165+
else:
166+
final_configs = [final_configs[args.config_num]]
168167

169-
for enum_conf_1, current_config_ in enumerate(final_configs):
170-
print("current_config of agent to be run:", current_config_, enum_conf_1)
171168

172-
algorithm = config.algorithm
173169

174170

175-
tune_config = current_config_
176-
print("tune_config:",)
177-
pp.pprint(tune_config)
171+
for enum_conf_1, current_config_ in enumerate(final_configs):
172+
print("current_config of agent to be run:", current_config_, enum_conf_1)
178173

174+
algorithm = config.algorithm
179175

180-
if 'timesteps_total' in dir(config):
181-
timesteps_total = config.timesteps_total
182-
else:
183-
timesteps_total = tune_config["timesteps_total"]
184-
185-
del tune_config["timesteps_total"] #hack Ray doesn't allow unknown configs
186-
187-
188-
print("\n\033[1;32m======== Running on environment: " + tune_config["env"] \
189-
+ " =========\033[0;0m\n")
190-
print("\n\033[1;32m======== for " + str(timesteps_total) \
191-
+ " steps =========\033[0;0m\n")
192-
193-
analysis = tune.run(
194-
algorithm,
195-
name=algorithm + '_' + str(stats_file_name.split('/')[-1]) + '_' \
196-
, ####IMP "name" has to be specified, otherwise,
197-
# it may lead to clashing for temp file in ~/ray_results/... directory.
198-
stop={
199-
"timesteps_total": timesteps_total,
200-
},
201-
config=tune_config,
202-
checkpoint_at_end=args.save_model,
203-
local_dir=args.framework_dir + '/_ray_results_' + str(args.config_num),
204-
#return_trials=True # add trials = tune.run( above
205-
)
206-
207-
if args.save_model:
208-
pickle.dump(analysis, open("{}_analysis.pickle".format(args.exp_name),
209-
"wb"))
210-
211-
config_processor.post_processing(framework=args.framework)
212-
213-
end = time.time()
214-
print("No. of seconds to run:", end - start)
176+
177+
tune_config = current_config_
178+
print("tune_config:",)
179+
pp.pprint(tune_config)
180+
181+
182+
if 'timesteps_total' in dir(config):
183+
timesteps_total = config.timesteps_total
184+
else:
185+
timesteps_total = tune_config["timesteps_total"]
186+
187+
del tune_config["timesteps_total"] #hack Ray doesn't allow unknown configs
188+
189+
190+
print("\n\033[1;32m======== Running on environment: " + tune_config["env"] \
191+
+ " =========\033[0;0m\n")
192+
print("\n\033[1;32m======== for " + str(timesteps_total) \
193+
+ " steps =========\033[0;0m\n")
194+
195+
analysis = tune.run(
196+
algorithm,
197+
name=algorithm + '_' + str(stats_file_name.split('/')[-1]) + '_' \
198+
, ####IMP "name" has to be specified, otherwise,
199+
# it may lead to clashing for temp file in ~/ray_results/... directory.
200+
stop={
201+
"timesteps_total": timesteps_total,
202+
},
203+
config=tune_config,
204+
checkpoint_at_end=args.save_model,
205+
local_dir=args.framework_dir + '/_ray_results_' + str(args.config_num),
206+
#return_trials=True # add trials = tune.run( above
207+
)
208+
209+
if args.save_model:
210+
pickle.dump(analysis, open("{}_analysis.pickle".format(args.exp_name),
211+
"wb"))
212+
213+
config_processor.post_processing(framework=args.framework)
214+
215+
end = time.time()
216+
print("No. of seconds to run:", end - start)
217+
218+
219+
if __name__ == '__main__':
220+
main()

0 commit comments

Comments
 (0)