def test_save_and_load(self): torch.manual_seed(42) config = ModelConfig() model = Model.create(config, logger=NullLogger()) model_dir = "local_tests/local_model_test" model.save(model_dir) assert os.path.exists(f"{model_dir}/config.json") assert os.path.exists(f"{model_dir}/model.pt") model = Model.load(model_dir).to(gpu) assert next(model.parameters()).device.type == gpu.type
def from_saved(cls, loc: str, use_best: bool, epsilon: float, workers: int, depth: int): net = Model.load(loc, load_best=use_best).to(gpu) return cls(net, epsilon=epsilon, workers=workers, depth=depth)
def from_saved(cls, loc: str, use_best: bool, c: float, search_graph: bool): net = Model.load(loc, load_best=use_best) net.to(gpu) return cls(net, c=c, search_graph=search_graph)
def from_saved(cls, loc: str, use_best: bool): net = Model.load(loc, load_best=use_best) net.to(gpu) return cls(net)
def from_saved(cls, loc: str, use_best: bool, lambda_: float, expansions: int) -> DeepAgent: net = Model.load(loc, load_best=use_best).to(gpu) return cls(net, lambda_=lambda_, expansions=expansions)
def from_saved(cls, loc: str, use_best: bool, sample_policy=False): net = Model.load(loc, load_best=use_best) net.to(gpu) return cls(net, sample_policy)
def agent_optimize(): """ Main way to run optimization. Hard coded to run optimization at 1 sec per game, but other behaviour can be set with CLI arguments seen by running `python librubiks/solving/hyper_optim.py --help`. Does not support config arguments. NB: The path here is different to the one in runeval and runtrain: It needs to be to folder containing model.pt! It doesen't work with parent folder. Can work with runeval through ``` python librubiks/solving/hyper_optim.py --location example/net1/ python runeval.py --location example/ --optimized_params True ``` """ set_seeds() #Lot of overhead just for default argument niceness: latest model is latest from runeval import train_folders model_path = '' if train_folders: for folder in [train_folders[-1]] + glob(f"{train_folders[-1]}/*/"): if os.path.isfile(os.path.join(folder, 'model.pt')): model_path = os.path.join(folder) break parser = argparse.ArgumentParser(description='Optimize Monte Carlo Tree Search for one model') parser.add_argument('--location', help='Folder which includes model.pt. Results will also be saved here', type=str, default=model_path) parser.add_argument('--iterations', help='Number of iterations of Bayesian Optimization', type=int, default=125) parser.add_argument('--agent', help='Name of agent corresponding to agent class in librubiks.solving.agents', type=str, default='AStar', choices = ['AStar', 'MCTS', 'EGVM']) parser.add_argument('--depth', help='Single number corresponding to the depth at which to test. If 0: run this at deep', type=int, default=0) parser.add_argument('--eval_games', help='Number of games to evaluate at depth', type = int, default='100') parser.add_argument('--save_optimal', help='If Tue, saves a JSON of optimal hyperparameters usable for runeval', type=literal_eval, default=True, choices = [True, False]) parser.add_argument('--use_best', help="Set to True to use model-best.pt instead of model.pt.", type=literal_eval, default=True, choices = [True, False]) parser.add_argument('--optim_lengths', help="Set to true to optimize against sol percentage / solution length. Else, simply use sol %", type=literal_eval, default=True, choices = [True, False]) parser.add_argument('--optimizer', help="Either BO or grid", type=str, default="grid", choices = ("grid", "BO")) args = parser.parse_args() agent_name = args.agent if agent_name == 'MCTS': params = { 'c': (0.1, 100), } def prepper(params): return params persistent_params = { 'net': Model.load(args.location, load_best=args.use_best), 'search_graph': True, } elif agent_name == 'AStar': params = { 'lambda_': (0, 0.4), 'expansions': (1, 1000), } def prepper(params): params['expansions'] = int(params['expansions']) return params persistent_params = { 'net': Model.load(args.location, load_best=args.use_best), } elif agent_name == 'EGVM': params = { 'epsilon': (0, 0.5), 'workers': (1, 500), 'depth': (1, 250), } def prepper(params): params['workers'] = int(params['workers']) params['depth'] = int(params['depth']) return params persistent_params = { 'net': Model.load(args.location, load_best=args.use_best), } else: raise NameError(f"{agent_name} does not correspond to a known agent, please pick either AStar, MCTS or EGVM") logger = Logger(os.path.join(args.location, f'{agent_name}_optimization.log'), 'Optimization') logger.log(f"{agent_name} optimization. Using network from {model_path}.") logger.log(f"Received arguments: {vars(args)}") agent = getattr(agents, agent_name) evaluator = Evaluator(n_games=args.eval_games, max_time=5, scrambling_depths=range(0) if args.depth == 0 else [args.depth]) assert args.optimizer in ["BO", "grid"], f"Optimizer should be 'BO' or 'grid', not '{args.optimizer}'" if args.optimizer == "BO": optimizer = BayesianOptimizer(target_function=None, parameters=params, logger=logger) else: optimizer = GridSearch(target_function=None, parameters=params, logger=logger) optimizer.objective_from_evaluator(evaluator, agent, persistent_params, param_prepper=prepper, optim_lengths=args.optim_lengths) optimizer.optimize(args.iterations) if args.save_optimal: with open(os.path.join(args.location, f'{agent_name}_params.json'), 'w') as outfile: json.dump(prepper(copy(optimizer.optimal)), outfile)
import matplotlib.pyplot as plt import numpy as np import torch from librubiks import gpu, no_grad from librubiks import cube from librubiks.model import Model from librubiks.utils import TickTock, Logger tt = TickTock() log = Logger("data/local_analyses/net.log", "Analyzing MCTS") net = Model.load("data/local_method_comparison/asgerfix").eval().to(gpu) def _get_adi_ff_slices(b, n): slice_size = n // b + 1 # Final slice may have overflow, however this is simply ignored when indexing slices = [slice(i * slice_size, (i + 1) * slice_size) for i in range(b)] return slices def _ff(oh_states, value=True, policy=True): batches = 1 while True: try: value_parts = [net(oh_states[slice_], policy=policy, value=value).squeeze() for slice_ in _get_adi_ff_slices(batches, len(oh_states))] values = torch.cat(value_parts).cpu() break except RuntimeError as e: # Usually caused by running out of vram. If not, the error is still raised, else batch size is reduced if "alloc" not in str(e): raise e
import matplotlib.pyplot as plt import numpy as np from librubiks import gpu, cube, rc_params from librubiks.model import Model from librubiks.solving.agents import MCTS from librubiks.utils import set_seeds, Logger, TickTock, TimeUnit np.set_printoptions(precision=4, threshold=np.inf) plt.rcParams.update(rc_params) tt = TickTock() log = Logger("data/local_analyses/mcts.log", "Analyzing MCTS") net = Model.load("local_net").eval().to(gpu) def solve(depth: int, c: float, time_limit: float): state, f, d = cube.scramble(depth, True) searcher = MCTS(net, c=c, search_graph=False) is_solved = searcher.search(state, time_limit) assert is_solved == (cube.get_solved().tostring() in searcher.indices) return is_solved, len(searcher.indices) def analyze_var(var: str, values: np.ndarray, other_vars: dict): x = values y = [] tree_sizes = [] log.section( f"Optimizing {var}\nExpected runtime: {len(x)*time_limit*n:.2f} s\nGames per evaluation: {n}"