101 Commits

Author SHA1 Message Date
Johannes Fischer
f5f1c24f45 Remove unused method 2022-03-01 10:00:40 +01:00
Johannes Fischer
f93e130498 Merge branch 'main' into idm_upgrade 2022-03-01 09:58:07 +01:00
Johannes Fischer
2965dc9982 Update scratch for plotting 2022-03-01 09:57:36 +01:00
Johannes Fischer
fa0e20998d Update IDM 2022-03-01 09:56:14 +01:00
Arec Jamgochian
57a42f70ec purging etienne experiment files, adding hail metric files 2022-02-28 19:03:57 -08:00
Arec Jamgochian
5f6ad37c37 updating bc experiment, adding automatic config copying, fixing idm/expert running from file issues in eval_experiments 2022-02-28 18:56:28 -08:00
Arec Jamgochian
e602aa0641 Merge branch 'main' of https://github.com/sisl/InteractionImitation into main 2022-02-28 03:35:03 -08:00
Arec Jamgochian
5ada1cc543 updating weight decay 2022-02-28 03:35:00 -08:00
ebuehrle
a9314c4657 Copy over config files 2022-02-28 12:23:28 +01:00
ebuehrle
a37995694d Load policy config in evaluation 2022-02-28 12:23:02 +01:00
Arec Jamgochian
62c28d0cfa adding big tune run options 2022-02-28 03:04:59 -08:00
Johannes Fischer
e28459a168 Merge branch 'main' into idm_upgrade 2022-02-28 11:47:11 +01:00
Arec Jamgochian
6f181a7351 Merge branch 'main' of https://github.com/sisl/InteractionImitation into main 2022-02-28 01:57:28 -08:00
Arec Jamgochian
81e38f55ab adding shail-etienne policies 2022-02-28 01:57:25 -08:00
ebuehrle
51eb810f5c COnfigure HAIL in eval_experiments 2022-02-28 10:52:26 +01:00
Johannes Fischer
b94344214b Merge branch 'main' into idm_upgrade 2022-02-28 10:50:43 +01:00
Johannes Fischer
6d867466c6 Change IDM default params 2022-02-28 10:49:58 +01:00
ebuehrle
8cc71f07de Configure HAIL in eval script 2022-02-28 10:45:19 +01:00
ebuehrle
57076793c1 Add configs for SHAIL 2022-02-28 10:43:12 +01:00
ebuehrle
da6d1d812c Add some configs 2022-02-28 10:33:10 +01:00
Arec Jamgochian
88cae70477 fixing big in loading precalculated metrics for averaging 2022-02-28 00:59:30 -08:00
Arec Jamgochian
7814c7c30d ignoring pngs 2022-02-28 00:37:30 -08:00
Arec Jamgochian
5533faab40 adding metric pkls 2022-02-28 00:36:52 -08:00
Arec Jamgochian
1ee3805aba adding trained test policies, as well as fixing evaluate script and commands 2022-02-27 23:51:12 -08:00
Arec Jamgochian
e37911eeff removing gail-trpo since performance is about the same as gail, adding experiment evaluation script, updating metric averaging to work 2022-02-27 23:03:28 -08:00
Arec Jamgochian
e110570092 adding final bc configs, updating experiment to validate in longer intervals 2022-02-27 20:40:24 -08:00
Arec Jamgochian
5f77398fd0 commiting json files and intermediate settings used to run baseline methods around 02-26, 16ocklock. Next will set off big tuning runs for gail, gailtrpo, and bc (with committed values) 2022-02-27 16:27:01 -08:00
Arec Jamgochian
2cacdf691f Merge branch 'main' of https://github.com/sisl/InteractionImitation into main 2022-02-27 14:30:32 -08:00
Arec Jamgochian
e52b658aff adding all bestconfigs from big tune run (not sure what happened in last commit) 2022-02-27 14:29:49 -08:00
Arec Jamgochian
578459e37b best_configs/hail_expA.json 2022-02-27 14:27:29 -08:00
ebuehrle
25e4d5679f Make envs independent in BC experiment 2022-02-27 22:53:12 +01:00
Arec Jamgochian
7f1557144c committing etiennes best configs, leading to 73% success rate in shail expB 2022-02-27 13:43:59 -08:00
ebuehrle
7039468e46 Add tuning script for BC. Todo: if enough GPUs, enable resources in run function 2022-02-27 17:30:33 +01:00
ebuehrle
cc3848e8e0 Remove unused parameters 2022-02-27 15:02:32 +01:00
ebuehrle
4443492d3e Add tuning script for GAIL (TRPO) 2022-02-27 14:38:40 +01:00
ebuehrle
4b4fa7e09a Add tuning script for GAIL (PPO) 2022-02-27 14:14:08 +01:00
Arec Jamgochian
569e0756ca getting loading of configs, overwriting with seeds, running with tune, and moving back to directory working. adding check for either training or testing, and allowing specification of number of test cpus to split seeds over 2022-02-27 02:25:16 -08:00
Arec Jamgochian
21cbd1c956 getting best shail/hail configs outsave up and running, adding shell for test runs 2022-02-27 01:22:39 -08:00
Arec Jamgochian
acb4fdc518 renaming shail policy file, removing ogail file since its unnecessary 2022-02-27 00:00:42 -08:00
Arec Jamgochian
3280041efa committing what is hopefully final run of sgail for both experiments, A and B 2022-02-26 23:48:58 -08:00
Arec Jamgochian
3b9051505e naming convention doesnt like env key, leakyrelu is no bueno, running quick experiment to see which option sets can work with our time left. the options that look 4s ahead are definitely out of the questions, possibly the 2s ones aswell 2022-02-26 16:02:29 -08:00
ebuehrle
71e3c5f816 Parametrize discriminator architecture 2022-02-26 14:53:29 +01:00
ebuehrle
35e6fb299c Use collision rate as main metric 2022-02-26 14:28:58 +01:00
ebuehrle
1e24612347 Merge branch 'main' of https://github.com/sisl/InteractionImitation 2022-02-26 14:06:22 +01:00
ebuehrle
6876cf9625 Track collision rate 2022-02-26 13:50:53 +01:00
ebuehrle
dc9cbf329b Enable safe options on evaluation env 2022-02-26 12:24:25 +01:00
ebuehrle
f9d3cceed5 Save checkpoints and config to folder, move params to config 2022-02-26 12:23:42 +01:00
Arec Jamgochian
c28c6c05b7 added ogail script and splitting up feasability on next line to avoid calculating it unnecessarily (though it might be fine as is) 2022-02-25 18:39:33 -08:00
Arec Jamgochian
fa98601fa6 fixing issues with lazylinear sequential, setting off a big run 2022-02-25 17:48:56 -08:00
Arec Jamgochian
2dfd7e3c2b add policy saving 2022-02-25 17:00:46 -08:00
Arec Jamgochian
59083ebce3 making option list indexable to visualize in tensorboard. noticing run from last night had much better performance under more long options, unclear if due to choice or environment factors, like episodes lasting longer. making stoponcollision and seed parameters. fixing ability to see reward metrics under ray/tune/, problem was they were being returned as tensors, not floats 2022-02-25 16:36:14 -08:00
Arec Jamgochian
d1f23e6d25 readding expertdata to gitignore, just manually adding expert joint state and action files 2022-02-25 01:27:02 -08:00
Arec Jamgochian
46564231ef changing gitignore to upload expert data for evaluation, adding multiple roundabout trackfile environments in vecenv 2022-02-25 01:21:16 -08:00
Arec Jamgochian
bf9ce84fe4 changing when directory name gets saved 2022-02-25 00:42:44 -08:00
Arec Jamgochian
99aa50a08b added support for different activations, number of hidden layers, options, running a big run over this 2022-02-25 00:00:04 -08:00
Arec Jamgochian
7feea74eb8 adding stablebaselines, adding safe loading for nonCuda cluster 2022-02-24 23:18:02 -08:00
ebuehrle
5a5d8a7aff WIP: Support different plan lengths 2022-02-25 01:32:54 +01:00
ebuehrle
02c1813b00 Incrementing agent expert data, smaller policy network 2022-02-25 01:23:15 +01:00
Johannes Fischer
0d193d4af3 Scratch for horner scheme 2022-02-24 15:12:29 +01:00
Johannes Fischer
8e12996dfe fix typo 2022-02-24 14:18:26 +01:00
ebuehrle
febceed651 Add expert data 2022-02-23 18:17:30 +01:00
Johannes Fischer
a3280893af Update IDM script 2022-02-23 18:16:01 +01:00
ebuehrle
336cf02278 Parameterize hidden layer size of policy, add some candidates to grid search 2022-02-23 18:14:23 +01:00
ebuehrle
7f64ec7bb0 Move hyperparameters to config object
ToDo: parameterize network architectures
2022-02-23 18:00:19 +01:00
ebuehrle
406c4ad9ee Fix tune by moving file 2022-02-23 17:41:41 +01:00
Johannes Fischer
9c3cb4fb55 Add IDM script 2022-02-23 17:21:02 +01:00
ebuehrle
f037c119cc Set up for ray tune 2022-02-23 16:55:13 +01:00
ebuehrle
91f88983b0 Add learning rate schedule to SHAIL-PPO 2022-02-23 14:22:02 +01:00
Johannes Fischer
a1db6aa553 Make IDM use vehicle on ego path a reference 2022-02-22 22:00:46 +01:00
Arec
68b066ec53 adding success rate, total distance, and survive time 2022-02-22 00:48:35 -08:00
Arec
e7f4f6a871 wrapping all environments in timelimit to stop runs longer than 100s, since some others were erroring 2022-02-21 17:54:29 -08:00
Arec
e7f8385628 updating rwse to work at different times, updating correct testing environment from roundabout, removing the assertion that a collision implies done in the evaluator, using nanmean and nanstd in averaging 2022-02-21 15:55:16 -08:00
ebuehrle
daa4825f17 Add GAIL-PPO 2022-02-21 22:21:13 +01:00
ebuehrle
a89317e1d5 Correct checkpoint file path 2022-02-21 22:11:34 +01:00
ebuehrle
b89f5db9d8 Add SHAIL policy with more options 2022-02-21 22:07:44 +01:00
ebuehrle
953a93a541 Add two checkpoints for SHAIL-PPO 2022-02-21 17:33:08 +01:00
ebuehrle
a242edc5d3 Fix predict for reparameterized modules
Better way would probably be to rewrite flat_grad and reparam
2022-02-21 13:29:53 +01:00
ebuehrle
2da0e05782 Implement rwse 2022-02-21 11:05:19 +01:00
Arec
8c4ff03208 adding average absolute delta v, and tracking positions and setting up architecture to implement rwse 2022-02-21 00:06:39 -08:00
Arec
d2932951f6 adding metric saving and averaging over seeds 2022-02-20 23:22:46 -08:00
Arec Jamgochian
a7102a29df Merge pull request #4 from sisl/options
Integrate options env and policy
2022-02-20 20:20:28 -08:00
ebuehrle
ce22516893 Fix imports 2022-02-18 10:18:10 +01:00
ebuehrle
84351e77f2 Add SHAIL-PPO 2022-02-18 06:54:52 +01:00
ebuehrle
1624e1a349 Add SHAIL 2022-02-17 23:51:40 +01:00
ebuehrle
9de6bfe9a3 Add GAIL 2022-02-17 22:58:00 +01:00
ebuehrle
cd58ce2898 Remove old code 2022-02-17 22:43:41 +01:00
ebuehrle
5bd8b42d9f Merge updated files 2022-02-17 22:41:55 +01:00
ebuehrle
b78f95bab5 More checkpoints, adjustments for collision check 2022-02-16 10:19:50 +01:00
ebuehrle
c5e68ca33a Add model checkpoint 2022-02-15 22:01:28 +01:00
ebuehrle
c6a4c10605 Integrate options env and policy 2022-02-15 18:36:53 +01:00
ebuehrle
072c0ff417 Copy files 2022-02-15 14:03:22 +01:00
ebuehrle
a3b9b3e250 Port TRPO, PPO, GAIL 2022-02-15 11:07:08 +01:00
Arec
530ac95d61 Merge branch 'test' into main 2022-02-05 21:50:16 -08:00
Arec
3e6fce42ee BUG FIXES: moving around when policy is loaded, adding BaseAlgorithm abstract classes, correcting metrics, normalizng actions if idm environment is a normalized action one, manually updating environment graph when using idm, implementing idm forward class 2022-02-05 21:48:56 -08:00
Arec
795e1c08b6 adding metric comparisons and updating (note: pre-debug) init 2022-02-04 15:51:17 -08:00
Arec
d1f9e3d7c4 adding main test sequence. must debug and add summary and comparison metric generators tomorrow 2022-02-02 22:29:05 -08:00
Arec
31912416f1 adding pbar to evaluator and making metric save optional, adding typing to baselines 2022-02-02 22:19:40 -08:00
Arec
3ce86b31f7 adding Prop controller and IDMRulePolicy 2022-02-02 15:43:23 -08:00
Arec
3991306da0 updating evaluation wrapper to only store relevant variables during execution 2022-01-31 16:28:13 -08:00
ebuehrle
a60cc18874 PPO lidar + random agent 2022-01-22 08:05:16 +01:00
ebuehrle
18af0de2a4 Add experiment for PPO on lidar observations 2022-01-22 07:49:48 +01:00
278 changed files with 9365 additions and 275 deletions

2
.gitignore vendored
View File

@@ -1,7 +1,9 @@
*.png
*.pkl *.pkl
*.pt *.pt
*.zip *.zip
**/ray/* **/ray/*
**/runs/*
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/

214
bc-experiment.py Normal file
View File

@@ -0,0 +1,214 @@
# %%
import os
from tqdm import tqdm
from src.core.sampling import rollout
from src.core.gail import gail_ppo, Buffer
from src.core.value import SetValue
from src.core.policy import SetPolicy
from src.core.discriminator import DeepsetDiscriminator
import torch
from intersim.envs import IntersimpleLidarFlatRandom
from intersim.envs.intersimple import speed_reward
import functools
from src.util.wrappers import CollisionPenaltyWrapper, TransformObservation, Setobs
import numpy as np
from torch.utils.tensorboard import SummaryWriter
from ray import tune
from datetime import datetime
import json
DIR = os.path.dirname(os.path.abspath(__file__))
activations = [torch.nn.Tanh, torch.nn.LeakyReLU]
obs_min = np.array([
[-1000, -1000, 0, -np.pi, -1e-1, 0.],
[0, -np.pi, -20, -20, -np.pi, -1e-1],
[0, -np.pi, -20, -20, -np.pi, -1e-1],
[0, -np.pi, -20, -20, -np.pi, -1e-1],
[0, -np.pi, -20, -20, -np.pi, -1e-1],
[0, -np.pi, -20, -20, -np.pi, -1e-1],
]).reshape(-1)
obs_max = np.array([
[1000, 1000, 20, np.pi, 1e-1, 0.],
[50, np.pi, 20, 20, np.pi, 1e-1],
[50, np.pi, 20, 20, np.pi, 1e-1],
[50, np.pi, 20, 20, np.pi, 1e-1],
[50, np.pi, 20, 20, np.pi, 1e-1],
[50, np.pi, 20, 20, np.pi, 1e-1],
]).reshape(-1)
def training_function(config):
np.random.seed(config['seed'])
torch.manual_seed(config['seed'])
# choose validation environment
if config['experiment'] == 'A':
envs = [Setobs(TransformObservation(CollisionPenaltyWrapper(
IntersimpleLidarFlatRandom(
n_rays=5,
reward=functools.partial(
speed_reward,
collision_penalty=0
),
check_collisions=True,
stop_on_collision=config['trainenv']['stop_on_collision'],
), collision_distance=6, collision_penalty=100),
lambda obs: (obs - obs_min) / (obs_max - obs_min + 1e-10)
)) for _ in range(60)]
elif config['experiment'] == 'B':
envs = sum([[Setobs(TransformObservation(CollisionPenaltyWrapper(
IntersimpleLidarFlatRandom(
n_rays=5,
reward=functools.partial(
speed_reward,
collision_penalty=0
),
check_collisions=True,
stop_on_collision=config['trainenv']['stop_on_collision'],
), collision_distance=6, collision_penalty=100),
lambda obs: (obs - obs_min) / (obs_max - obs_min + 1e-10)
)) for _ in range(15)] for track in range(4)],[])
else:
raise NotImplementedError
env_fn = lambda i: envs[i]
# load expert data
if config['experiment'] == 'A':
expert_data = torch.load(os.path.join(DIR, 'intersimple-expert-data-setobs2-loc0-track0.pt'))
elif config['experiment'] == 'B':
expert_data = [
torch.load(os.path.join(DIR, 'intersimple-expert-data-setobs2-loc0-track0.pt')),
torch.load(os.path.join(DIR, 'intersimple-expert-data-setobs2-loc0-track1.pt')),
torch.load(os.path.join(DIR, 'intersimple-expert-data-setobs2-loc0-track2.pt')),
torch.load(os.path.join(DIR, 'intersimple-expert-data-setobs2-loc0-track3.pt')),
]
d0 = [d[0] for d in expert_data]
d1 = [d[1] for d in expert_data]
d2 = [d[2] for d in expert_data]
d3 = [d[3] for d in expert_data]
expert_data = (torch.cat(d0), torch.cat(d1), torch.cat(d2), torch.cat(d3))
expert_data = Buffer(*expert_data)
# configure and train policy
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
policy = SetPolicy(expert_data.actions.shape[-1],
n_hidden_layers=config['policy']['n_hidden_layers'],
hidden_layer_size=config['policy']['hidden_layer_size'],
activation=activations[config['policy']['activation']] ) # config net architecture
policy = policy.to(device)
pi_opt = torch.optim.Adam(policy.parameters(), lr=config['policy']['learning_rate'])
pi_lr_scheduler = torch.optim.lr_scheduler.ExponentialLR(pi_opt, gamma=config['policy']['learning_rate_decay'])
expert_states = expert_data.states[~expert_data.dones].to(device)
expert_actions = expert_data.actions[~expert_data.dones].to(device)
for epoch in range(config['train_epochs']):
pi_opt.zero_grad()
loss = -policy.log_prob(policy(expert_states), expert_actions).mean()
loss.backward()
pi_opt.step()
pi_lr_scheduler.step()
if epoch % 25 == 0:
gen_states, gen_actions, gen_rewards, gen_dones, gen_collisions = rollout(env_fn, policy.cpu(), n_episodes=60, max_steps_per_episode=200)
gen_mean_episode_length = (~gen_dones).sum() / gen_states.shape[0]
gen_mean_reward_per_episode = gen_rewards[~gen_dones].sum() / gen_states.shape[0]
gen_collision_rate = (1. * gen_collisions.any(-1)).mean()
tune.report(
gen_mean_reward_per_episode=gen_mean_reward_per_episode.item(),
mean_episode_length=gen_mean_episode_length.item(),
gen_collision_rate=gen_collision_rate.item(),
loss=loss.item(),
)
# save model checkpoints
ep = epoch + 1
if (ep % 50 == 0):
torch.save(policy.state_dict(), f'policy_epoch{ep}.pt')
# save model
torch.save(policy.state_dict(), 'policy_final.pt')
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--train', choices=['A', 'B'])
parser.add_argument('--epochs', type=int, default=500)
parser.add_argument('--test', type=str, help='path to config file to run final training on')
parser.add_argument('--test_seeds', type=int, default=5)
parser.add_argument('--test_cpus', type=int, help='number of cpus available to split test seed training over')
args = parser.parse_args()
assert (args.train is None) ^ (args.test is None), 'Must either train on an experiment or test with a config file'
# if no test config specified, train
if args.test is None:
print('Running Tuning for Experiment %s'%(args.train))
analysis = tune.run(
training_function,
config={
'experiment': args.train,
'trainenv': {
'stop_on_collision': False,
},
'policy': {
'learning_rate': 3e-4,
'learning_rate_decay': tune.grid_search([0.999, 1.0]),
'hidden_layer_size': tune.grid_search([10, 20, 40]),
'n_hidden_layers': tune.grid_search([2, 3]),
'activation':tune.grid_search([0, 1]),
},
'train_epochs': args.epochs,
'seed': 0,
}
# TODO resources_per_trial={'gpu': 1}
)
best_config = analysis.get_best_config(metric='gen_collision_rate', mode='min')
print('Best config: ', best_config)
# safe best_config
if not os.path.isdir(os.path.join(DIR, 'best_configs')):
os.mkdir(os.path.join(DIR, 'best_configs'))
# save gail
with open(os.path.join(DIR, 'best_configs',f'bc_exp{args.train}.json'), 'w', encoding='utf-8') as f:
json.dump(best_config, f, ensure_ascii=False, indent=4)
# if config file specified, rerun it with appropriate number of seeds
else:
with open(args.test, 'rb') as f:
config = json.load(f)
print(f'Retraining {args.test} with {args.test_seeds} seeds on experiment {config["experiment"]}')
# rerun with appropriate number of seeds
rpt = {'cpu': int(args.test_cpus/args.test_seeds)} if (args.test_cpus is not None) else None
config['seed'] = tune.grid_search(list(range(1,args.test_seeds+1)))
analysis = tune.run(training_function, config=config, resources_per_trial=rpt)
# move final policies to appropriate directory
split_ = os.path.basename(args.test).split('_')
model = split_[0]
exper = split_[-1].split('.')[0]
savepath = os.path.join('test_policies',model,exper)
if not os.path.isdir(savepath):
os.makedirs(savepath)
import shutil
for i in range(args.test_seeds):
s = analysis._checkpoints[i]['config']['seed']
check_dir = analysis._checkpoints[i]['logdir']
shutil.copyfile(os.path.join(check_dir,'policy_final.pt'),
os.path.join(savepath, f'policy_seed{s}.pt'))
shutil.copyfile(os.path.join(check_dir,'params.json'),
os.path.join(savepath, 'config.json')) # copy config automatically

15
best_configs/bc_expA.json Normal file
View File

@@ -0,0 +1,15 @@
{
"experiment": "A",
"trainenv": {
"stop_on_collision": false
},
"policy": {
"learning_rate": 0.0003,
"learning_rate_decay": 1.0,
"hidden_layer_size": 40,
"n_hidden_layers": 2,
"activation": 0
},
"train_epochs": 300,
"seed": 0
}

15
best_configs/bc_expB.json Normal file
View File

@@ -0,0 +1,15 @@
{
"experiment": "B",
"trainenv": {
"stop_on_collision": false
},
"policy": {
"learning_rate": 0.0003,
"learning_rate_decay": 1.0,
"hidden_layer_size": 40,
"n_hidden_layers": 2,
"activation": 0
},
"train_epochs": 300,
"seed": 0
}

View File

@@ -0,0 +1,31 @@
{
"experiment": "A",
"trainenv": {
"stop_on_collision": false
},
"policy": {
"learning_rate": 0.0003,
"learning_rate_decay": 1.0,
"clip_ratio": 0.2,
"iterations_per_epoch": 100,
"hidden_layer_size": 40,
"n_hidden_layers": 2,
"activation": 0
},
"value": {
"learning_rate": 0.0001,
"weight_decay": 0.001,
"iterations_per_epoch": 1000
},
"discriminator": {
"learning_rate": 0.001,
"weight_decay": 0.0001,
"iterations_per_epoch": 100,
"n_hidden_layers_element": 4,
"n_hidden_layers_global": 1,
"hidden_layer_size": 10,
"activation": 0
},
"train_epochs": 100,
"seed": 0
}

View File

@@ -0,0 +1,31 @@
{
"experiment": "B",
"trainenv": {
"stop_on_collision": false
},
"policy": {
"learning_rate": 0.0003,
"learning_rate_decay": 1.0,
"clip_ratio": 0.2,
"iterations_per_epoch": 100,
"hidden_layer_size": 40,
"n_hidden_layers": 2,
"activation": 0
},
"value": {
"learning_rate": 0.0001,
"weight_decay": 0.001,
"iterations_per_epoch": 1000
},
"discriminator": {
"learning_rate": 0.001,
"weight_decay": 0.0001,
"iterations_per_epoch": 100,
"n_hidden_layers_element": 4,
"n_hidden_layers_global": 1,
"hidden_layer_size": 10,
"activation": 0
},
"train_epochs": 100,
"seed": 0
}

View File

@@ -0,0 +1,33 @@
{
"experiment": "A",
"trainenv": {
"stop_on_collision": false,
"safe_actions_collision_method": null,
"abort_unsafe_collision_method": null
},
"policy": {
"learning_rate": 0.0003,
"learning_rate_decay": 1.0,
"clip_ratio": 0.2,
"iterations_per_epoch": 100,
"hidden_layer_size": 40,
"n_hidden_layers": 2,
"activation": 0,
"option": 0
},
"value": {
"learning_rate": 0.001,
"iterations_per_epoch": 1000
},
"discriminator": {
"learning_rate": 0.001,
"weight_decay": 0.0001,
"iterations_per_epoch": 100,
"n_hidden_layers_element": 4,
"n_hidden_layers_global": 1,
"hidden_layer_size": 10,
"activation": 0
},
"train_epochs": 90,
"seed": 0
}

View File

@@ -0,0 +1,33 @@
{
"experiment": "B",
"trainenv": {
"stop_on_collision": false,
"safe_actions_collision_method": null,
"abort_unsafe_collision_method": null
},
"policy": {
"learning_rate": 0.0003,
"learning_rate_decay": 1.0,
"clip_ratio": 0.2,
"iterations_per_epoch": 100,
"hidden_layer_size": 20,
"n_hidden_layers": 2,
"activation": 0,
"option": 0
},
"value": {
"learning_rate": 0.001,
"iterations_per_epoch": 1000
},
"discriminator": {
"learning_rate": 0.001,
"weight_decay": 0.0001,
"iterations_per_epoch": 100,
"n_hidden_layers_element": 4,
"n_hidden_layers_global": 2,
"hidden_layer_size": 10,
"activation": 0
},
"train_epochs": 85,
"seed": 0
}

View File

@@ -0,0 +1,33 @@
{
"experiment": "A",
"trainenv": {
"stop_on_collision": false,
"safe_actions_collision_method": "circle",
"abort_unsafe_collision_method": "circle"
},
"policy": {
"learning_rate": 0.0003,
"learning_rate_decay": 1.0,
"clip_ratio": 0.2,
"iterations_per_epoch": 100,
"hidden_layer_size": 40,
"n_hidden_layers": 2,
"activation": 0,
"option": 0
},
"value": {
"learning_rate": 0.001,
"iterations_per_epoch": 1000
},
"discriminator": {
"learning_rate": 0.001,
"weight_decay": 0.0001,
"iterations_per_epoch": 100,
"n_hidden_layers_element": 4,
"n_hidden_layers_global": 1,
"hidden_layer_size": 10,
"activation": 0
},
"train_epochs": 90,
"seed": 0
}

View File

@@ -0,0 +1,33 @@
{
"experiment": "B",
"trainenv": {
"stop_on_collision": false,
"safe_actions_collision_method": "circle",
"abort_unsafe_collision_method": "circle"
},
"policy": {
"learning_rate": 0.0003,
"learning_rate_decay": 1.0,
"clip_ratio": 0.2,
"iterations_per_epoch": 100,
"hidden_layer_size": 20,
"n_hidden_layers": 2,
"activation": 0,
"option": 0
},
"value": {
"learning_rate": 0.001,
"iterations_per_epoch": 1000
},
"discriminator": {
"learning_rate": 0.001,
"weight_decay": 0.0001,
"iterations_per_epoch": 100,
"n_hidden_layers_element": 4,
"n_hidden_layers_global": 2,
"hidden_layer_size": 10,
"activation": 0
},
"train_epochs": 85,
"seed": 0
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

100
eval_experiments.py Normal file
View File

@@ -0,0 +1,100 @@
import os
from src.eval_main import eval_main
from src.evaluation.utils import load_and_average
import torch
import json
activations = [torch.nn.Tanh, torch.nn.LeakyReLU]
def main(method:str='expert', folder:str=None, locations=[(0,0)], skip_running=False):
exclude_keys_from_policy_kwargs = {'learning_rate', 'learning_rate_decay', 'clip_ratio', 'iterations_per_epoch', 'option'}
policy_kwargs = {}
if method in ['expert', 'idm']:
env, env_kwargs ='NRasterizedRouteIncrementingAgent', {}
elif method in ['bc','gail']:
env='NormalizedContinuousEvalEnv'
env_kwargs={'stop_on_collision':True, 'max_episode_steps':1000}
elif method in ['hail']:
env = 'NormalizedSafeOptionsEvalEnv'
env_kwargs={'stop_on_collision':True, 'max_episode_steps':1000, 'safe_actions_collision_method': None, 'abort_unsafe_collision_method': None}
elif method in ['shail']:
env = 'NormalizedSafeOptionsEvalEnv'
env_kwargs={'stop_on_collision':True, 'max_episode_steps':1000}
else:
raise NotImplementedError
files = ['']
if folder is not None:
files = [os.path.join(folder, f) for f in os.listdir(folder) if os.path.isfile(os.path.join(folder, f))]
files = [f for f in files if f.endswith('.pt')]
with open(os.path.join(folder, 'config.json'), 'rb') as f:
config = json.load(f)
print('%i policy files found in %s folder' %(len(files), folder))
print('found policy config', config['policy'])
policy_config = {k: v for k, v in config['policy'].items() if k not in exclude_keys_from_policy_kwargs}
policy_config['activation'] = activations[policy_config['activation']]
print('final policy config', policy_config)
policy_kwargs.update(policy_config)
print('final policy kwargs', policy_kwargs)
if not skip_running:
for policy_file in files:
# run metrics on that file
outbase = eval_main(locations=locations,
method=method,
policy_file=policy_file,
policy_kwargs=policy_kwargs,
env=env,
env_kwargs=env_kwargs)
outfolder = os.path.dirname(outbase)
else:
locstr = 'loc_'+'_'.join([f'r{ro}t{tr}' for (ro,tr) in locations])
if folder is None:
outfolder = os.path.join('out',method,locstr)
else:
path_items = folder.split('/')
outfolder = os.path.join('out', '/'.join(path_items[1:]), locstr)
# load metrics from save_path
average_metrics = load_and_average(outfolder)
if method in ['expert', 'idm']:
latex_print(average_metrics, light=True)
else:
latex_print(average_metrics)
def latex_print(am, light=False):
"""
print latex line
am (Dict[str,tuple]): dict mapping metric_name to (mean, std)
"""
print('success rate, distance travelled, RWSE_10, |DeltaV|, AccelJSD')
if light:
if 'rwse_10s' in am.keys():
print("%2.1f& %2.1f & %2.1f & %1.2f& "
"%0.3f \\\\" %( 100*am['success rate'][0], am['mean travel distance'][0], am['rwse_10s'][0],
am['average absolute average velocity'][0],am['acceleration distribution divergence'][0] ))
return
print("%2.1f& %2.1f & $---$ & $---$ & "
"$---$ \\\\" %( 100*am['success rate'][0], am['mean travel distance'][0]))
return
print("%2.1f \\scriptstyle\\pm %2.1f & %2.1f \\scriptstyle\\pm %2.1f & "
"%2.1f \\scriptstyle\\pm %1.1f & %1.2f \\scriptstyle\\pm %1.2f & "
"%0.3f \\scriptstyle\\pm %0.3f \\\\" %( 100*am['success rate'][0], 100*am['success rate'][1],
am['mean travel distance'][0] , am['mean travel distance'][1] ,
am['rwse_10s'][0] , am['rwse_10s'][1] ,
am['average absolute average velocity'][0] , am['average absolute average velocity'][1] ,
am['acceleration distribution divergence'][0] , am['acceleration distribution divergence'][1] ))
if __name__=='__main__':
import fire
fire.Fire(main)

19
evaluate_models.sh Executable file
View File

@@ -0,0 +1,19 @@
# can add --skip_running if you've run the runs before on the saved policies
python -m eval_experiments
python -m eval_experiments --locations='[(0,4)]'
python -m eval_experiments --method idm
python -m eval_experiments --method idm --locations='[(0,4)]'
python -m eval_experiments --method bc --folder='test_policies/bc/expA'
python -m eval_experiments --method bc --folder='test_policies/bc/expB' --locations='[(0,4)]'
python -m eval_experiments --method gail --folder='test_policies/gail/expA'
python -m eval_experiments --method gail --folder='test_policies/gail/expB' --locations='[(0,4)]'
python -m eval_experiments --method hail --folder='test_policies/hail/expA'
python -m eval_experiments --method hail --folder='test_policies/hail/expB' --locations='[(0,4)]'
python -m eval_experiments --method shail --folder='test_policies/shail/expA'
python -m eval_experiments --method shail --folder='test_policies/shail/expB' --locations='[(0,4)]'
python -m eval_experiments --method hail --folder='test_policies/hail-etienne/expA'
python -m eval_experiments --method hail --folder='test_policies/hail-etienne/expB' --locations='[(0,4)]'
python -m eval_experiments --method shail --folder='test_policies/shail-etienne/expA'
python -m eval_experiments --method shail --folder='test_policies/shail-etienne/expB' --locations='[(0,4)]'

240
gail-experiment.py Normal file
View File

@@ -0,0 +1,240 @@
# %%
import os
import gym
from src.core.gail import gail_ppo, Buffer
from src.core.value import SetValue
from src.core.policy import SetPolicy
from src.core.discriminator import DeepsetDiscriminator
import torch
from intersim.envs import IntersimpleLidarFlatRandom
from intersim.envs.intersimple import speed_reward
import functools
from src.util.wrappers import CollisionPenaltyWrapper, TransformObservation, Setobs
import numpy as np
from torch.utils.tensorboard import SummaryWriter
from ray import tune
from datetime import datetime
import json
DIR = os.path.dirname(os.path.abspath(__file__))
activations = [torch.nn.Tanh, torch.nn.LeakyReLU]
obs_min = np.array([
[-1000, -1000, 0, -np.pi, -1e-1, 0.],
[0, -np.pi, -20, -20, -np.pi, -1e-1],
[0, -np.pi, -20, -20, -np.pi, -1e-1],
[0, -np.pi, -20, -20, -np.pi, -1e-1],
[0, -np.pi, -20, -20, -np.pi, -1e-1],
[0, -np.pi, -20, -20, -np.pi, -1e-1],
]).reshape(-1)
obs_max = np.array([
[1000, 1000, 20, np.pi, 1e-1, 0.],
[50, np.pi, 20, 20, np.pi, 1e-1],
[50, np.pi, 20, 20, np.pi, 1e-1],
[50, np.pi, 20, 20, np.pi, 1e-1],
[50, np.pi, 20, 20, np.pi, 1e-1],
[50, np.pi, 20, 20, np.pi, 1e-1],
]).reshape(-1)
def training_function(config):
np.random.seed(config['seed'])
torch.manual_seed(config['seed'])
if config['experiment'] == 'A':
envs = [Setobs(TransformObservation(CollisionPenaltyWrapper(
IntersimpleLidarFlatRandom(
n_rays=5,
reward=functools.partial(
speed_reward,
collision_penalty=0
),
check_collisions=True,
stop_on_collision=config['trainenv']['stop_on_collision'],
), collision_distance=6, collision_penalty=100),
lambda obs: (obs - obs_min) / (obs_max - obs_min + 1e-10)
)) for _ in range(60)]
elif config['experiment'] == 'B':
envs = sum([[Setobs(TransformObservation(CollisionPenaltyWrapper(
IntersimpleLidarFlatRandom(
n_rays=5,
reward=functools.partial(
speed_reward,
collision_penalty=0
),
check_collisions=True,
stop_on_collision=config['trainenv']['stop_on_collision'],
track=track,
), collision_distance=6, collision_penalty=100),
lambda obs: (obs - obs_min) / (obs_max - obs_min + 1e-10)
)) for _ in range(15)] for track in range(4)],[])
else:
raise NotImplementedError
env_fn = lambda i: envs[i]
policy = SetPolicy(env_fn(0).action_space.shape[0],
n_hidden_layers=config['policy']['n_hidden_layers'],
hidden_layer_size=config['policy']['hidden_layer_size'],
activation=activations[config['policy']['activation']] ) # config net architecture
pi_opt = torch.optim.Adam(policy.parameters(), lr=config['policy']['learning_rate'])
pi_lr_scheduler = torch.optim.lr_scheduler.ExponentialLR(pi_opt, gamma=config['policy']['learning_rate_decay'])
value = SetValue() # config net architecture
v_opt = torch.optim.Adam(value.parameters(), lr=config['value']['learning_rate'], weight_decay=config['value']['weight_decay'])
discriminator = DeepsetDiscriminator(
n_hidden_layers_element=config['discriminator']['n_hidden_layers_element'],
n_hidden_layers_global=config['discriminator']['n_hidden_layers_global'],
hidden_layer_size=config['discriminator']['hidden_layer_size'],
activation=activations[config['discriminator']['activation']],
)
disc_opt = torch.optim.Adam(discriminator.parameters(), lr=config['discriminator']['learning_rate'], weight_decay=config['discriminator']['weight_decay'])
if config['experiment'] == 'A':
expert_data = torch.load(os.path.join(DIR, 'intersimple-expert-data-setobs2-loc0-track0.pt'))
elif config['experiment'] == 'B':
expert_data = [
torch.load(os.path.join(DIR, 'intersimple-expert-data-setobs2-loc0-track0.pt')),
torch.load(os.path.join(DIR, 'intersimple-expert-data-setobs2-loc0-track1.pt')),
torch.load(os.path.join(DIR, 'intersimple-expert-data-setobs2-loc0-track2.pt')),
torch.load(os.path.join(DIR, 'intersimple-expert-data-setobs2-loc0-track3.pt')),
]
d0 = [d[0] for d in expert_data]
d1 = [d[1] for d in expert_data]
d2 = [d[2] for d in expert_data]
d3 = [d[3] for d in expert_data]
expert_data = (torch.cat(d0), torch.cat(d1), torch.cat(d2), torch.cat(d3))
expert_data = Buffer(*expert_data)
def callback(info):
tune.report(gen_mean_reward_per_episode=info['gen/mean_reward_per_episode'],
disc_mean_reward_per_episode=info['disc/mean_reward_per_episode'],
mean_episode_length=info['gen/mean_episode_length'],
gen_collision_rate=info['gen/collision_rate'])
# save model checkpoints
ep = info['epoch'] + 1
if (ep % 25 == 0):
torch.save(info['policy'].state_dict(), f'policy_epoch{ep}.pt')
value, policy = gail_ppo(
env_fn=env_fn,
expert_data=expert_data,
discriminator=discriminator,
disc_opt=disc_opt,
disc_iters=config['discriminator']['iterations_per_epoch'],
policy=policy,
value=value,
v_opt=v_opt,
v_iters=config['value']['iterations_per_epoch'],
epochs=config['train_epochs'],
rollout_episodes=60,
rollout_steps=200,
gamma=0.99,
gae_lambda=0.9,
clip_ratio=config['policy']['clip_ratio'],
pi_opt=pi_opt,
pi_iters=config['policy']['iterations_per_epoch'],
logger=SummaryWriter(comment='gail-ppo-options-setobs2'),
callback=callback,
lr_schedulers=[pi_lr_scheduler],
)
# save model
torch.save(policy.state_dict(), 'policy_final.pt')
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--train', choices=['A', 'B'])
parser.add_argument('--epochs', type=int, default=200)
parser.add_argument('--test', type=str, help='path to config file to run final training on')
parser.add_argument('--test_seeds', type=int, default=5)
parser.add_argument('--test_cpus', type=int, help='number of cpus available to split test seed training over')
args = parser.parse_args()
assert (args.train is None) ^ (args.test is None), 'Must either train on an experiment or test with a config file'
# if no test config specified, train
if args.test is None:
print('Running Tuning for Experiment %s'%(args.train))
analysis = tune.run(
training_function,
config={
'experiment': args.train,
'trainenv': {
'stop_on_collision': False,
},
'policy': {
'learning_rate': 3e-4,
'learning_rate_decay': 1.0,
'clip_ratio': 0.2,
'iterations_per_epoch': 100,
'hidden_layer_size': tune.grid_search([20, 40]),
'n_hidden_layers': tune.grid_search([2, 3]),
'activation':0,
},
'value': {
'learning_rate': 1e-4,
'weight_decay': 1e-3,
'iterations_per_epoch': 1000,
},
'discriminator': {
'learning_rate': 1e-3,
'weight_decay': 1e-4,
'iterations_per_epoch': 100,
'n_hidden_layers_element': tune.grid_search([3,4]),
'n_hidden_layers_global': tune.grid_search([1,2]),
'hidden_layer_size': 10,
'activation': 0,
},
'train_epochs': args.epochs,
'seed': 0,
}
)
best_config = analysis.get_best_config(metric='gen_collision_rate', mode='min')
print('Best config: ', best_config)
# safe best_config
if not os.path.isdir(os.path.join(DIR, 'best_configs')):
os.mkdir(os.path.join(DIR, 'best_configs'))
# save gail
with open(os.path.join(DIR, 'best_configs',f'gail_exp{args.train}.json'), 'w', encoding='utf-8') as f:
json.dump(best_config, f, ensure_ascii=False, indent=4)
# if config file specified, rerun it with appropriate number of seeds
else:
with open(args.test, 'rb') as f:
config = json.load(f)
print(f'Retraining {args.test} with {args.test_seeds} seeds on experiment {config["experiment"]}')
# rerun with appropriate number of seeds
rpt = {'cpu': int(args.test_cpus/args.test_seeds)} if (args.test_cpus is not None) else None
config['seed'] = tune.grid_search(list(range(1,args.test_seeds+1)))
analysis = tune.run(training_function, config=config, resources_per_trial=rpt)
# move final policies to appropriate directory
split_ = os.path.basename(args.test).split('_')
model = split_[0]
exper = split_[-1].split('.')[0]
savepath = os.path.join('test_policies',model,exper)
if not os.path.isdir(savepath):
os.makedirs(savepath)
import shutil
for i in range(args.test_seeds):
s = analysis._checkpoints[i]['config']['seed']
check_dir = analysis._checkpoints[i]['logdir']
shutil.copyfile(os.path.join(check_dir,'policy_final.pt'),
os.path.join(savepath, f'policy_seed{s}.pt'))
shutil.copyfile(os.path.join(check_dir,'params.json'),
os.path.join(savepath, 'config.json')) # copy config automatically

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More