diff --git a/solo_run_scripts/solo_test_eval_model.py b/solo_run_scripts/solo_test_eval_model.py new file mode 100644 index 0000000..e13585e --- /dev/null +++ b/solo_run_scripts/solo_test_eval_model.py @@ -0,0 +1,137 @@ +""" +This code will read in a trained model and output the classes for predicted objects matched to the ground truth + +""" +import logging +import os +import time + +import numpy as np +import deepdisc.astrodet.astrodet as toolkit + +from deepdisc.data_format.file_io import get_data_from_json +from deepdisc.data_format.image_readers import HSCImageReader +from deepdisc.inference.match_objects import get_matched_object_classes +from deepdisc.inference.predictors import return_predictor_transformer +from deepdisc.utils.parse_arguments import dtype_from_args, make_inference_arg_parser + +from detectron2 import model_zoo +from detectron2.config import LazyConfig +from detectron2.data import MetadataCatalog +from detectron2.utils.logger import setup_logger + +from pathlib import Path + +setup_logger() +logger = logging.getLogger(__name__) + +# Inference should use the config with parameters that are used in training +# cfg now already contains everything we've set previously. We changed it a little bit for inference: + +def return_predictor( + cfgfile, run_name, nc=1, output_dir="/home/shared/hsc/HSC/HSC_DR3/models/noclass/", roi_thresh=0.5 +): + """ + This function returns a trained model and its config file. + Used for models that have yacs config files + + Parameters + ---------- + cfgfile: str + A path to a model config file, provided by the detectron2 repo + run_name: str + Prefix used for the name of the saved model + nc: int + Number of prediction classes used in the model + output_dir: str + THe directory to save metric outputs + roi_thresh: float + Hyperparamter that functions as a detection sensitivity level + """ + cfg = LazyConfig.load(cfgfile) + + cfg.MODEL.ROI_HEADS.NUM_CLASSES = nc + cfg.OUTPUT_DIR = output_dir + cfg.MODEL.WEIGHTS = os.path.join(cfg.OUTPUT_DIR, run_name) # path to the model we just trained + cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = roi_thresh # set a custom testing threshold + + predictor = toolkit.AstroPredictor(cfg) + + return predictor, cfg + + +if __name__ == "__main__": + # --------- Handle args + args = make_inference_arg_parser().parse_args() + roi_thresh = args.roi_thresh + run_name = args.run_name + testfile = args.testfile + savedir = args.savedir + Path(savedir).mkdir(parents=True, exist_ok=True) + output_dir = args.output_dir + dtype=dtype_from_args(args.datatype) + + + # --------- Load data + dataset_names = ["test"] + datadir = "/home/shared/hsc/HSC/HSC_DR3/data/" + t0 = time.time() + dataset_dicts = {} + for i, d in enumerate(dataset_names): + dataset_dicts[d] = get_data_from_json(testfile) + print("Took ", time.time() - t0, "seconds to load samples") + + # Local vars/metadata + #classes = ["star", "galaxy"] + bb = args.run_name.split("_")[0] # backbone + + # --------- Start config stuff + cfgfile = ( + f"./tests/deepdisc/test_data/configs/" + f"solo/solo_cascade_mask_rcnn_swin_b_in21k_50ep_test_eval.py" + ) + cfg = LazyConfig.load(cfgfile) + + # --------- Setting a bunch of config stuff + cfg.model.roi_heads.num_classes = args.nc + + for bp in cfg.model.roi_heads.box_predictors: + bp.test_score_thresh = roi_thresh + + for box_predictor in cfg.model.roi_heads.box_predictors: + box_predictor.test_topk_per_image = 1000 + box_predictor.test_score_thresh = roi_thresh + + cfg.train.init_checkpoint = os.path.join(output_dir, run_name) + + # --------- Now we case predictor on model type (the second case has way different config vals it appears) + + cfg.OUTPUT_DIR = output_dir + if bb in ['Swin','MViTv2']: + predictor= return_predictor_transformer(cfg) + else: + cfgfile = "./tests/deepdisc/test_data/configs/solo/solo_test_eval_model_option.py" + predictor, cfg = return_predictor(cfgfile, run_name, output_dir=output_dir, nc=2, roi_thresh=roi_thresh) + + # --------- + def hsc_key_mapper(dataset_dict): + filenames = [ + dataset_dict["filename_G"], + dataset_dict["filename_R"], + dataset_dict["filename_I"], + ] + return filenames + IR = HSCImageReader(norm=args.norm) + + # --------- Do the thing + t0 = time.time() + print("Matching objects") + true_classes, pred_classes = get_matched_object_classes(dataset_dicts["test"], IR, hsc_key_mapper, predictor) + classes = np.array([true_classes, pred_classes]) + + savename = f"{bb}_test_matched_classes.npy" + np.save(os.path.join(args.savedir, savename), classes) + + print("Took ", time.time() - t0, " seconds") + print(classes) + t0 = time.time() \ No newline at end of file diff --git a/solo_test_run_transformers.py b/solo_run_scripts/solo_test_run_transformers.py similarity index 88% rename from solo_test_run_transformers.py rename to solo_run_scripts/solo_test_run_transformers.py index 23d4433..58fb058 100644 --- a/solo_test_run_transformers.py +++ b/solo_run_scripts/solo_test_run_transformers.py @@ -61,20 +61,19 @@ def main(train_head, args): scheme = args.scheme alphas = args.alphas modname = args.modname + dtype = dtype_from_args(args.dtype) + + # Get file locations + trainfile = dirpath + "single_test.json" + testfile = dirpath + "single_test.json" if modname == "swin": cfgfile = "./tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_swin_b_in21k_50ep.py" - # initwfile = "/home/shared/hsc/detectron2/projects/ViTDet/model_final_246a82.pkl" elif modname == "mvitv2": - cfgfile = "/home/shared/hsc/detectron2/projects/ViTDet/configs/COCO/cascade_mask_rcnn_mvitv2_b_in21k_100ep.py" - # initwfile = "/home/shared/hsc/detectron2/projects/ViTDet/model_final_8c3da3.pkl" - elif modname == "vitdet": - cfgfile = "/home/shared/hsc/detectron2/projects/ViTDet/configs/COCO/mask_rcnn_vitdet_b_100ep.py" - # initwfile = '/home/g4merz/deblend/detectron2/projects/ViTDet/model_final_435fa9.pkl' - # initwfile = "/home/shared/hsc/detectron2/projects/ViTDet/model_final_61ccd1.pkl" - dtype = dtype_from_args(args.dtype) - trainfile = dirpath + "single_test.json" - testfile = dirpath + "single_test.json" - + cfgfile = "./tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_mvitv2_b_in21k_100ep.py" + # Vitdet not currently available (cuda issues) so we're tabling it for now + #elif modname == "vitdet": + # cfgfile = "/home/shared/hsc/detectron2/projects/ViTDet/configs/COCO/mask_rcnn_vitdet_b_100ep.py" + # Load the config cfg = LazyConfig.load(cfgfile) @@ -91,6 +90,7 @@ def main(train_head, args): os.makedirs(cfg.OUTPUT_DIR, exist_ok=True) # Iterations for 15, 25, 35, 50 epochs + # TODOLIV could this stuff be moved to a config too? epoch = int(args.tl / cfg.dataloader.train.total_batch_size) e1 = 20 e2 = epoch * 10 @@ -135,7 +135,7 @@ def hsc_key_mapper(dataset_dict): schedulerHook = return_schedulerhook(optimizer) hookList = [lossHook, schedulerHook, saveHook] - trainer = return_lazy_trainer(model, loader, optimizer, cfg, cfg, hookList) + trainer = return_lazy_trainer(model, loader, optimizer, cfg, hookList) trainer.set_period(5) trainer.train(0, 20) diff --git a/solo_run_scripts/solo_test_run_transformers_DC2.py b/solo_run_scripts/solo_test_run_transformers_DC2.py new file mode 100644 index 0000000..7525da1 --- /dev/null +++ b/solo_run_scripts/solo_test_run_transformers_DC2.py @@ -0,0 +1,170 @@ +""" Training script for LazyConfig models. + +This uses the new "solo config" in which the previous yaml-style config +(a Detectron CfgNode type called cfg_loader) is now bundled into the +LazyConfig type cfg. +""" + +try: + # ignore ShapelyDeprecationWarning from fvcore + import warnings + from shapely.errors import ShapelyDeprecationWarning + warnings.filterwarnings("ignore", category=sShapelyDeprecationWarning) +except: + pass +warnings.filterwarnings("ignore", category=RuntimeWarning) +warnings.filterwarnings("ignore", category=UserWarning) + +# Some basic setup: +# Setup detectron2 logger +from detectron2.utils.logger import setup_logger +setup_logger() + +import gc +import os +import time + +import detectron2.utils.comm as comm + +# import some common libraries +import numpy as np +import torch + +# import some common detectron2 utilities +from detectron2.config import LazyConfig, get_cfg +from detectron2.engine import launch + +from deepdisc.data_format.augment_image import train_augs +from deepdisc.data_format.image_readers import DC2ImageReader +from deepdisc.data_format.register_data import register_data_set +from deepdisc.model.loaders import DictMapper, return_test_loader, return_train_loader +from deepdisc.model.models import return_lazy_model +from deepdisc.training.trainers import ( + return_evallosshook, + return_lazy_trainer, + return_optimizer, + return_savehook, + return_schedulerhook, +) +from deepdisc.utils.parse_arguments import make_training_arg_parser + + +def main(train_head, args): + # Hack if you get SSL certificate error + import ssl + ssl._create_default_https_context = ssl._create_unverified_context + + # Handle args + output_dir = args.output_dir + output_name = args.run_name + dirpath = args.data_dir # Path to dataset + scheme = args.scheme + alphas = args.alphas + modname = args.modname + datatype = args.dtype + if datatype == 8: + dtype = np.uint8 + elif datatype == 16: + dtype = np.int16 + + # Get file locations + trainfile = dirpath + "single_test.json" + testfile = dirpath + "single_test.json" + if modname == "swin": + cfgfile = "./tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_swin_b_in21k_50ep_DC2.py" + elif modname == "mvitv2": + cfgfile = "./tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_mvitv2_b_in21k_100ep_DC2.py" + # Vitdet not currently available (cuda issues) so we're tabling it for now + #elif modname == "vitdet": + # cfgfile = "/home/shared/hsc/detectron2/projects/ViTDet/configs/COCO/mask_rcnn_vitdet_b_100ep.py" + + # Load the config + cfg = LazyConfig.load(cfgfile) + + # Register the data sets + astrotrain_metadata = register_data_set( + cfg.DATASETS.TRAIN, trainfile, thing_classes=cfg.metadata.classes + ) + astroval_metadata = register_data_set( + cfg.DATASETS.TEST, testfile, thing_classes=cfg.metadata.classes + ) + + # Set the output directory + cfg.OUTPUT_DIR = output_dir + os.makedirs(cfg.OUTPUT_DIR, exist_ok=True) + + # Iterations for 15, 25, 35, 50 epochs + # TODOLIV could this stuff be moved to a config too? + epoch = int(args.tl / cfg.dataloader.train.total_batch_size) + e1 = 20 + e2 = epoch * 10 + e3 = epoch * 20 + efinal = epoch * 35 + + val_per = 5 + + if train_head: + cfg.train.init_checkpoint = None # or initwfile, the path to your model + + model = return_lazy_model(cfg) + + cfg.optimizer.params.model = model + cfg.optimizer.lr = 0.001 + + cfg.SOLVER.STEPS = [] # do not decay learning rate for retraining + cfg.SOLVER.LR_SCHEDULER_NAME = "WarmupMultiStepLR" + cfg.SOLVER.WARMUP_ITERS = 0 + cfg.SOLVER.MAX_ITER = e1 # for DefaultTrainer + + # optimizer = instantiate(cfg.optimizer) + optimizer = return_optimizer(cfg) + + def dc2_key_mapper(dataset_dict): + filename = dataset_dict["filename"] + return filename + + IR = DC2ImageReader(norm=args.norm) + mapper = DictMapper(IR, dc2_key_mapper, train_augs).map_data + loader = return_train_loader(cfg, mapper) + test_mapper = DictMapper(IR, dc2_key_mapper).map_data + test_loader = return_test_loader(cfg, test_mapper) + + saveHook = return_savehook(output_name) + lossHook = return_evallosshook(val_per, model, test_loader) + schedulerHook = return_schedulerhook(optimizer) + hookList = [lossHook, schedulerHook, saveHook] + + trainer = return_lazy_trainer(model, loader, optimizer, cfg, hookList) + + trainer.set_period(5) + trainer.train(0, 20) + if comm.is_main_process(): + np.save(output_dir + output_name + "_losses", trainer.lossList) + np.save(output_dir + output_name + "_val_losses", trainer.vallossList) + return + + +if __name__ == "__main__": + args = make_training_arg_parser().parse_args() + print("Command Line Args:", args) + + print("Training head layers") + train_head = True + t0 = time.time() + launch( + main, + args.num_gpus, + num_machines=args.num_machines, + machine_rank=args.machine_rank, + dist_url=args.dist_url, + args=( + train_head, + args, + ), + ) + + torch.cuda.empty_cache() + gc.collect() + + print(f"Took {time.time()-t0} seconds") + \ No newline at end of file diff --git a/solo_run_scripts/solo_test_run_transformers_DC2_redshift.py b/solo_run_scripts/solo_test_run_transformers_DC2_redshift.py new file mode 100644 index 0000000..ea83fca --- /dev/null +++ b/solo_run_scripts/solo_test_run_transformers_DC2_redshift.py @@ -0,0 +1,170 @@ +""" Training script for LazyConfig models. + +This uses the new "solo config" in which the previous yaml-style config +(a Detectron CfgNode type called cfg_loader) is now bundled into the +LazyConfig type cfg. +""" + +try: + # ignore ShapelyDeprecationWarning from fvcore + import warnings + from shapely.errors import ShapelyDeprecationWarning + warnings.filterwarnings("ignore", category=sShapelyDeprecationWarning) +except: + pass +warnings.filterwarnings("ignore", category=RuntimeWarning) +warnings.filterwarnings("ignore", category=UserWarning) + +# Some basic setup: +# Setup detectron2 logger +from detectron2.utils.logger import setup_logger +setup_logger() + +import gc +import os +import time + +import detectron2.utils.comm as comm + +# import some common libraries +import numpy as np +import torch + +# import some common detectron2 utilities +from detectron2.config import LazyConfig, get_cfg +from detectron2.engine import launch + +from deepdisc.data_format.augment_image import train_augs +from deepdisc.data_format.image_readers import DC2ImageReader +from deepdisc.data_format.register_data import register_data_set +from deepdisc.model.loaders import RedshiftDictMapper, return_test_loader, return_train_loader +from deepdisc.model.models import RedshiftPDFCasROIHeads, return_lazy_model +from deepdisc.training.trainers import ( + return_evallosshook, + return_lazy_trainer, + return_optimizer, + return_savehook, + return_schedulerhook, +) +from deepdisc.utils.parse_arguments import make_training_arg_parser + + +def main(train_head, args): + # Hack if you get SSL certificate error + import ssl + ssl._create_default_https_context = ssl._create_unverified_context + + # Handle args + output_dir = args.output_dir + output_name = args.run_name + dirpath = args.data_dir # Path to dataset + scheme = args.scheme + alphas = args.alphas + modname = args.modname + datatype = args.dtype + if datatype == 8: + dtype = np.uint8 + elif datatype == 16: + dtype = np.int16 + + # Get file locations + trainfile = dirpath + "single_test.json" + testfile = dirpath + "single_test.json" + if modname == "swin": + cfgfile = "./tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_swin_b_in21k_50ep_DC2.py" + elif modname == "mvitv2": + cfgfile = "./tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_mvitv2_b_in21k_100ep_DC2.py" + # Vitdet not currently available (cuda issues) so we're tabling it for now + #elif modname == "vitdet": + # cfgfile = "/home/shared/hsc/detectron2/projects/ViTDet/configs/COCO/mask_rcnn_vitdet_b_100ep.py" + + # Load the config + cfg = LazyConfig.load(cfgfile) + + # Register the data sets + astrotrain_metadata = register_data_set( + cfg.DATASETS.TRAIN, trainfile, thing_classes=cfg.metadata.classes + ) + astroval_metadata = register_data_set( + cfg.DATASETS.TEST, testfile, thing_classes=cfg.metadata.classes + ) + + # Set the output directory + cfg.OUTPUT_DIR = output_dir + os.makedirs(cfg.OUTPUT_DIR, exist_ok=True) + + # Iterations for 15, 25, 35, 50 epochs + # TODOLIV could this stuff be moved to a config too? + epoch = int(args.tl / cfg.dataloader.train.total_batch_size) + e1 = 20 + e2 = epoch * 10 + e3 = epoch * 20 + efinal = epoch * 35 + + val_per = 5 + + if train_head: + cfg.train.init_checkpoint = None # or initwfile, the path to your model + + model = return_lazy_model(cfg) + + cfg.optimizer.params.model = model + cfg.optimizer.lr = 0.001 + + cfg.SOLVER.STEPS = [] # do not decay learning rate for retraining + cfg.SOLVER.LR_SCHEDULER_NAME = "WarmupMultiStepLR" + cfg.SOLVER.WARMUP_ITERS = 0 + cfg.SOLVER.MAX_ITER = e1 # for DefaultTrainer + + # optimizer = instantiate(cfg.optimizer) + optimizer = return_optimizer(cfg) + + def dc2_key_mapper(dataset_dict): + filename = dataset_dict["filename"] + return filename + + IR = DC2ImageReader() + mapper = RedshiftDictMapper(IR, dc2_key_mapper, train_augs).map_data + loader = return_train_loader(cfg, mapper) + test_mapper = RedshiftDictMapper(IR, dc2_key_mapper).map_data + test_loader = return_test_loader(cfg, test_mapper) + + saveHook = return_savehook(output_name) + lossHook = return_evallosshook(val_per, model, test_loader) + schedulerHook = return_schedulerhook(optimizer) + hookList = [lossHook, schedulerHook, saveHook] + + trainer = return_lazy_trainer(model, loader, optimizer, cfg, hookList) + + trainer.set_period(5) + trainer.train(0, 20) + if comm.is_main_process(): + np.save(output_dir + output_name + "_losses", trainer.lossList) + np.save(output_dir + output_name + "_val_losses", trainer.vallossList) + return + + +if __name__ == "__main__": + args = make_training_arg_parser().parse_args() + print("Command Line Args:", args) + + print("Training head layers") + train_head = True + t0 = time.time() + launch( + main, + args.num_gpus, + num_machines=args.num_machines, + machine_rank=args.machine_rank, + dist_url=args.dist_url, + args=( + train_head, + args, + ), + ) + + torch.cuda.empty_cache() + gc.collect() + + print(f"Took {time.time()-t0} seconds") + diff --git a/src/deepdisc/astrodet/astrodet.py b/src/deepdisc/astrodet/astrodet.py index 7599635..734c7cd 100644 --- a/src/deepdisc/astrodet/astrodet.py +++ b/src/deepdisc/astrodet/astrodet.py @@ -138,7 +138,7 @@ class NewAstroTrainer(SimpleTrainer): The data loader that loads the training set optimizer: The learning optimizer - cfg: yacs file + cfg: config file The model config @@ -255,27 +255,19 @@ class AstroPredictor: inputs = cv2.imread("input.jpg") outputs = pred(inputs) """ - - def __init__(self, cfg, lazy=False, cfglazy=None): - if lazy: - self.cfg = cfg.clone() # cfg can be modified by model - self.cfglazy = cfglazy - self.model = instantiate(self.cfglazy.model) - self.model.to(self.cfglazy.train.device) - self.model = create_ddp_model(self.model) - self.model.eval() - checkpointer = DetectionCheckpointer(self.model, cfg.OUTPUT_DIR) - checkpointer.load(cfglazy.train.init_checkpoint) - else: - self.cfg = cfg.clone() # cfg can be modified by model - self.model = build_model(self.cfg) - self.model.eval() - if len(cfg.DATASETS.TEST): - self.metadata = MetadataCatalog.get(cfg.DATASETS.TEST[0]) - - checkpointer = DetectionCheckpointer(self.model) - checkpointer.load(cfg.MODEL.WEIGHTS) - + def __init__(self, cfg): + self.cfg = cfg.clone() # cfg can be modified by model + + self.model = instantiate(self.cfg.model) + self.model.to(self.cfg.train.device) + self.model = create_ddp_model(self.model) + self.model.eval() + if len(cfg.DATASETS.TEST): + self.metadata = MetadataCatalog.get(cfg.DATASETS.TEST[0]) + + checkpointer = DetectionCheckpointer(self.model, cfg.OUTPUT_DIR) + checkpointer.load(cfg.train.init_checkpoint) + self.aug = T.ResizeShortestEdge( [cfg.INPUT.MIN_SIZE_TEST, cfg.INPUT.MIN_SIZE_TEST], cfg.INPUT.MAX_SIZE_TEST ) diff --git a/src/deepdisc/inference/predictors.py b/src/deepdisc/inference/predictors.py index e144972..241d65b 100644 --- a/src/deepdisc/inference/predictors.py +++ b/src/deepdisc/inference/predictors.py @@ -1,25 +1,21 @@ import deepdisc.astrodet.astrodet as toolkit -def return_predictor_transformer(cfg, cfg_loader): - """ - This function returns a trained model and its config file. - Used for models with lazy config files. Also assumes a cascade roi head structure +def return_predictor_transformer(cfg): + """This function returns a trained model and its config file. + + Used for models with lazy config files. Also assumes a cascade roi head structure. Parameters ---------- cfg : .py file a LazyConfig - cfg_loader : .py file - a LazyConfig Returns ------- torch model """ - - predictor = toolkit.AstroPredictor(cfg_loader, lazy=True, cfglazy=cfg) - + predictor = toolkit.AstroPredictor(cfg) return predictor diff --git a/src/deepdisc/model/loaders.py b/src/deepdisc/model/loaders.py index 6d82252..aa6eee5 100644 --- a/src/deepdisc/model/loaders.py +++ b/src/deepdisc/model/loaders.py @@ -219,13 +219,13 @@ def map_data(self, row): } -def return_train_loader(cfg_loader, mapper): +def return_train_loader(cfg, mapper): """Returns a train loader Parameters ---------- - cfg_loader: .yml file - The config used for the data loaders + cfg : LazyConfig + The lazy config, which contains data loader config values **kwargs for the read_image functionality @@ -233,24 +233,23 @@ def return_train_loader(cfg_loader, mapper): ------- a train loader """ - loader = data.build_detection_train_loader(cfg_loader, mapper=mapper) + loader = data.build_detection_train_loader(cfg, mapper=mapper) return loader -def return_test_loader(cfg_loader, mapper): - """Returns a train loader +def return_test_loader(cfg, mapper): + """Returns a test loader Parameters ---------- - cfg_loader: .yml file - The config used for the data loaders + cfg : LazyConfig + The lazy config, which contains data loader config values **kwargs for the read_image functionality Returns ------- - a train loader + a test loader """ - # _train_mapper = mapper - loader = data.build_detection_test_loader(cfg_loader, cfg_loader.DATASETS.TEST, mapper=mapper) + loader = data.build_detection_test_loader(cfg, cfg.DATASETS.TEST, mapper=mapper) return loader diff --git a/src/deepdisc/training/trainers.py b/src/deepdisc/training/trainers.py index 0ef63a6..3afc647 100644 --- a/src/deepdisc/training/trainers.py +++ b/src/deepdisc/training/trainers.py @@ -13,16 +13,15 @@ class LazyAstroTrainer(SimpleTrainer): - def __init__(self, model, data_loader, optimizer, cfg, cfg_old): + def __init__(self, model, data_loader, optimizer, cfg): super().__init__(model, data_loader, optimizer) - # super().__init__(model, data_loader, optimizer) # Borrowed from DefaultTrainer constructor # see https://detectron2.readthedocs.io/en/latest/_modules/detectron2/engine/defaults.html#DefaultTrainer self.checkpointer = checkpointer.DetectionCheckpointer( # Assume you want to save checkpoints together with logs/statistics model, - cfg_old.OUTPUT_DIR, + cfg.OUTPUT_DIR, ) # load weights self.checkpointer.load(cfg.train.init_checkpoint) @@ -34,7 +33,7 @@ def __init__(self, model, data_loader, optimizer, cfg, cfg_old): self.period = 20 self.iterCount = 0 - self.scheduler = self.build_lr_scheduler(cfg_old, optimizer) + self.scheduler = self.build_lr_scheduler(cfg, optimizer) # self.scheduler = instantiate(cfg.lr_multiplier) self.valloss = 0 @@ -103,7 +102,7 @@ def add_val_loss(self, val_loss): self.vallossList.append(val_loss) -def return_lazy_trainer(model, loader, optimizer, cfg, cfg_loader, hooklist): +def return_lazy_trainer(model, loader, optimizer, cfg, hooklist): """Return a trainer for models built on LazyConfigs Parameters @@ -112,24 +111,20 @@ def return_lazy_trainer(model, loader, optimizer, cfg, cfg_loader, hooklist): pointer to file loader : detectron2 data loader - optimizer: detectron2 optimizer + optimizer : detectron2 optimizer cfg : .py file - The LazyConfig used to build the model + The LazyConfig used to build the model, and also stores config vals for data loaders - cfg_loader: .yml file - The config used for the data loaders - - hooklist: list + hooklist : list The list of hooks to use for the trainer Returns ------- trainer """ - trainer = LazyAstroTrainer(model, loader, optimizer, cfg, cfg_loader) + trainer = LazyAstroTrainer(model, loader, optimizer, cfg) trainer.register_hooks(hooklist) - return trainer diff --git a/tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_mvitv2_b_in21k_100ep.py b/tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_mvitv2_b_in21k_100ep.py new file mode 100644 index 0000000..1e5564e --- /dev/null +++ b/tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_mvitv2_b_in21k_100ep.py @@ -0,0 +1,66 @@ +"""This is a 'solo config' file using various baselines.""" + +from omegaconf import OmegaConf + +# ---------------------------------------------------------------------------- # +# Local variables and metadata +# ---------------------------------------------------------------------------- # +bs = 1 + +metadata = OmegaConf.create() +metadata.classes = ["star", "galaxy"] + +numclasses = len(metadata.classes) + +# ---------------------------------------------------------------------------- # +# Standard, Lazy-Config-style config values +# ---------------------------------------------------------------------------- # +# Baselines +from ..COCO.cascade_mask_rcnn_mvitv2_b_in21k_100ep import ( + constants, + dataloader, + lr_multiplier, + model, + optimizer, + train, +) + +# Overrides +model.proposal_generator.anchor_generator.sizes = [[8], [16], [32], [64], [128]] +dataloader.train.total_batch_size = bs +model.roi_heads.num_classes = numclasses +model.roi_heads.batch_size_per_image = 512 + +# ---------------------------------------------------------------------------- # +# Yacs-style config values +# ---------------------------------------------------------------------------- # +# Baselines +from .yacs_style_defaults import ( + MISC, + DATALOADER, + DATASETS, + GLOBAL, + INPUT, + MODEL, + SOLVER, + TEST, +) + +# Overrides +DATALOADER.PREFETCH_FACTOR = 2 + +DATASETS.TRAIN = "astro_train" +DATASETS.TEST = "astro_val" + +SOLVER.BASE_LR = 0.001 +SOLVER.CLIP_GRADIENTS.ENABLED = True +# Type of gradient clipping, currently 2 values are supported: +# - "value": the absolute values of elements of each gradients are clipped +# - "norm": the norm of the gradient for each parameter is clipped thus +# affecting all elements in the parameter +SOLVER.CLIP_GRADIENTS.CLIP_TYPE = "norm" +# Maximum absolute value used for clipping gradients +# Floating point number p for L-p norm to be used with the "norm" +# gradient clipping type; for L-inf, please specify .inf +SOLVER.CLIP_GRADIENTS.NORM_TYPE = 5.0 +SOLVER.IMS_PER_BATCH = bs diff --git a/tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_mvitv2_b_in21k_100ep_DC2.py b/tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_mvitv2_b_in21k_100ep_DC2.py new file mode 100644 index 0000000..b0fd684 --- /dev/null +++ b/tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_mvitv2_b_in21k_100ep_DC2.py @@ -0,0 +1,79 @@ +"""This is a 'solo config' file using various baselines.""" + + +from omegaconf import OmegaConf + +# ---------------------------------------------------------------------------- # +# Local variables and metadata +# ---------------------------------------------------------------------------- # +bs = 1 + +metadata = OmegaConf.create() +metadata.classes = ["object"] + +numclasses = len(metadata.classes) + +# ---------------------------------------------------------------------------- # +# Standard, Lazy-Config-style config values +# ---------------------------------------------------------------------------- # +# Baselines +from ..COCO.cascade_mask_rcnn_mvitv2_b_in21k_100ep import ( + constants, + dataloader, + lr_multiplier, + model, + optimizer, + train, +) + +# Overrides +model.proposal_generator.anchor_generator.sizes = [[8], [16], [32], [64], [128]] +dataloader.train.total_batch_size = bs +model.roi_heads.num_classes = numclasses +model.roi_heads.batch_size_per_image = 512 + +# DC2 overrides +model.backbone.bottom_up.in_chans = 6 +model.pixel_mean = [ + 0.05381286, + 0.04986344, + 0.07526361, + 0.10420945, + 0.14229655, + 0.21245764, +] +model.pixel_std = [2.9318833, 1.8443471, 2.581817, 3.5950038, 4.5809164, 7.302009] + +# ---------------------------------------------------------------------------- # +# Yacs-style config values +# ---------------------------------------------------------------------------- # +# Baselines +from .yacs_style_defaults import ( + MISC, + DATALOADER, + DATASETS, + GLOBAL, + INPUT, + MODEL, + SOLVER, + TEST, +) + +# Overrides +DATALOADER.PREFETCH_FACTOR = 2 + +DATASETS.TRAIN = "astro_train" +DATASETS.TEST = "astro_val" + +SOLVER.BASE_LR = 0.001 +SOLVER.CLIP_GRADIENTS.ENABLED = True +# Type of gradient clipping, currently 2 values are supported: +# - "value": the absolute values of elements of each gradients are clipped +# - "norm": the norm of the gradient for each parameter is clipped thus +# affecting all elements in the parameter +SOLVER.CLIP_GRADIENTS.CLIP_TYPE = "norm" +# Maximum absolute value used for clipping gradients +# Floating point number p for L-p norm to be used with the "norm" +# gradient clipping type; for L-inf, please specify .inf +SOLVER.CLIP_GRADIENTS.NORM_TYPE = 5.0 +SOLVER.IMS_PER_BATCH = bs diff --git a/tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_swin_b_in21k_50ep.py b/tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_swin_b_in21k_50ep.py index 6ee954a..c7b4b01 100644 --- a/tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_swin_b_in21k_50ep.py +++ b/tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_swin_b_in21k_50ep.py @@ -1,12 +1,5 @@ -""" This is a demo "solo config" file for use in solo_test_run_transformers.py. +"""This is a 'solo config' file using various baselines.""" -This uses template configs cascade_mask_rcnn_swin_b_in21k_50ep and yaml_style_defaults.""" - -from detectron2 import model_zoo -from detectron2.config import LazyCall as L -from detectron2.solver import WarmupParamScheduler -from detectron2.modeling import SwinTransformer -from fvcore.common.param_scheduler import MultiStepParamScheduler from omegaconf import OmegaConf # ---------------------------------------------------------------------------- # @@ -14,17 +7,22 @@ # ---------------------------------------------------------------------------- # bs = 1 -metadata = OmegaConf.create() +metadata = OmegaConf.create() metadata.classes = ["star", "galaxy"] numclasses = len(metadata.classes) # ---------------------------------------------------------------------------- # -# Standard config (this has always been the LazyConfig/.py-style config) +# Standard, Lazy-Config-style config values # ---------------------------------------------------------------------------- # -# Get values from templates -from ..common.coco_loader_lsj import dataloader -from ..COCO.cascade_mask_rcnn_swin_b_in21k_50ep import dataloader, model, train, lr_multiplier, optimizer +# Baselines +from ..COCO.cascade_mask_rcnn_swin_b_in21k_50ep import ( + dataloader, + lr_multiplier, + model, + optimizer, + train, +) # Overrides model.proposal_generator.anchor_generator.sizes = [[8], [16], [32], [64], [128]] @@ -33,10 +31,19 @@ model.roi_heads.batch_size_per_image = 512 # ---------------------------------------------------------------------------- # -# Yaml-style config (was formerly saved as a .yaml file, loaded to cfg_loader) +# Yacs-style config values # ---------------------------------------------------------------------------- # -# Get values from template -from .yaml_style_defaults import MISC, DATALOADER, DATASETS, GLOBAL, INPUT, MODEL, SOLVER, TEST +# Baselines +from .yacs_style_defaults import ( + MISC, + DATALOADER, + DATASETS, + GLOBAL, + INPUT, + MODEL, + SOLVER, + TEST, +) # Overrides DATALOADER.PREFETCH_FACTOR = 2 diff --git a/tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_swin_b_in21k_50ep_DC2.py b/tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_swin_b_in21k_50ep_DC2.py new file mode 100644 index 0000000..fcf808f --- /dev/null +++ b/tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_swin_b_in21k_50ep_DC2.py @@ -0,0 +1,77 @@ +"""This is a 'solo config' file using various baselines.""" + +from omegaconf import OmegaConf + +# ---------------------------------------------------------------------------- # +# Local variables and metadata +# ---------------------------------------------------------------------------- # +bs = 1 + +metadata = OmegaConf.create() +metadata.classes = ["object"] + +numclasses = len(metadata.classes) + +# ---------------------------------------------------------------------------- # +# Standard, Lazy-Config-style config values +# ---------------------------------------------------------------------------- # +# Baselines +from ..COCO.cascade_mask_rcnn_swin_b_in21k_50ep import ( + dataloader, + lr_multiplier, + model, + optimizer, + train, +) + +# Overrides +model.proposal_generator.anchor_generator.sizes = [[8], [16], [32], [64], [128]] +dataloader.train.total_batch_size = bs +model.roi_heads.num_classes = numclasses +model.roi_heads.batch_size_per_image = 512 + +# DC2 overrides +model.backbone.bottom_up.in_chans = 6 +model.pixel_mean = [ + 0.05381286, + 0.04986344, + 0.07526361, + 0.10420945, + 0.14229655, + 0.21245764, +] +model.pixel_std = [2.9318833, 1.8443471, 2.581817, 3.5950038, 4.5809164, 7.302009] + +# ---------------------------------------------------------------------------- # +# Yacs-style config values +# ---------------------------------------------------------------------------- # +# Baselines +from .yacs_style_defaults import ( + MISC, + DATALOADER, + DATASETS, + GLOBAL, + INPUT, + MODEL, + SOLVER, + TEST, +) + +# Overrides +DATALOADER.PREFETCH_FACTOR = 2 + +DATASETS.TRAIN = "astro_train" +DATASETS.TEST = "astro_val" + +SOLVER.BASE_LR = 0.001 +SOLVER.CLIP_GRADIENTS.ENABLED = True +# Type of gradient clipping, currently 2 values are supported: +# - "value": the absolute values of elements of each gradients are clipped +# - "norm": the norm of the gradient for each parameter is clipped thus +# affecting all elements in the parameter +SOLVER.CLIP_GRADIENTS.CLIP_TYPE = "norm" +# Maximum absolute value used for clipping gradients +# Floating point number p for L-p norm to be used with the "norm" +# gradient clipping type; for L-inf, please specify .inf +SOLVER.CLIP_GRADIENTS.NORM_TYPE = 5.0 +SOLVER.IMS_PER_BATCH = bs diff --git a/tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_swin_b_in21k_50ep_test_eval.py b/tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_swin_b_in21k_50ep_test_eval.py new file mode 100644 index 0000000..4c491e6 --- /dev/null +++ b/tests/deepdisc/test_data/configs/solo/solo_cascade_mask_rcnn_swin_b_in21k_50ep_test_eval.py @@ -0,0 +1,60 @@ +"""This is a 'solo config' file using various baselines.""" + +from omegaconf import OmegaConf + +# ---------------------------------------------------------------------------- # +# Local variables and metadata +# ---------------------------------------------------------------------------- # + +classes = ["star", "galaxy"] + +# ---------------------------------------------------------------------------- # +# Standard, Lazy-Config-style config values +# ---------------------------------------------------------------------------- # +# Baselines +from ..COCO.cascade_mask_rcnn_swin_b_in21k_50ep import ( + dataloader, + lr_multiplier, + model, + optimizer, + train, +) + +# Overrides +model.proposal_generator.anchor_generator.sizes = [[8], [16], [32], [64], [128]] +dataloader.train.total_batch_size = 4 +model.roi_heads.num_classes = len( + classes +) # args.nc ##TODO assuming nc can be replaced with the number of classes we declared above +model.roi_heads.batch_size_per_image = 512 + + +model.proposal_generator.pre_nms_topk = [6000, 6000] +model.proposal_generator.post_nms_topk = [6000, 6000] +model.proposal_generator.nms_thresh = 0.3 + +# ---------------------------------------------------------------------------- # +# Yacs-style config values +# ---------------------------------------------------------------------------- # +# Baselines +from .yacs_style_defaults import ( + MISC, + DATALOADER, + DATASETS, + GLOBAL, + INPUT, + MODEL, + SOLVER, + TEST, +) + +# Overrides +DATALOADER.NUM_WORKERS = 1 + +DATASETS.TRAIN = "astro_train" # Register Metadata +DATASETS.TEST = "astro_val" + +SOLVER.BASE_LR = 0.001 +SOLVER.IMS_PER_BATCH = 4 + +TEST.DETECTIONS_PER_IMAGE = 1000 diff --git a/tests/deepdisc/test_data/configs/solo/solo_test_eval_model_option.py b/tests/deepdisc/test_data/configs/solo/solo_test_eval_model_option.py new file mode 100644 index 0000000..a74098a --- /dev/null +++ b/tests/deepdisc/test_data/configs/solo/solo_test_eval_model_option.py @@ -0,0 +1,71 @@ +"""This is a 'solo config' file using various baselines.""" + +from omegaconf import OmegaConf + +# ---------------------------------------------------------------------------- # +# Local variables and metadata +# ---------------------------------------------------------------------------- # + +# ---------------------------------------------------------------------------- # +# Standard, Lazy-Config-style config values +# ---------------------------------------------------------------------------- # +# Baselines +from ..solo.solo_cascade_mask_rcnn_swin_b_in21k_50ep_test_eval import ( + dataloader, + lr_multiplier, + model, + optimizer, + train, +) + +# ---------------------------------------------------------------------------- # +# Yacs-style config values +# ---------------------------------------------------------------------------- # +# Baselines +from .yacs_style_defaults import ( + MISC, + DATALOADER, + DATASETS, + GLOBAL, + INPUT, + MODEL, + SOLVER, + TEST, +) + +# Overrides +DATASETS.TRAIN = "astro_train" # Register Metadata +DATASETS.TEST = ( + "astro_test", +) # Config calls this TEST, but it should be the val dataset +DATALOADER.NUM_WORKERS = 1 +SOLVER.IMS_PER_BATCH = 4 # this is images per iteration. 1 epoch is len(images)/(ims_per_batch iterations*num_gpus) +SOLVER.BASE_LR = 0.001 +SOLVER.STEPS = [] # do not decay learning rate for retraining +SOLVER.MAX_ITER = 100 # for DefaultTrainer +MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = ( + 512 # faster, and good enough for this toy dataset (default: 512) +) +# MODEL.ROI_HEADS.NUM_CLASSES = nc +# OUTPUT_DIR = output_dir +TEST.DETECTIONS_PER_IMAGE = 1000 +INPUT.MIN_SIZE_TRAIN = 1025 +INPUT.MAX_SIZE_TRAIN = 1050 + +# Defaults +# PRE_NMS_TOPK_TEST: 6000git st +# POST_NMS_TOPK_TEST: 1000 +# PRE_NMS_TOPK_TRAIN: 12000 +# POST_NMS_TOPK_TRAIN: 2000 + +MODEL.RPN.POST_NMS_TOPK_TEST = 6000 +MODEL.RPN.PRE_NMS_TOPK_TEST = 6000 + +MODEL.RPN.BATCH_SIZE_PER_IMAGE = 512 +MODEL.ANCHOR_GENERATOR.SIZES = [[8, 16, 32, 64, 128]] + +# MODEL.WEIGHTS = os.path.join(cfg.OUTPUT_DIR, run_name) # path to the model we just trained +# MODEL.ROI_HEADS.SCORE_THRESH_TEST = roi_thresh # set a custom testing threshold +MODEL.ROI_HEADS.NMS_THRESH_TEST = 0.3 +MODEL.ROI_BOX_HEAD.GAMMA = 1 +MODEL.ROI_BOX_HEAD.ALPHAS = None diff --git a/tests/deepdisc/test_data/configs/solo/yaml_style_defaults.py b/tests/deepdisc/test_data/configs/solo/yacs_style_defaults.py similarity index 99% rename from tests/deepdisc/test_data/configs/solo/yaml_style_defaults.py rename to tests/deepdisc/test_data/configs/solo/yacs_style_defaults.py index 77f0797..a677b53 100644 --- a/tests/deepdisc/test_data/configs/solo/yaml_style_defaults.py +++ b/tests/deepdisc/test_data/configs/solo/yacs_style_defaults.py @@ -2,7 +2,7 @@ LazyConfig-style config. This may be used as a base config in any other LazyConfig-style file, just import: -from .data_loader_defaults import MISC, DATALOADER, DATASETS, GLOBAL, INPUT, MODEL, SOLVER, TEST +from .yacs_style_defaults import MISC, DATALOADER, DATASETS, GLOBAL, INPUT, MODEL, SOLVER, TEST Values are as defined in detectron2/config/defaults.py, which can be found at: https://github.com/facebookresearch/detectron2/blob/main/detectron2/config/defaults.py