mirror of
https://github.com/wassname/cr-dv3.git
synced 2026-09-12 12:21:56 +08:00
217 lines
7.9 KiB
Python
217 lines
7.9 KiB
Python
import importlib
|
|
import pathlib
|
|
import sys
|
|
import warnings
|
|
from functools import partial as bind
|
|
|
|
warnings.filterwarnings('ignore', '.*box bound precision lowered.*')
|
|
warnings.filterwarnings('ignore', '.*using stateful random seeds*')
|
|
warnings.filterwarnings('ignore', '.*is a deprecated alias for.*')
|
|
warnings.filterwarnings('ignore', '.*truncated to dtype int32.*')
|
|
|
|
directory = pathlib.Path(__file__).resolve()
|
|
directory = directory.parent
|
|
sys.path.append(str(directory.parent))
|
|
sys.path.append(str(directory.parent.parent))
|
|
sys.path.append(str(directory.parent.parent.parent))
|
|
__package__ = directory.name
|
|
|
|
import embodied
|
|
from embodied import wrappers
|
|
|
|
|
|
def main(argv=None):
|
|
from . import agent as agt
|
|
|
|
parsed, other = embodied.Flags(configs=['defaults']).parse_known(argv)
|
|
config = embodied.Config(agt.Agent.configs['defaults'])
|
|
for name in parsed.configs:
|
|
config = config.update(agt.Agent.configs[name])
|
|
config = embodied.Flags(config).parse(other)
|
|
args = embodied.Config(
|
|
**config.run, logdir=config.logdir,
|
|
batch_steps=config.batch_size * config.batch_length)
|
|
print(config)
|
|
|
|
logdir = embodied.Path(args.logdir)
|
|
logdir.mkdirs()
|
|
config.save(logdir / 'config.yaml')
|
|
step = embodied.Counter()
|
|
logger = make_logger(parsed, logdir, step, config)
|
|
|
|
cleanup = []
|
|
try:
|
|
|
|
if args.script == 'train':
|
|
replay = make_replay(config, logdir / 'replay')
|
|
env = make_envs(config)
|
|
cleanup.append(env)
|
|
agent = agt.Agent(env.obs_space, env.act_space, step, config)
|
|
embodied.run.train(agent, env, replay, logger, args)
|
|
|
|
elif args.script == 'train_save':
|
|
replay = make_replay(config, logdir / 'replay')
|
|
env = make_envs(config)
|
|
cleanup.append(env)
|
|
agent = agt.Agent(env.obs_space, env.act_space, step, config)
|
|
embodied.run.train_save(agent, env, replay, logger, args)
|
|
|
|
elif args.script == 'train_eval':
|
|
replay = make_replay(config, logdir / 'replay')
|
|
eval_replay = make_replay(config, logdir / 'eval_replay', is_eval=True)
|
|
env = make_envs(config)
|
|
eval_env = make_envs(config) # mode='eval'
|
|
cleanup += [env, eval_env]
|
|
agent = agt.Agent(env.obs_space, env.act_space, step, config)
|
|
embodied.run.train_eval(
|
|
agent, env, eval_env, replay, eval_replay, logger, args)
|
|
|
|
elif args.script == 'train_holdout':
|
|
replay = make_replay(config, logdir / 'replay')
|
|
if config.eval_dir:
|
|
assert not config.train.eval_fill
|
|
eval_replay = make_replay(config, config.eval_dir, is_eval=True)
|
|
else:
|
|
assert 0 < args.eval_fill <= config.replay_size // 10, args.eval_fill
|
|
eval_replay = make_replay(config, logdir / 'eval_replay', is_eval=True)
|
|
env = make_envs(config)
|
|
cleanup.append(env)
|
|
agent = agt.Agent(env.obs_space, env.act_space, step, config)
|
|
embodied.run.train_holdout(
|
|
agent, env, replay, eval_replay, logger, args)
|
|
|
|
elif args.script == 'eval_only':
|
|
env = make_envs(config) # mode='eval'
|
|
cleanup.append(env)
|
|
agent = agt.Agent(env.obs_space, env.act_space, step, config)
|
|
embodied.run.eval_only(agent, env, logger, args)
|
|
|
|
elif args.script == 'parallel':
|
|
assert config.run.actor_batch <= config.envs.amount, (
|
|
config.run.actor_batch, config.envs.amount)
|
|
step = embodied.Counter()
|
|
env = make_env(config)
|
|
agent = agt.Agent(env.obs_space, env.act_space, step, config)
|
|
env.close()
|
|
replay = make_replay(config, logdir / 'replay', rate_limit=True)
|
|
embodied.run.parallel(
|
|
agent, replay, logger, bind(make_env, config),
|
|
num_envs=config.envs.amount, args=args)
|
|
|
|
else:
|
|
raise NotImplementedError(args.script)
|
|
finally:
|
|
for obj in cleanup:
|
|
obj.close()
|
|
|
|
|
|
def make_logger(parsed, logdir, step, config):
|
|
multiplier = config.env.get(config.task.split('_')[0], {}).get('repeat', 1)
|
|
logger = embodied.Logger(step, [
|
|
embodied.logger.TerminalOutput(config.filter),
|
|
embodied.logger.JSONLOutput(logdir, 'metrics.jsonl'),
|
|
embodied.logger.JSONLOutput(logdir, 'scores.jsonl', 'episode/score'),
|
|
embodied.logger.TensorBoardOutput(logdir),
|
|
# embodied.logger.WandBOutput(logdir.name, config),
|
|
# embodied.logger.MLFlowOutput(logdir.name),
|
|
], multiplier)
|
|
return logger
|
|
|
|
|
|
def make_replay(
|
|
config, directory=None, is_eval=False, rate_limit=False, **kwargs):
|
|
assert config.replay == 'uniform' or not rate_limit
|
|
length = config.batch_length
|
|
size = config.replay_size // 10 if is_eval else config.replay_size
|
|
if config.replay == 'uniform' or is_eval:
|
|
kw = {'online': config.replay_online}
|
|
if rate_limit and config.run.train_ratio > 0:
|
|
kw['samples_per_insert'] = config.run.train_ratio / config.batch_length
|
|
kw['tolerance'] = 10 * config.batch_size
|
|
kw['min_size'] = config.batch_size
|
|
replay = embodied.replay.Uniform(length, size, directory, **kw)
|
|
elif config.replay == 'reverb':
|
|
replay = embodied.replay.Reverb(length, size, directory)
|
|
elif config.replay == 'curious-replay':
|
|
replay = embodied.replay.CuriousReplay(length, size, directory, hyper=config.replay_hyper)
|
|
elif config.replay == 'per':
|
|
replay = embodied.replay.PrioritizedExperienceReplay(length, size, directory, hyper=config.replay_hyper)
|
|
elif config.replay == 'count-based':
|
|
replay = embodied.replay.CountBasedReplay(length, size, directory, hyper=config.replay_hyper)
|
|
elif config.replay == 'adversarial':
|
|
replay = embodied.replay.AdversarialReplay(length, size, directory, hyper=config.replay_hyper)
|
|
elif config.replay == 'chunks':
|
|
replay = embodied.replay.NaiveChunks(length, size, directory)
|
|
else:
|
|
raise NotImplementedError(config.replay)
|
|
return replay
|
|
|
|
|
|
def make_envs(config, **overrides):
|
|
suite, task = config.task.split('_', 1)
|
|
ctors = []
|
|
for index in range(config.envs.amount):
|
|
ctor = lambda: make_env(config, **overrides)
|
|
if config.envs.parallel != 'none':
|
|
ctor = bind(embodied.Parallel, ctor, config.envs.parallel)
|
|
if config.envs.restart:
|
|
ctor = bind(wrappers.RestartOnException, ctor)
|
|
ctors.append(ctor)
|
|
envs = [ctor() for ctor in ctors]
|
|
return embodied.BatchEnv(envs, parallel=(config.envs.parallel != 'none'))
|
|
|
|
|
|
def make_env(config, **overrides):
|
|
# You can add custom environments by creating and returning the environment
|
|
# instance here. Environments with different interfaces can be converted
|
|
# using `embodied.envs.from_gym.FromGym` and `embodied.envs.from_dm.FromDM`.
|
|
suite, task = config.task.split('_', 1)
|
|
ctor = {
|
|
'dummy': 'embodied.envs.dummy:Dummy',
|
|
'gym': 'embodied.envs.from_gym:FromGym',
|
|
'dm': 'embodied.envs.from_dmenv:FromDM',
|
|
'crafter': 'embodied.envs.crafter:Crafter',
|
|
'dmc': 'embodied.envs.dmc:DMC',
|
|
'atari': 'embodied.envs.atari:Atari',
|
|
'dmlab': 'embodied.envs.dmlab:DMLab',
|
|
'minecraft': 'embodied.envs.minecraft:Minecraft',
|
|
'loconav': 'embodied.envs.loconav:LocoNav',
|
|
'pinpad': 'embodied.envs.pinpad:PinPad',
|
|
'cdmc': 'embodied.envs.cdmc:CDMC',
|
|
'ddmc': 'embodied.envs.ddmc:DDMC',
|
|
}[suite]
|
|
if isinstance(ctor, str):
|
|
module, cls = ctor.split(':')
|
|
module = importlib.import_module(module)
|
|
ctor = getattr(module, cls)
|
|
kwargs = config.env.get(suite, {})
|
|
kwargs.update(overrides)
|
|
env = ctor(task, **kwargs)
|
|
return wrap_env(env, config)
|
|
|
|
|
|
def wrap_env(env, config):
|
|
args = config.wrapper
|
|
for name, space in env.act_space.items():
|
|
if name == 'reset':
|
|
continue
|
|
elif space.discrete:
|
|
env = wrappers.OneHotAction(env, name)
|
|
elif args.discretize:
|
|
env = wrappers.DiscretizeAction(env, name, args.discretize)
|
|
else:
|
|
env = wrappers.NormalizeAction(env, name)
|
|
env = wrappers.ExpandScalars(env)
|
|
if args.length:
|
|
env = wrappers.TimeLimit(env, args.length, args.reset)
|
|
if args.checks:
|
|
env = wrappers.CheckSpaces(env)
|
|
for name, space in env.act_space.items():
|
|
if not space.discrete:
|
|
env = wrappers.ClipAction(env, name)
|
|
return env
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|