def main(): parser = argparse.ArgumentParser() parser.add_argument("--env", type=str, default="BreakoutNoFrameskip-v4", help="Gym Env ID.") parser.add_argument("--gpu", type=int, default=0, help="GPU device ID. Set to -1 to use CPUs only.") parser.add_argument( "--num-envs", type=int, default=8, help="Number of env instances run in parallel.", ) parser.add_argument("--seed", type=int, default=0, help="Random seed [0, 2 ** 32)") parser.add_argument( "--outdir", type=str, default="results", help=("Directory path to save output files." " If it does not exist, it will be created."), ) parser.add_argument("--steps", type=int, default=10**7, help="Total time steps for training.") parser.add_argument( "--max-frames", type=int, default=30 * 60 * 60, # 30 minutes with 60 fps help="Maximum number of frames for each episode.", ) parser.add_argument("--lr", type=float, default=2.5e-4, help="Learning rate.") parser.add_argument( "--eval-interval", type=int, default=100000, help="Interval (in timesteps) between evaluation phases.", ) parser.add_argument( "--eval-n-runs", type=int, default=10, help="Number of episodes ran in an evaluation phase.", ) parser.add_argument( "--demo", action="store_true", default=False, help="Run demo episodes, not training.", ) parser.add_argument( "--load", type=str, default="", help=("Directory path to load a saved agent data from" " if it is a non-empty string."), ) parser.add_argument( "--log-level", type=int, default=20, help="Logging level. 10:DEBUG, 20:INFO etc.", ) parser.add_argument( "--render", action="store_true", default=False, help="Render env states in a GUI window.", ) parser.add_argument( "--monitor", action="store_true", default=False, help= ("Monitor env. Videos and additional information are saved as output files." ), ) parser.add_argument( "--update-interval", type=int, default=128 * 8, help="Interval (in timesteps) between PPO iterations.", ) parser.add_argument( "--batchsize", type=int, default=32 * 8, help="Size of minibatch (in timesteps).", ) parser.add_argument( "--epochs", type=int, default=4, help="Number of epochs used for each PPO iteration.", ) parser.add_argument( "--log-interval", type=int, default=10000, help="Interval (in timesteps) of printing logs.", ) parser.add_argument( "--recurrent", action="store_true", default=False, help="Use a recurrent model. See the code for the model definition.", ) parser.add_argument( "--flicker", action="store_true", default=False, help=("Use so-called flickering Atari, where each" " screen is blacked out with probability 0.5."), ) parser.add_argument( "--no-frame-stack", action="store_true", default=False, help= ("Disable frame stacking so that the agent can only see the current screen." ), ) parser.add_argument( "--checkpoint-frequency", type=int, default=None, help="Frequency at which agents are stored.", ) args = parser.parse_args() import logging logging.basicConfig(level=args.log_level) # Set a random seed used in PFRL. utils.set_random_seed(args.seed) # Set different random seeds for different subprocesses. # If seed=0 and processes=4, subprocess seeds are [0, 1, 2, 3]. # If seed=1 and processes=4, subprocess seeds are [4, 5, 6, 7]. process_seeds = np.arange(args.num_envs) + args.seed * args.num_envs assert process_seeds.max() < 2**32 args.outdir = experiments.prepare_output_dir(args, args.outdir) print("Output files are saved in {}".format(args.outdir)) def make_env(idx, test): # Use different random seeds for train and test envs process_seed = int(process_seeds[idx]) env_seed = 2**32 - 1 - process_seed if test else process_seed env = atari_wrappers.wrap_deepmind( atari_wrappers.make_atari(args.env, max_frames=args.max_frames), episode_life=not test, clip_rewards=not test, flicker=args.flicker, frame_stack=False, ) env.seed(env_seed) if args.monitor: env = pfrl.wrappers.Monitor( env, args.outdir, mode="evaluation" if test else "training") if args.render: env = pfrl.wrappers.Render(env) return env def make_batch_env(test): vec_env = pfrl.envs.MultiprocessVectorEnv([ (lambda: make_env(idx, test)) for idx, env in enumerate(range(args.num_envs)) ]) if not args.no_frame_stack: vec_env = pfrl.wrappers.VectorFrameStack(vec_env, 4) return vec_env sample_env = make_batch_env(test=False) print("Observation space", sample_env.observation_space) print("Action space", sample_env.action_space) n_actions = sample_env.action_space.n obs_n_channels = sample_env.observation_space.low.shape[0] del sample_env def lecun_init(layer, gain=1): if isinstance(layer, (nn.Conv2d, nn.Linear)): pfrl.initializers.init_lecun_normal(layer.weight, gain) nn.init.zeros_(layer.bias) else: pfrl.initializers.init_lecun_normal(layer.weight_ih_l0, gain) pfrl.initializers.init_lecun_normal(layer.weight_hh_l0, gain) nn.init.zeros_(layer.bias_ih_l0) nn.init.zeros_(layer.bias_hh_l0) return layer if args.recurrent: model = pfrl.nn.RecurrentSequential( lecun_init(nn.Conv2d(obs_n_channels, 32, 8, stride=4)), nn.ReLU(), lecun_init(nn.Conv2d(32, 64, 4, stride=2)), nn.ReLU(), lecun_init(nn.Conv2d(64, 64, 3, stride=1)), nn.ReLU(), nn.Flatten(), lecun_init(nn.Linear(3136, 512)), nn.ReLU(), lecun_init(nn.GRU(num_layers=1, input_size=512, hidden_size=512)), pfrl.nn.Branched( nn.Sequential( lecun_init(nn.Linear(512, n_actions), 1e-2), SoftmaxCategoricalHead(), ), lecun_init(nn.Linear(512, 1)), ), ) else: model = nn.Sequential( lecun_init(nn.Conv2d(obs_n_channels, 32, 8, stride=4)), nn.ReLU(), lecun_init(nn.Conv2d(32, 64, 4, stride=2)), nn.ReLU(), lecun_init(nn.Conv2d(64, 64, 3, stride=1)), nn.ReLU(), nn.Flatten(), lecun_init(nn.Linear(3136, 512)), nn.ReLU(), pfrl.nn.Branched( nn.Sequential( lecun_init(nn.Linear(512, n_actions), 1e-2), SoftmaxCategoricalHead(), ), lecun_init(nn.Linear(512, 1)), ), ) opt = torch.optim.Adam(model.parameters(), lr=args.lr, eps=1e-5) def phi(x): # Feature extractor return np.asarray(x, dtype=np.float32) / 255 agent = PPO( model, opt, gpu=args.gpu, phi=phi, update_interval=args.update_interval, minibatch_size=args.batchsize, epochs=args.epochs, clip_eps=0.1, clip_eps_vf=None, standardize_advantages=True, entropy_coef=1e-2, recurrent=args.recurrent, max_grad_norm=0.5, ) if args.load: agent.load(args.load) if args.demo: eval_stats = experiments.eval_performance( env=make_batch_env(test=True), agent=agent, n_steps=None, n_episodes=args.eval_n_runs, ) print("n_runs: {} mean: {} median: {} stdev: {}".format( args.eval_n_runs, eval_stats["mean"], eval_stats["median"], eval_stats["stdev"], )) else: step_hooks = [] # Linearly decay the learning rate to zero def lr_setter(env, agent, value): for param_group in agent.optimizer.param_groups: param_group["lr"] = value step_hooks.append( experiments.LinearInterpolationHook(args.steps, args.lr, 0, lr_setter)) experiments.train_agent_batch_with_evaluation( agent=agent, env=make_batch_env(False), eval_env=make_batch_env(True), outdir=args.outdir, steps=args.steps, eval_n_steps=None, eval_n_episodes=args.eval_n_runs, checkpoint_freq=args.checkpoint_frequency, eval_interval=args.eval_interval, log_interval=args.log_interval, save_best_so_far_agent=False, step_hooks=step_hooks, )
def main(): import logging parser = argparse.ArgumentParser() parser.add_argument( "--gpu", type=int, default=0, help="GPU to use, set to -1 if no GPU." ) parser.add_argument( "--env", type=str, default="reach_target-ee-vision-v0", help="OpenAI Gym MuJoCo env to perform algorithm on.", ) parser.add_argument( "--num-envs", type=int, default=1, help="Number of envs run in parallel." ) parser.add_argument("--seed", type=int, default=0, help="Random seed [0, 2 ** 32)") parser.add_argument( "--outdir", type=str, default="results", help=( "Directory path to save output files." " If it does not exist, it will be created." ), ) parser.add_argument( "--steps", type=int, default=2 * 10 ** 6, help="Total number of timesteps to train the agent.", ) parser.add_argument( "--eval-interval", type=int, default=100000, help="Interval in timesteps between evaluations.", ) parser.add_argument( "--eval-n-runs", type=int, default=100, help="Number of episodes run for each evaluation.", ) parser.add_argument( "--render", action="store_true", help="Render env states in a GUI window." ) parser.add_argument( "--demo", action="store_true", help="Just run evaluation, not training." ) parser.add_argument("--load-pretrained", action="store_true", default=False) parser.add_argument( "--load", type=str, default="", help="Directory to load agent from." ) parser.add_argument( "--log-level", type=int, default=logging.INFO, help="Level of the root logger." ) parser.add_argument( "--monitor", action="store_true", help="Wrap env with gym.wrappers.Monitor." ) parser.add_argument( "--log-interval", type=int, default=1000, help="Interval in timesteps between outputting log messages during training", ) parser.add_argument( "--update-interval", type=int, default=2048, help="Interval in timesteps between model updates.", ) parser.add_argument( "--epochs", type=int, default=10, help="Number of epochs to update model for per PPO iteration.", ) parser.add_argument( "--action-size", type=int, default=3, help="Action size (needs to match env.action_space)", ) parser.add_argument("--batch-size", type=int, default=64, help="Minibatch size") args = parser.parse_args() logging.basicConfig(level=args.log_level) # Set a random seed used in PFRL utils.set_random_seed(args.seed) # Set different random seeds for different subprocesses. # If seed=0 and processes=4, subprocess seeds are [0, 1, 2, 3]. # If seed=1 and processes=4, subprocess seeds are [4, 5, 6, 7]. process_seeds = np.arange(args.num_envs) + args.seed * args.num_envs assert process_seeds.max() < 2 ** 32 args.outdir = experiments.prepare_output_dir(args, args.outdir) def make_env(process_idx, test): render_mode = 'human' if args.render else None env = NormalizeAction(GraspActionWrapper(FlattenObservation(ResizeObservation(WristObsWrapper(gym.make(args.env, render_mode=render_mode)), (64, 64))), args.action_size)) # env = GraspActionWrapper(RescaleAction(FlattenObservation(ResizeObservation(WristObsWrapper(gym.make(args.env)), (64, 64))), -0.5, 0.5)) # Use different random seeds for train and test envs process_seed = int(process_seeds[process_idx]) env_seed = 2 ** 32 - 1 - process_seed if test else process_seed env.seed(env_seed) # Cast observations to float32 because our model uses float32 env = pfrl.wrappers.CastObservationToFloat32(env) if args.monitor: env = pfrl.wrappers.Monitor(env, args.outdir) if args.render: env = pfrl.wrappers.Render(env) return env def make_batch_env(test): return MultiprocessVectorEnv( [ functools.partial(make_env, idx, test) for idx, env in enumerate(range(args.num_envs)) ] ) # Only for getting timesteps, and obs-action spaces # sample_env = RescaleAction(GraspActionWrapper(FlattenObservation(ResizeObservation(WristObsWrapper(gym.make(args.env)), (64, 64))), args.action_size), -0.5, 0.5) # timestep_limit = sample_env.spec.max_episode_steps timestep_limit = 200 # obs_space = sample_env.observation_space obs_space = spaces.Box(low=0, high=1, shape=(64 * 64 * 3,)) # action_space = sample_env.action_space action_space = spaces.Box(low=-1.0, high=1.0, shape=(args.action_size,)) print("Observation space:", obs_space) print("Action space:", action_space) # assert obs_space == spaces.Box(low=0, high=1, shape=(64 * 64 * 3,)) # assert action_space == spaces.Box(low=-1.0, high=1.0, shape=(args.action_size,)) # sample_env.close() assert isinstance(action_space, gym.spaces.Box) # Normalize observations based on their empirical mean and variance obs_normalizer = pfrl.nn.EmpiricalNormalization( obs_space.low.size, clip_threshold=5 ) obs_size = obs_space.low.size action_size = action_space.low.size policy = torch.nn.Sequential( nn.Linear(obs_size, 64), nn.Tanh(), nn.Linear(64, 64), nn.Tanh(), nn.Linear(64, action_size), pfrl.policies.GaussianHeadWithStateIndependentCovariance( action_size=action_size, var_type="diagonal", var_func=lambda x: torch.exp(2 * x), # Parameterize log std var_param_init=0, # log std = 0 => std = 1 ), ) vf = torch.nn.Sequential( nn.Linear(obs_size, 64), nn.Tanh(), nn.Linear(64, 64), nn.Tanh(), nn.Linear(64, 1), ) # While the original paper initialized weights by normal distribution, # we use orthogonal initialization as the latest openai/baselines does. def ortho_init(layer, gain): nn.init.orthogonal_(layer.weight, gain=gain) nn.init.zeros_(layer.bias) ortho_init(policy[0], gain=1) ortho_init(policy[2], gain=1) ortho_init(policy[4], gain=1e-2) ortho_init(vf[0], gain=1) ortho_init(vf[2], gain=1) ortho_init(vf[4], gain=1) # Combine a policy and a value function into a single model model = pfrl.nn.Branched(policy, vf) opt = torch.optim.Adam(model.parameters(), lr=3e-4, eps=1e-5) agent = PPO( model, opt, obs_normalizer=obs_normalizer, gpu=args.gpu, update_interval=args.update_interval, minibatch_size=args.batch_size, epochs=args.epochs, clip_eps_vf=None, entropy_coef=0, standardize_advantages=True, gamma=0.995, lambd=0.97, ) if args.load or args.load_pretrained: if args.load_pretrained: raise Exception("Pretrained models are currently unsupported.") # either load or load_pretrained must be false assert not args.load or not args.load_pretrained if args.load: agent.load(args.load) else: agent.load(utils.download_model("PPO", args.env, model_type="final")[0]) if args.demo: env = make_batch_env(True) eval_stats = experiments.eval_performance( env=env, agent=agent, n_steps=None, n_episodes=args.eval_n_runs, max_episode_len=timestep_limit, ) print( "n_runs: {} mean: {} median: {} stdev {}".format( args.eval_n_runs, eval_stats["mean"], eval_stats["median"], eval_stats["stdev"], ) ) else: experiments.train_agent_batch_with_evaluation( agent=agent, env=make_batch_env(False), eval_env=make_batch_env(True), outdir=args.outdir, steps=args.steps, eval_n_steps=None, eval_n_episodes=args.eval_n_runs, eval_interval=args.eval_interval, log_interval=args.log_interval, max_episode_len=timestep_limit, save_best_so_far_agent=True, )
def main(): import logging torch.cuda.empty_cache() parser = argparse.ArgumentParser() parser.add_argument('--gpu', type=int, default=0, help='GPU to use, set to -1 if no GPU') parser.add_argument('--env', type=str, default='LidarBat-v0', help='Bat simulation env') parser.add_argument('--arch', type=str, default='FFGaussian', choices=('FFSoftmax', 'FFMellowmax', 'FFGaussian')) parser.add_argument('--bound-mean', action='store_true') parser.add_argument('--seed', type=int, default=0, help='Random seed [0, 2 ** 32)') parser.add_argument('--outdir', type=str, default='data/ppo', help='Directory path to save output files.' ' If it does not exist, it will be created.') parser.add_argument('--steps', type=int, default=10**6) parser.add_argument('--eval-interval', type=int, default=10000) parser.add_argument('--eval-n-runs', type=int, default=10) parser.add_argument('--reward-scale-factor', type=float, default=1e-2) parser.add_argument('--standardize-advantages', action='store_true') parser.add_argument('--render', action='store_true', default=False) parser.add_argument('--lr', type=float, default=3e-4) parser.add_argument('--weight-decay', type=float, default=0.0) parser.add_argument('--demo', action='store_true', default=False) parser.add_argument('--load', type=str, default='') parser.add_argument("--load-pretrained", action="store_true", default=False) parser.add_argument('--logger-level', type=int, default=logging.DEBUG) parser.add_argument('--monitor', action='store_true') parser.add_argument( "--log-interval", type=int, default=1000, help= "Interval in timesteps between outputting log messages during training", ) parser.add_argument("--num-envs", type=int, default=1, help="Number of envs run in parallel.") parser.add_argument("--batch-size", type=int, default=64, help="Minibatch size") parser.add_argument('--update-interval', type=int, default=2048) parser.add_argument('--batchsize', type=int, default=64) parser.add_argument('--epochs', type=int, default=10) parser.add_argument('--entropy-coef', type=float, default=0.0) args = parser.parse_args() logging.basicConfig(level=args.logger_level) # Set a random seed used in PFRL utils.set_random_seed(args.seed) # Set different random seeds for different subprocesses. # If seed=0 and processes=4, subprocess seeds are [0, 1, 2, 3]. # If seed=1 and processes=4, subprocess seeds are [4, 5, 6, 7]. process_seeds = np.arange(args.num_envs) + args.seed * args.num_envs assert process_seeds.max() < 2**32 args.outdir = experiments.prepare_output_dir(args, args.outdir) def make_env(process_idx, test): env = gym.make(args.env) # Use different random seeds for train and test envs process_seed = int(process_seeds[process_idx]) env_seed = 2**32 - 1 - process_seed if test else process_seed env.seed(env_seed) # Cast observations to float32 because our model uses float32 env = pfrl.wrappers.CastObservationToFloat32(env) if args.monitor: env = pfrl.wrappers.Monitor(env, args.outdir) # TODO # if not test is not here if args.render: env = pfrl.wrappers.Render(env) return env def make_batch_env(test): return pfrl.envs.MultiprocessVectorEnv([ functools.partial(make_env, idx, test) for idx, env in enumerate(range(args.num_envs)) ]) # Only for getting timesteps, and obs-action spaces sample_env = gym.make(args.env) timestep_limit = sample_env.spec.max_episode_steps obs_space = sample_env.observation_space action_space = sample_env.action_space print("Observation space:", obs_space) print("Action space:", action_space) assert isinstance(action_space, gym.spaces.Box) # Normalize observations based on their empirical mean and variance obs_normalizer = pfrl.nn.EmpiricalNormalization(obs_space.low.size, clip_threshold=5) # pulicy here magic number must be concidered again obs_size = obs_space.low.size action_size = action_space.low.size policy = torch.nn.Sequential( nn.Linear(obs_size, 64), nn.Tanh(), nn.Linear(64, 64), nn.Tanh(), nn.Linear(64, action_size), pfrl.policies.GaussianHeadWithStateIndependentCovariance( action_size=action_size, var_type="diagonal", var_func=lambda x: torch.exp(2 * x), # Parameterize log std var_param_init=0, # log std = 0 => std = 1 ), ) vf = torch.nn.Sequential( nn.Linear(obs_size, 64), nn.Tanh(), nn.Linear(64, 64), nn.Tanh(), nn.Linear(64, 1), ) # While the original paper initialized weights by normal distribution, # we use orthogonal initialization as the latest openai/baselines does. def ortho_init(layer, gain): nn.init.orthogonal_(layer.weight, gain=gain) nn.init.zeros_(layer.bias) ortho_init(policy[0], gain=1) ortho_init(policy[2], gain=1) ortho_init(policy[4], gain=1e-2) ortho_init(vf[0], gain=1) ortho_init(vf[2], gain=1) ortho_init(vf[4], gain=1) # Combine a policy and a value function into a single model model = pfrl.nn.Branched(policy, vf) opt = torch.optim.Adam(model.parameters(), lr=args.lr, eps=1e-5) agent = PPO( model, opt, obs_normalizer=obs_normalizer, gpu=args.gpu, update_interval=args.update_interval, minibatch_size=args.batch_size, epochs=args.epochs, clip_eps_vf=None, entropy_coef=args.entropy_coef, standardize_advantages=True, gamma=0.995, lambd=0.97, ) if args.load or args.load_pretrained: if args.load_pretrained: raise Exception("Pretrained models are currently unsupported.") # either load or load_pretrained must be false assert not args.load or not args.load_pretrained if args.load: agent.load(args.load) else: agent.load( utils.download_model("PPO", args.env, model_type="final")[0]) if args.demo: env = make_batch_env(True) eval_stats = experiments.eval_performance( env=env, agent=agent, n_steps=None, n_episodes=args.eval_n_runs, max_episode_len=timestep_limit, ) print("n_runs: {} mean: {} median: {} stdev {}".format( args.eval_n_runs, eval_stats["mean"], eval_stats["median"], eval_stats["stdev"], )) else: experiments.train_agent_batch_with_evaluation( agent=agent, env=make_batch_env(False), eval_env=make_batch_env(True), outdir=args.outdir, steps=args.steps, eval_n_steps=None, eval_n_episodes=args.eval_n_runs, eval_interval=args.eval_interval, log_interval=args.log_interval, max_episode_len=timestep_limit, save_best_so_far_agent=False, )