From 026543305b0e93d10b7bbc6ae690ac923dfbe660 Mon Sep 17 00:00:00 2001 From: Arzamazov Nikita Date: Mon, 4 Apr 2022 22:17:41 +0000 Subject: [PATCH 1/4] v0.23.0 updates 1 --- .gitignore | 12 +- models/model_meta.json | 36 ++++-- serve/src/gui.html | 15 --- serve/src/sly_serve.py | 14 +-- serve/src/utils.py | 9 +- train/src/init_cfg.py | 29 +++-- train/src/init_default_cfg.py | 171 ++++++++++++++++++++++++++ train/src/sly_globals.py | 36 +++--- train/src/ui/architectures.html | 13 -- train/src/ui/architectures.py | 196 ++---------------------------- train/src/ui/hyperparameters.html | 6 +- train/src/ui/hyperparameters.py | 1 + train/src/ui/monitoring.html | 2 - train/src/ui/monitoring.py | 41 +++---- train/src/ui/splits.py | 5 +- train/src/ui/ui.py | 3 + 16 files changed, 288 insertions(+), 301 deletions(-) create mode 100644 train/src/init_default_cfg.py diff --git a/.gitignore b/.gitignore index 7345fe9..92e11d4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,17 @@ +configs +data +.idea +cache +.vscode + train/secret_debug.env serve/secret_debug.env -configs serve/.DS_Store train/.DS_Store train/src/.DS_Store .DS_Store -.idea/ \ No newline at end of file + +serve/src/__pycache__ +train/src/__pycache__ +train/src/ui/__pycache__ \ No newline at end of file diff --git a/models/model_meta.json b/models/model_meta.json index c93b1bf..07650ad 100644 --- a/models/model_meta.json +++ b/models/model_meta.json @@ -1,6 +1,24 @@ [ { - "model_name" : "SegFormer", + "model_name" : "BEiT", + "yml_file" : "beit/beit.yml", + "paper_from": "ICLR", + "year": 2022 + }, + { + "model_name" : "ConvNeXt", + "yml_file" : "convnext/convnext.yml", + "paper_from": "CVPR", + "year": 2022 + }, + { + "model_name" : "KNet", + "yml_file" : "knet/knet.yml", + "paper_from": "NeurIPS", + "year": 2021 + }, + { + "model_name" : "Segformer", "yml_file" : "segformer/segformer.yml", "paper_from": "NeurIPS", "year": 2021 @@ -90,7 +108,7 @@ "year": 2019 }, { - "model_name" : "Fast-SCNN", + "model_name" : "FastSCNN", "yml_file" : "fastscnn/fastscnn.yml", "paper_from": "ArXiv", "year": 2019 @@ -168,7 +186,7 @@ "year": 2018 }, { - "model_name" : "Non-local Net", + "model_name" : "NonLocalNet", "yml_file" : "nonlocal_net/nonlocal_net.yml", "paper_from": "CVPR", "year": 2018 @@ -221,18 +239,18 @@ "paper_from": "CVPR", "year": 2017 }, - { - "model_name" : "UNet", - "yml_file" : "unet/unet.yml", - "paper_from": "MICCAI", - "year": 2016 - }, { "model_name" : "ERFNet", "yml_file" : "erfnet/erfnet.yml", "paper_from": "T-ITS", "year": 2017 }, + { + "model_name" : "UNet", + "yml_file" : "unet/unet.yml", + "paper_from": "MICCAI", + "year": 2016 + }, { "model_name" : "FCN", "yml_file" : "fcn/fcn.yml", diff --git a/serve/src/gui.html b/serve/src/gui.html index 98dae86..a6f8380 100644 --- a/serve/src/gui.html +++ b/serve/src/gui.html @@ -48,24 +48,9 @@ Learn more... -
Pretrained model:
- diff --git a/serve/src/sly_serve.py b/serve/src/sly_serve.py index 88505e2..c0ce5b4 100644 --- a/serve/src/sly_serve.py +++ b/serve/src/sly_serve.py @@ -119,7 +119,7 @@ def init_model(api: sly.Api, task_id, context, state, app_logger): def init_state_and_data(data, state): - state['pretrainedModel'] = 'SegFormer' + state['pretrainedModel'] = 'Segformer' data["pretrainedModels"], metrics = utils.get_pretrained_models(return_metrics=True) model_select_info = [] for model_name, params in data["pretrainedModels"].items(): @@ -139,18 +139,6 @@ def init_state_and_data(data, state): state["weightsPath"] = "" state["loading"] = False state["deployed"] = False - ''' - data["github_icon"] = { - "imageUrl": "https://github.githubassets.com/favicons/favicon.png", - "rounded": False, - "bgColor": "rgba(0,0,0,0)" - } - data["arxiv_icon"] = { - "imageUrl": "https://static.arxiv.org/static/browse/0.3.2.8/images/icons/favicon.ico", - "rounded": False, - "bgColor": "rgba(0,0,0,0)" - } - ''' def main(): diff --git a/serve/src/utils.py b/serve/src/utils.py index 3ef6ee7..99e1ea0 100644 --- a/serve/src/utils.py +++ b/serve/src/utils.py @@ -49,9 +49,6 @@ def get_pretrained_models(return_metrics=False): with open(os.path.join(g.configs_dir, model_meta["yml_file"]), "r") as stream: model_info = yaml.safe_load(stream) model_config[model_meta["model_name"]] = {} - # model_config[model_meta["model_name"]]["code_url"] = model_info["Collections"][0]["Code"]["URL"] - # model_config[model_meta["model_name"]]["paper_title"] = model_info["Collections"][0]["Paper"]["Title"] - # model_config[model_meta["model_name"]]["paper_url"] = model_info["Collections"][0]["Paper"]["URL"] model_config[model_meta["model_name"]]["checkpoints"] = [] model_config[model_meta["model_name"]]["paper_from"] = model_meta["paper_from"] model_config[model_meta["model_name"]]["year"] = model_meta["year"] @@ -64,6 +61,7 @@ def get_pretrained_models(return_metrics=False): for model in model_info["Models"]: checkpoint_info = {} checkpoint_info["name"] = model["Name"] + checkpoint_info["method"] = model["In Collection"] checkpoint_info["backbone"] = model["Metadata"]["backbone"] try: checkpoint_info["inference_time"] = model["Metadata"]["inference time (ms/im)"][0]["value"] @@ -95,14 +93,15 @@ def get_table_columns(metrics): columns = [ {"key": "name", "title": " ", "subtitle": None}, {"key": "backbone", "title": "Backbone", "subtitle": None}, + {"key": "method", "title": "Method", "subtitle": None}, {"key": "dataset", "title": "Dataset", "subtitle": None}, {"key": "inference_time", "title": "Inference time", "subtitle": "(ms/im)"}, {"key": "crop_size", "title": "Input size", "subtitle": "(H, W)"}, {"key": "lr_schd", "title": "LR scheduler", "subtitle": "steps"}, - {"key": "training_memory", "title": "Training memory", "subtitle": "GB"}, + {"key": "training_memory", "title": "Memory", "subtitle": "Training (GB)"}, ] for metric in metrics: - columns.append({"key": metric, "title": f"{metric} score", "subtitle": None}) + columns.append({"key": metric, "title": metric, "subtitle": "score"}) return columns diff --git a/train/src/init_cfg.py b/train/src/init_cfg.py index 836b440..ac2228c 100644 --- a/train/src/init_cfg.py +++ b/train/src/init_cfg.py @@ -1,5 +1,6 @@ import architectures import augs +import splits import os import sly_globals as g from mmcv import ConfigDict @@ -127,12 +128,11 @@ def init_cfg_splits(cfg, img_dir, ann_dir, classes, palette): cfg.data.train.img_dir = img_dir cfg.data.train.ann_dir = ann_dir cfg.data.train.pipeline = cfg.train_pipeline - cfg.data.train.split = 'splits/train.txt' + cfg.data.train.split = splits.train_set_path cfg.data.train.classes = classes cfg.data.train.palette = palette cfg.data.train.img_suffix = '' cfg.data.train.seg_map_suffix = '.png' - # cfg.data.train.ignore_index = ignore_index if hasattr(cfg.data.train, "times"): delattr(cfg.data.train, "times") if hasattr(cfg.data.train, "dataset"): @@ -143,12 +143,11 @@ def init_cfg_splits(cfg, img_dir, ann_dir, classes, palette): cfg.data.val.img_dir = img_dir cfg.data.val.ann_dir = ann_dir cfg.data.val.pipeline = cfg.val_pipeline - cfg.data.val.split = 'splits/val.txt' + cfg.data.val.split = splits.val_set_path cfg.data.val.classes = classes cfg.data.val.palette = palette cfg.data.val.img_suffix = '' cfg.data.val.seg_map_suffix = '.png' - # cfg.data.val.ignore_index = ignore_index cfg.data.test.type = cfg.dataset_type cfg.data.test.data_root = cfg.data_root @@ -160,7 +159,6 @@ def init_cfg_splits(cfg, img_dir, ann_dir, classes, palette): cfg.data.test.palette = palette cfg.data.test.img_suffix = '' cfg.data.test.seg_map_suffix = '.png' - # cfg.data.test.ignore_index = ignore_index def init_cfg_training(cfg, state): @@ -221,7 +219,9 @@ def init_cfg_lr(cfg, state): warmup_ratio=state["warmupRatio"] ) if state["lrPolicy"] == "Step": - lr_config["lr_step"] = [int(step) for step in state["lr_step"].split(",")] + steps = [int(step) for step in state["lr_step"].split(",")] + assert len(steps) + lr_config["step"] = steps lr_config["gamma"] = state["gamma"] lr_config["min_lr"] = state["minLR"] elif state["lrPolicy"] == "Exp": @@ -265,21 +265,28 @@ def init_cfg(state, img_dir, ann_dir, classes, palette): # Since we use ony one GPU, BN is used instead of SyncBN cfg.norm_cfg = dict(type='BN', requires_grad=True) - if cfg.pretrained_model not in ["DPT", "SegFormer", "SETR", "Swin Transformer", "Twins", "ViT"]: + if cfg.pretrained_model not in ["DPT", "Segformer", "SETR", "Swin Transformer", "Twins", "ViT"]: cfg.model.backbone.norm_cfg = cfg.norm_cfg class_weights = init_class_weights(state, classes) + if hasattr(cfg.model.backbone, "pretrained"): + delattr(cfg.model.backbone, "pretrained") + if isinstance(cfg.model.decode_head, list): for i in range(len(cfg.model.decode_head)): head = init_cfg_decode_head(cfg, state, classes, class_weights, ind=i) for key in head: cfg.model.decode_head[i][key] = head[key] else: - head = init_cfg_decode_head(cfg, state, classes, class_weights) - for key in head: - cfg.model.decode_head[key] = head[key] + if cfg.pretrained_model == "KNet": + for i in range(len(cfg.model.decode_head.kernel_update_head)): + cfg.model.decode_head.kernel_update_head[i].num_classes = len(classes) + cfg.model.decode_head.kernel_generate_head.num_classes = len(classes) + else: + head = init_cfg_decode_head(cfg, state, classes, class_weights) + for key in head: + cfg.model.decode_head[key] = head[key] - init_cfg_decode_head(cfg, state, classes, class_weights) if state["useAuxiliaryHead"]: if isinstance(cfg.model.auxiliary_head, list): for i in range(len(cfg.model.auxiliary_head)): diff --git a/train/src/init_default_cfg.py b/train/src/init_default_cfg.py new file mode 100644 index 0000000..3f009d2 --- /dev/null +++ b/train/src/init_default_cfg.py @@ -0,0 +1,171 @@ +import sly_globals as g + +def init_default_cfg_params(state): + state["optimizer"] = "SGD" + state["lr"] = 0.001 + state["weightDecay"] = 0 + state["decodeHeadLoss"] = "CrossEntropyLoss" + state["auxiliaryHeadLoss"] = "CrossEntropyLoss" + state["decodeHeadLossWeight"] = 1.0 + state["auxiliaryHeadLossWeight"] = 0.4 + state["lrPolicy"] = "Cyclic" + state["useWarmup"] = False + state["warmup"] = "constant" + state["warmupIters"] = 0 + state["warmupRatio"] = 0.1 + state["schedulerByEpochs"] = False + state["minLREnabled"] = False + state["minLR"] = None + state["minLRRatio"] = None + state["power"] = 1 + state["momentum"] = 0.9 + state["beta1"] = 0.9 + state["beta2"] = 0.999 + state["input_size"] = { + "value": { + "width": 256, + "height": 256, + "proportional": False + }, + "options": { + "proportions": { + "width": 100, + "height": 100 + }, + "min": 64 + } + } + state["batchSizePerGPU"] = 4 + state["workersPerGPU"] = 2 + + +def init_default_cfg_args(cfg): + params = [] + if hasattr(cfg.model, "decode_head") and cfg.model.decode_head is not None: + decode_is_list = isinstance(cfg.model.decode_head, list) + if decode_is_list and hasattr(cfg.model.decode_head[0], "loss_decode") or not decode_is_list and hasattr(cfg.model.decode_head, "loss_decode"): + params.extend([ + { + "field": "state.decodeHeadLoss", + "payload": cfg.model.decode_head[0].loss_decode.type if decode_is_list else cfg.model.decode_head.loss_decode.type + }, + { + "field": "state.decodeHeadLossWeight", + "payload": cfg.model.decode_head[0].loss_decode.loss_weight if decode_is_list else cfg.model.decode_head.loss_decode.loss_weight + }, + ]) + if hasattr(cfg.model, "auxiliary_head") and cfg.model.auxiliary_head is not None: + params.extend([ + { + "field": "state.auxiliaryHeadLoss", + "payload": cfg.model.auxiliary_head[0].loss_decode.type if isinstance(cfg.model.auxiliary_head, + list) else cfg.model.auxiliary_head.loss_decode.type + }, + { + "field": "state.auxiliaryHeadLossWeight", + "payload": cfg.model.auxiliary_head[0].loss_decode.loss_weight if isinstance(cfg.model.auxiliary_head, list) else cfg.model.auxiliary_head.loss_decode.loss_weight + } + ]) + if hasattr(cfg.data, "samples_per_gpu"): + params.extend([{ + "field": "state.batchSizePerGPU", + "payload": cfg.data.samples_per_gpu + }]) + if hasattr(cfg.data, "workers_per_gpu"): + params.extend([{ + "field": "state.workersPerGPU", + "payload": cfg.data.workers_per_gpu + }]) + if hasattr(cfg, "crop_size"): + params.extend([{ + "field": "state.input_size.value.height", + "payload": cfg.crop_size[0] + },{ + "field": "state.input_size.value.width", + "payload": cfg.crop_size[1] + },{ + "field": "state.input_size.options.proportions.height", + "payload": 100 + },{ + "field": "state.input_size.options.proportions.width", + "payload": 100 * (cfg.crop_size[1] / cfg.crop_size[0]) + }]) + if hasattr(cfg.optimizer, "type"): + params.extend([{ + "field": "state.optimizer", + "payload": cfg.optimizer.type + }]) + if hasattr(cfg.optimizer, "lr"): + params.extend([{ + "field": "state.lr", + "payload": cfg.optimizer.lr + }]) + if hasattr(cfg.optimizer, "weight_decay"): + params.extend([{ + "field": "state.weightDecay", + "payload": cfg.optimizer.weight_decay + }]) + if hasattr(cfg.optimizer, "momentum"): + params.extend([{ + "field": "state.momentum", + "payload": cfg.optimizer.momentum + }]) + if hasattr(cfg.optimizer, "betas"): + params.extend([{ + "field": "state.beta1", + "payload": cfg.optimizer.betas[0] + },{ + "field": "state.beta2", + "payload": cfg.optimizer.betas[1] + }]) + # take lr scheduler params + if hasattr(cfg, "lr_config"): + if hasattr(cfg.lr_config, "policy"): + policy = cfg.lr_config.policy.capitalize() + params.extend([{ + "field": "state.lrPolicy", + "payload": "Cyclic" + }]) + if hasattr(cfg.lr_config, "warmup"): + warmup = cfg.lr_config.warmup + params.extend([{ + "field": "state.useWarmup", + "payload": warmup is not None + },{ + "field": "state.warmup", + "payload": warmup + }]) + if hasattr(cfg.lr_config, "warmup_iters"): + warmup_iters = cfg.lr_config.warmup_iters + # warmup iters no more than half of all data length + if warmup_iters > g.project_info.items_count * 0.5 // cfg.data.samples_per_gpu: + warmup_iters = g.project_info.items_count * 0.5 // cfg.data.samples_per_gpu + params.extend([{ + "field": "state.warmupIters", + "payload": warmup_iters + }]) + if hasattr(cfg.lr_config, "warmup_ratio"): + params.extend([{ + "field": "state.warmupRatio", + "payload": cfg.lr_config.warmup_ratio + }]) + if hasattr(cfg.lr_config, "by_epoch"): + params.extend([{ + "field": "state.schedulerByEpochs", + "payload": cfg.lr_config.by_epoch + }]) + if hasattr(cfg.lr_config, "min_lr"): + params.extend([{ + "field": "state.minLREnabled", + "payload": True + },{ + "field": "state.minLR", + "payload": cfg.lr_config.min_lr + }]) + if hasattr(cfg.lr_config, "power"): + params.extend([{ + "field": "state.power", + "payload": cfg.lr_config.power + }]) + + return params \ No newline at end of file diff --git a/train/src/sly_globals.py b/train/src/sly_globals.py index d831ce3..b6ca41c 100644 --- a/train/src/sly_globals.py +++ b/train/src/sly_globals.py @@ -6,6 +6,25 @@ import shutil import pkg_resources +from dotenv import load_dotenv + +root_source_dir = str(Path(sys.argv[0]).parents[2]) +sly.logger.info(f"Root source directory: {root_source_dir}") +sys.path.append(root_source_dir) +source_path = str(Path(sys.argv[0]).parents[0]) +sly.logger.info(f"App source directory: {source_path}") +sys.path.append(source_path) +ui_sources_dir = os.path.join(source_path, "ui") +sly.logger.info(f"UI source directory: {ui_sources_dir}") +sys.path.append(ui_sources_dir) +sly.logger.info(f"Added to sys.path: {ui_sources_dir}") + +debug_env_path = os.path.join(root_source_dir, "train", "debug.env") +secret_debug_env_path = os.path.join(root_source_dir, "train", "secret_debug.env") +# @TODO: for debug +# load_dotenv(debug_env_path) +# load_dotenv(secret_debug_env_path, override=True) + my_app = AppService() api = my_app.public_api task_id = my_app.task_id @@ -15,10 +34,8 @@ project_id = int(os.environ['modal.state.slyProjectId']) project_info = api.project.get_info_by_id(project_id) -if project_info is None: # for debug - raise ValueError(f"Project with id={project_id} not found") -sly.fs.clean_dir(my_app.data_dir) # @TODO: for debug +# sly.fs.clean_dir(my_app.data_dir) # @TODO: for debug project_dir = os.path.join(my_app.data_dir, "sly_project") project_seg_dir = os.path.join(my_app.data_dir, "sly_seg_project") @@ -31,17 +48,6 @@ checkpoints_dir = os.path.join(artifacts_dir, "checkpoints") sly.fs.mkdir(checkpoints_dir) -root_source_dir = str(Path(sys.argv[0]).parents[2]) -sly.logger.info(f"Root source directory: {root_source_dir}") -sys.path.append(root_source_dir) -source_path = str(Path(sys.argv[0]).parents[0]) -sly.logger.info(f"App source directory: {source_path}") -sys.path.append(source_path) -ui_sources_dir = os.path.join(source_path, "ui") -sly.logger.info(f"UI source directory: {ui_sources_dir}") -sys.path.append(ui_sources_dir) -sly.logger.info(f"Added to sys.path: {ui_sources_dir}") - configs_dir = os.path.join(root_source_dir, "configs") mmseg_ver = pkg_resources.get_distribution("mmsegmentation").version if os.path.isdir(f"/tmp/mmseg/mmsegmentation-{mmseg_ver}"): @@ -50,4 +56,4 @@ sly.logger.info(f"Getting model configs of current mmsegmentation version {mmseg_ver}...") shutil.copytree(f"/tmp/mmseg/mmsegmentation-{mmseg_ver}/configs", configs_dir) models_cnt = len(os.listdir(configs_dir)) - 1 - sly.logger.info(f"Found {models_cnt} models in {configs_dir} directory.") + sly.logger.info(f"Found {models_cnt} folders in {configs_dir} directory.") diff --git a/train/src/ui/architectures.html b/train/src/ui/architectures.html index 2d6af66..af73aca 100644 --- a/train/src/ui/architectures.html +++ b/train/src/ui/architectures.html @@ -24,20 +24,7 @@ Learn more... -
Pretrained model:
diff --git a/train/src/ui/architectures.py b/train/src/ui/architectures.py index ab7b35e..0bc0d90 100644 --- a/train/src/ui/architectures.py +++ b/train/src/ui/architectures.py @@ -6,50 +6,13 @@ import sly_globals as g import supervisely as sly from supervisely.app.v1.widgets.progress_bar import ProgressBar +import init_default_cfg as init_dc from mmcv import Config cfg = None -def init_default_cfg_params(state): - state["optimizer"] = "SGD" - state["lr"] = 0.001 - state["weightDecay"] = 0 - state["decodeHeadLoss"] = "CrossEntropyLoss" - state["auxiliaryHeadLoss"] = "CrossEntropyLoss" - state["decodeHeadLossWeight"] = 1.0 - state["auxiliaryHeadLossWeight"] = 0.4 - state["lrPolicy"] = "Cyclic" - state["useWarmup"] = False - state["warmup"] = "constant" - state["warmupIters"] = 0 - state["warmupRatio"] = 0.1 - state["schedulerByEpochs"] = False - state["minLREnabled"] = False - state["minLR"] = None - state["minLRRatio"] = None - state["power"] = 1 - state["momentum"] = 0.9 - state["beta1"] = 0.9 - state["beta2"] = 0.999 - state["input_size"] = { - "value": { - "width": 256, - "height": 256, - "proportional": False - }, - "options": { - "proportions": { - "width": 100, - "height": 100 - }, - "min": 64 - } - } - state["batchSizePerGPU"] = 4 - state["workersPerGPU"] = 2 - def init(data, state): - state['pretrainedModel'] = 'SegFormer' + state['pretrainedModel'] = 'Segformer' data["pretrainedModels"], metrics = get_pretrained_models(return_metrics=True) model_select_info = [] for model_name, params in data["pretrainedModels"].items(): @@ -74,22 +37,11 @@ def init(data, state): state["loadingModel"] = False # default hyperparams that may be reassigned from model default params - init_default_cfg_params(state) + init_dc.init_default_cfg_params(state) ProgressBar(g.task_id, g.api, "data.progress6", "Download weights", is_size=True, min_report_percent=5).init_data(data) - ''' - data["github_icon"] = { - "imageUrl": "https://github.githubassets.com/favicons/favicon.png", - "rounded": False, - "bgColor": "rgba(0,0,0,0)" - } - data["arxiv_icon"] = { - "imageUrl": "https://static.arxiv.org/static/browse/0.3.2.8/images/icons/favicon.ico", - "rounded": False, - "bgColor": "rgba(0,0,0,0)" - } - ''' + def get_pretrained_models(return_metrics=False): model_yamls = sly.json.load_json_file(os.path.join(g.root_source_dir, "models", "model_meta.json")) @@ -99,9 +51,6 @@ def get_pretrained_models(return_metrics=False): with open(os.path.join(g.configs_dir, model_meta["yml_file"]), "r") as stream: model_info = yaml.safe_load(stream) model_config[model_meta["model_name"]] = {} - # model_config[model_meta["model_name"]]["code_url"] = model_info["Collections"][0]["Code"]["URL"] - # model_config[model_meta["model_name"]]["paper_title"] = model_info["Collections"][0]["Paper"]["Title"] - # model_config[model_meta["model_name"]]["paper_url"] = model_info["Collections"][0]["Paper"]["URL"] model_config[model_meta["model_name"]]["checkpoints"] = [] model_config[model_meta["model_name"]]["paper_from"] = model_meta["paper_from"] model_config[model_meta["model_name"]]["year"] = model_meta["year"] @@ -111,6 +60,7 @@ def get_pretrained_models(return_metrics=False): for model in model_info["Models"]: checkpoint_info = {} checkpoint_info["name"] = model["Name"] + checkpoint_info["method"] = model["In Collection"] checkpoint_info["backbone"] = model["Metadata"]["backbone"] try: checkpoint_info["inference_time"] = model["Metadata"]["inference time (ms/im)"][0]["value"] @@ -142,14 +92,15 @@ def get_table_columns(metrics): columns = [ {"key": "name", "title": " ", "subtitle": None}, {"key": "backbone", "title": "Backbone", "subtitle": None}, + {"key": "method", "title": "Method", "subtitle": None}, {"key": "dataset", "title": "Dataset", "subtitle": None}, {"key": "inference_time", "title": "Inference time", "subtitle": "(ms/im)"}, {"key": "crop_size", "title": "Input size", "subtitle": "(H, W)"}, {"key": "lr_schd", "title": "LR scheduler", "subtitle": "steps"}, - {"key": "training_memory", "title": "Training memory", "subtitle": "GB"}, + {"key": "training_memory", "title": "Memory", "subtitle": "Training (GB)"}, ] for metric in metrics: - columns.append({"key": metric, "title": f"{metric} score", "subtitle": None}) + columns.append({"key": metric, "title": metric, "subtitle": "score"}) return columns @@ -178,138 +129,14 @@ def download_custom_config(state): download_sly_file(config_remote_dir, g.model_config_local_path, progress) -def init_default_cfg_args(cfg): - params = [ - { - "field": "state.decodeHeadLoss", - "payload": cfg.model.decode_head[0].loss_decode.type if isinstance(cfg.model.decode_head, list) else cfg.model.decode_head.loss_decode.type - }, - { - "field": "state.decodeHeadLossWeight", - "payload": cfg.model.decode_head[0].loss_decode.loss_weight if isinstance(cfg.model.decode_head, list) else cfg.model.decode_head.loss_decode.loss_weight - }, - ] - if hasattr(cfg.model, "auxiliary_head") and cfg.model.auxiliary_head is not None: - params.extend([ - { - "field": "state.auxiliaryHeadLoss", - "payload": cfg.model.decode_head[0].loss_decode.type if isinstance(cfg.model.decode_head, - list) else cfg.model.decode_head.loss_decode.type - }, - { - "field": "state.auxiliaryHeadLossWeight", - "payload": cfg.model.auxiliary_head[0].loss_decode.loss_weight if isinstance(cfg.model.auxiliary_head, list) else cfg.model.auxiliary_head.loss_decode.loss_weight - } - ]) - if hasattr(cfg.data, "samples_per_gpu"): - params.extend([{ - "field": "state.batchSizePerGPU", - "payload": cfg.data.samples_per_gpu - }]) - if hasattr(cfg.data, "workers_per_gpu"): - params.extend([{ - "field": "state.workersPerGPU", - "payload": cfg.data.workers_per_gpu - }]) - if hasattr(cfg, "crop_size"): - params.extend([{ - "field": "state.input_size.value.height", - "payload": cfg.crop_size[0] - },{ - "field": "state.input_size.value.width", - "payload": cfg.crop_size[1] - },{ - "field": "state.input_size.options.proportions.height", - "payload": 100 - },{ - "field": "state.input_size.options.proportions.width", - "payload": 100 * (cfg.crop_size[1] / cfg.crop_size[0]) - }]) - if hasattr(cfg.optimizer, "type"): - params.extend([{ - "field": "state.optimizer", - "payload": cfg.optimizer.type - }]) - if hasattr(cfg.optimizer, "lr"): - params.extend([{ - "field": "state.lr", - "payload": cfg.optimizer.lr - }]) - if hasattr(cfg.optimizer, "weight_decay"): - params.extend([{ - "field": "state.weightDecay", - "payload": cfg.optimizer.weight_decay - }]) - if hasattr(cfg.optimizer, "momentum"): - params.extend([{ - "field": "state.momentum", - "payload": cfg.optimizer.momentum - }]) - if hasattr(cfg.optimizer, "betas"): - params.extend([{ - "field": "state.beta1", - "payload": cfg.optimizer.betas[0] - },{ - "field": "state.beta2", - "payload": cfg.optimizer.betas[1] - }]) - # take lr scheduler params - if hasattr(cfg, "lr_config"): - if hasattr(cfg.lr_config, "policy"): - policy = cfg.lr_config.policy.capitalize() - params.extend([{ - "field": "state.lrPolicy", - "payload": "Cyclic" - }]) - if hasattr(cfg.lr_config, "warmup"): - params.extend([{ - "field": "state.useWarmup", - "payload": True - },{ - "field": "state.warmup", - "payload": cfg.lr_config.warmup - }]) - if hasattr(cfg.lr_config, "warmup_iters"): - params.extend([{ - "field": "state.warmupIters", - "payload": cfg.lr_config.warmup_iters - }]) - if hasattr(cfg.lr_config, "warmup_ratio"): - params.extend([{ - "field": "state.warmupRatio", - "payload": cfg.lr_config.warmup_ratio - }]) - if hasattr(cfg.lr_config, "by_epoch"): - params.extend([{ - "field": "state.schedulerByEpochs", - "payload": cfg.lr_config.by_epoch - }]) - if hasattr(cfg.lr_config, "min_lr"): - params.extend([{ - "field": "state.minLREnabled", - "payload": True - },{ - "field": "state.minLR", - "payload": cfg.lr_config.min_lr - }]) - if hasattr(cfg.lr_config, "power"): - params.extend([{ - "field": "state.power", - "payload": cfg.lr_config.power - }]) - - return params - - @g.my_app.callback("download_weights") @sly.timeit -# @g.my_app.ignore_errors_and_show_dialog_window() +@g.my_app.ignore_errors_and_show_dialog_window() def download_weights(api: sly.Api, task_id, context, state, app_logger): progress = ProgressBar(g.task_id, g.api, "data.progress6", "Download weights", is_size=True, min_report_percent=5) try: if state["weightsInitialization"] == "custom": - # raise NotImplementedError weights_path_remote = state["weightsPath"] if not weights_path_remote.endswith(".pth"): raise ValueError(f"Weights file has unsupported extension {sly.fs.get_file_ext(weights_path_remote)}. " @@ -332,7 +159,6 @@ def download_weights(api: sly.Api, task_id, context, state, app_logger): if weights_url is not None: g.local_weights_path = os.path.join(g.my_app.data_dir, sly.fs.get_file_name_with_ext(weights_url)) g.model_config_local_path = os.path.join(g.root_source_dir, config_file) - # TODO: check that pretrained weights are exist on remote server if sly.fs.file_exists(g.local_weights_path) is False: response = requests.head(weights_url, allow_redirects=True) sizeb = int(response.headers.get('content-length', 0)) @@ -362,9 +188,9 @@ def download_weights(api: sly.Api, task_id, context, state, app_logger): if state["weightsInitialization"] != "custom": cfg.pretrained_model = state["pretrainedModel"] # print(f'Config:\n{cfg.pretty_text}') - params = init_default_cfg_args(cfg) + params = init_dc.init_default_cfg_args(cfg) fields.extend(params) - if cfg.pretrained_model in ["CGNet", "DPT", "ERFNet", "HRNet", "MobileNetV3", "OCRNet", "PointRend", "SegFormer", "SemanticFPN", "Twins"]: + if cfg.pretrained_model in ["CGNet", "DPT", "ERFNet", "HRNet", "MobileNetV3", "OCRNet", "PointRend", "Segformer", "SemanticFPN", "Twins"]: fields.extend([ {"field": "state.useAuxiliaryHead", "payload": False} ]) diff --git a/train/src/ui/hyperparameters.html b/train/src/ui/hyperparameters.html index a31d253..06a1369 100644 --- a/train/src/ui/hyperparameters.html +++ b/train/src/ui/hyperparameters.html @@ -94,7 +94,7 @@
Choose optimizer and its settings, learn more in official - + pytorch documentation
@@ -165,7 +165,7 @@
-
Selected classes order: ( {{class_name}} __bg__ )
+
Selected classes order: ( {{class_name}},__bg__ )
@@ -214,7 +214,7 @@
Choose LR scheduler and its settings, learn more in official - + pytorch documentation or in diff --git a/train/src/ui/hyperparameters.py b/train/src/ui/hyperparameters.py index 68db9aa..129abc3 100644 --- a/train/src/ui/hyperparameters.py +++ b/train/src/ui/hyperparameters.py @@ -85,6 +85,7 @@ def init(data, state): def restart(data, state): data["done6"] = False + data["availableMetrics"] = ["mIoU", "mDice"] @g.my_app.callback("use_hyp") diff --git a/train/src/ui/monitoring.html b/train/src/ui/monitoring.html index ec98d43..fd710c0 100644 --- a/train/src/ui/monitoring.html +++ b/train/src/ui/monitoring.html @@ -63,7 +63,6 @@ - -
{{state.chartTrainLoss.options.smoothingWeight}}
Date: Wed, 6 Apr 2022 07:51:26 +0000 Subject: [PATCH 2/4] v0.23.0 updates 2 --- models/model_meta.json | 13 +- serve/src/sly_serve.py | 2 +- train/augs/hard.json | 99 ++++++++++++ train/augs/hard_corrupt.json | 150 ++++++++++++++++++ train/augs/light.json | 81 ++++++++++ ..._flipLR_flipUD.json => light_corrupt.json} | 132 +++++++-------- train/augs/medium.json | 90 +++++++++++ train/augs/medium_corrupt.json | 141 ++++++++++++++++ train/augs/seg_simple.json | 74 --------- train/augs/seg_simple_rotate.json | 90 ----------- train/augs/seg_simple_rotate_crop.json | 106 ------------- train/augs/seg_simple_rotate_crop_flipLR.json | 115 -------------- train/src/init_cfg.py | 96 +++++------ train/src/init_default_cfg.py | 4 +- train/src/sly_imgaugs.py | 77 +++++++++ train/src/ui/architectures.py | 6 +- train/src/ui/augs.py | 58 +++---- train/src/ui/hyperparameters.html | 10 +- train/src/ui/monitoring.py | 2 +- 19 files changed, 808 insertions(+), 538 deletions(-) create mode 100644 train/augs/hard.json create mode 100644 train/augs/hard_corrupt.json create mode 100644 train/augs/light.json rename train/augs/{seg_simple_rotate_crop_flipLR_flipUD.json => light_corrupt.json} (58%) create mode 100644 train/augs/medium.json create mode 100644 train/augs/medium_corrupt.json delete mode 100644 train/augs/seg_simple.json delete mode 100644 train/augs/seg_simple_rotate.json delete mode 100644 train/augs/seg_simple_rotate_crop.json delete mode 100644 train/augs/seg_simple_rotate_crop_flipLR.json diff --git a/models/model_meta.json b/models/model_meta.json index 07650ad..8da4574 100644 --- a/models/model_meta.json +++ b/models/model_meta.json @@ -1,16 +1,17 @@ [ - { - "model_name" : "BEiT", - "yml_file" : "beit/beit.yml", - "paper_from": "ICLR", - "year": 2022 - }, { "model_name" : "ConvNeXt", "yml_file" : "convnext/convnext.yml", "paper_from": "CVPR", "year": 2022 }, + { + "model_name" : "BEiT", + "yml_file" : "beit/beit.yml", + "paper_from": "ICLR", + "year": 2022 + }, + { "model_name" : "KNet", "yml_file" : "knet/knet.yml", diff --git a/serve/src/sly_serve.py b/serve/src/sly_serve.py index c0ce5b4..baa49f6 100644 --- a/serve/src/sly_serve.py +++ b/serve/src/sly_serve.py @@ -119,7 +119,7 @@ def init_model(api: sly.Api, task_id, context, state, app_logger): def init_state_and_data(data, state): - state['pretrainedModel'] = 'Segformer' + state['pretrainedModel'] = 'ConvNeXt' data["pretrainedModels"], metrics = utils.get_pretrained_models(return_metrics=True) model_select_info = [] for model_name, params in data["pretrainedModels"].items(): diff --git a/train/augs/hard.json b/train/augs/hard.json new file mode 100644 index 0000000..354ac4c --- /dev/null +++ b/train/augs/hard.json @@ -0,0 +1,99 @@ +{ + "pipeline": [ + { + "category": "color", + "name": "MultiplyAndAddToBrightness", + "params": { + "mul": [ + 0.5, + 1.5 + ], + "add": [ + -80, + 80 + ], + "to_colorspace": "YCrCb", + "from_colorspace": "RGB", + "random_order": true + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.color.MultiplyAndAddToBrightness(mul=(0.5, 1.5), add=(-80, 80), to_colorspace='YCrCb', from_colorspace='RGB', random_order=True))" + }, + { + "category": "contrast", + "name": "GammaContrast", + "params": { + "gamma": [ + 0.5, + 2.0 + ], + "per_channel": true + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.contrast.GammaContrast(gamma=(0.5, 2.0), per_channel=True))" + }, + { + "category": "geometric", + "name": "Affine", + "params": { + "scale": [ + 0.6, + 1.6 + ], + "translate_percent": { + "x": [-0.3, 0.3], + "y": [-0.3, 0.3] + }, + "rotate": [ + -90, + 90 + ], + "shear": { + "x": [-45, 45], + "y": [-45, 45] + }, + "order": 1, + "cval": 0, + "mode": "constant", + "fit_output": false + }, + "sometimes": 0.7, + "python": "iaa.Sometimes(0.7, iaa.geometric.Affine(scale=(0.6, 1.6), translate_percent={'x': (-0.3, 0.3), 'y': (-0.3, 0.3)}, rotate=(-90, 90), shear={'x': (-45, 45), 'y': (-45, 45)}, order=1, cval=0, mode='constant', fit_output=False))" + }, + { + "category": "size", + "name": "CropAndPad", + "params": { + "percent": [ + -0.3, + 0.3 + ], + "pad_mode": "constant", + "pad_cval": 0, + "keep_size": false, + "sample_independently": true + }, + "sometimes": 0.4, + "python": "iaa.Sometimes(0.4, iaa.size.CropAndPad(percent=(-0.3, 0.3), pad_mode='constant', pad_cval=0, keep_size=False, sample_independently=True))" + }, + { + "category": "flip", + "name": "Fliplr", + "params": { + "p": 1.0 + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.flip.Fliplr(p=1.0))" + }, + { + "category": "flip", + "name": "Flipud", + "params": { + "p": 1.0 + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.flip.Flipud(p=1.0))" + } + ], + "random_order": false +} \ No newline at end of file diff --git a/train/augs/hard_corrupt.json b/train/augs/hard_corrupt.json new file mode 100644 index 0000000..cb81b0a --- /dev/null +++ b/train/augs/hard_corrupt.json @@ -0,0 +1,150 @@ +{ + "pipeline": [ + { + "category": "color", + "name": "MultiplyAndAddToBrightness", + "params": { + "mul": [ + 0.5, + 1.5 + ], + "add": [ + -80, + 80 + ], + "to_colorspace": "YCrCb", + "from_colorspace": "RGB", + "random_order": true + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.color.MultiplyAndAddToBrightness(mul=(0.5, 1.5), add=(-80, 80), to_colorspace='YCrCb', from_colorspace='RGB', random_order=True))" + }, + { + "category": "contrast", + "name": "GammaContrast", + "params": { + "gamma": [ + 0.5, + 2.0 + ], + "per_channel": true + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.contrast.GammaContrast(gamma=(0.5, 2.0), per_channel=True))" + }, + { + "category": "geometric", + "name": "Affine", + "params": { + "scale": [ + 0.6, + 1.6 + ], + "translate_percent": { + "x": [-0.3, 0.3], + "y": [-0.3, 0.3] + }, + "rotate": [ + -90, + 90 + ], + "shear": { + "x": [-45, 45], + "y": [-45, 45] + }, + "order": 1, + "cval": 0, + "mode": "constant", + "fit_output": false + }, + "sometimes": 0.7, + "python": "iaa.Sometimes(0.7, iaa.geometric.Affine(scale=(0.6, 1.6), translate_percent={'x': (-0.3, 0.3), 'y': (-0.3, 0.3)}, rotate=(-90, 90), shear={'x': (-45, 45), 'y': (-45, 45)}, order=1, cval=0, mode='constant', fit_output=False))" + }, + { + "category": "size", + "name": "CropAndPad", + "params": { + "percent": [ + -0.3, + 0.3 + ], + "pad_mode": "constant", + "pad_cval": 0, + "keep_size": false, + "sample_independently": true + }, + "sometimes": 0.4, + "python": "iaa.Sometimes(0.4, iaa.size.CropAndPad(percent=(-0.3, 0.3), pad_mode='constant', pad_cval=0, keep_size=False, sample_independently=True))" + }, + { + "category": "flip", + "name": "Fliplr", + "params": { + "p": 1.0 + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.flip.Fliplr(p=1.0))" + }, + { + "category": "flip", + "name": "Flipud", + "params": { + "p": 1.0 + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.flip.Flipud(p=1.0))" + }, + { + "category": "blur", + "name": "GaussianBlur", + "params": { + "sigma": [ + 0, + 3 + ] + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.blur.GaussianBlur(sigma=(0, 3)))" + }, + { + "category": "arithmetic", + "name": "JpegCompression", + "params": { + "compression": [ + 5, + 20 + ] + }, + "sometimes": 0.4, + "python": "iaa.Sometimes(0.4, iaa.arithmetic.JpegCompression(compression=(5, 20)))" + }, + { + "category": "arithmetic", + "name": "AdditiveGaussianNoise", + "params": { + "loc": 0, + "scale": [ + 1, + 15 + ], + "per_channel": false + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.arithmetic.AdditiveGaussianNoise(loc=0, scale=(1, 15), per_channel=False))" + }, + { + "category": "arithmetic", + "name": "SaltAndPepper", + "params": { + "p": [ + 0, + 0.4 + ], + "per_channel": false + }, + "sometimes": 0.4, + "python": "iaa.Sometimes(0.4, iaa.arithmetic.SaltAndPepper(p=(0, 0.4), per_channel=False))" + } + ], + "random_order": false +} \ No newline at end of file diff --git a/train/augs/light.json b/train/augs/light.json new file mode 100644 index 0000000..4aa7edc --- /dev/null +++ b/train/augs/light.json @@ -0,0 +1,81 @@ +{ + "pipeline": [ + { + "category": "color", + "name": "MultiplyAndAddToBrightness", + "params": { + "mul": [ + 0.8, + 1.2 + ], + "add": [ + -30, + 30 + ], + "to_colorspace": "YCrCb", + "from_colorspace": "RGB", + "random_order": true + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.color.MultiplyAndAddToBrightness(mul=(0.8, 1.2), add=(-30, 30), to_colorspace='YCrCb', from_colorspace='RGB', random_order=True))" + }, + { + "category": "contrast", + "name": "GammaContrast", + "params": { + "gamma": [ + 0.8, + 1.2 + ], + "per_channel": true + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.contrast.GammaContrast(gamma=(0.8, 1.2), per_channel=True))" + }, + { + "category": "geometric", + "name": "Affine", + "params": { + "scale": [ + 0.8, + 1.2 + ], + "translate_percent": { + "x": [-0.1, 0.1], + "y": [-0.1, 0.1] + }, + "rotate": [ + -30, + 30 + ], + "shear": { + "x": [-15, 15], + "y": [-15, 15] + }, + "order": 1, + "cval": 0, + "mode": "constant", + "fit_output": false + }, + "sometimes": 0.4, + "python": "iaa.Sometimes(0.4, iaa.geometric.Affine(scale=(0.8, 1.2), translate_percent={'x': (-0.1, 0.1), 'y': (-0.1, 0.1)}, rotate=(-30, 30), shear={'x': (-15, 15), 'y': (-15, 15)}, order=1, cval=0, mode='constant', fit_output=False))" + }, + { + "category": "size", + "name": "CropAndPad", + "params": { + "percent": [ + -0.1, + 0.1 + ], + "pad_mode": "constant", + "pad_cval": 0, + "keep_size": false, + "sample_independently": true + }, + "sometimes": 0.4, + "python": "iaa.Sometimes(0.4, iaa.size.CropAndPad(percent=(-0.1, 0.1), pad_mode='constant', pad_cval=0, keep_size=False, sample_independently=True))" + } + ], + "random_order": false +} \ No newline at end of file diff --git a/train/augs/seg_simple_rotate_crop_flipLR_flipUD.json b/train/augs/light_corrupt.json similarity index 58% rename from train/augs/seg_simple_rotate_crop_flipLR_flipUD.json rename to train/augs/light_corrupt.json index c8ff270..72cb37a 100644 --- a/train/augs/seg_simple_rotate_crop_flipLR_flipUD.json +++ b/train/augs/light_corrupt.json @@ -1,25 +1,12 @@ { "pipeline": [ - { - "category": "arithmetic", - "name": "SaltAndPepper", - "params": { - "p": [ - 0, - 0.23 - ], - "per_channel": false - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.arithmetic.SaltAndPepper(p=(0, 0.23), per_channel=False))" - }, { "category": "color", "name": "MultiplyAndAddToBrightness", "params": { "mul": [ - 0.7, - 1.3 + 0.8, + 1.2 ], "add": [ -30, @@ -29,95 +16,116 @@ "from_colorspace": "RGB", "random_order": true }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.color.MultiplyAndAddToBrightness(mul=(0.7, 1.3), add=(-30, 30), to_colorspace='YCrCb', from_colorspace='RGB', random_order=True))" - }, - { - "category": "blur", - "name": "GaussianBlur", - "params": { - "sigma": [ - 0, - 3 - ] - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.blur.GaussianBlur(sigma=(0, 3)))" + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.color.MultiplyAndAddToBrightness(mul=(0.8, 1.2), add=(-30, 30), to_colorspace='YCrCb', from_colorspace='RGB', random_order=True))" }, { "category": "contrast", "name": "GammaContrast", "params": { "gamma": [ - 0.7, - 1.7 + 0.8, + 1.2 ], - "per_channel": false + "per_channel": true }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.contrast.GammaContrast(gamma=(0.7, 1.7), per_channel=False))" - }, - { - "category": "arithmetic", - "name": "JpegCompression", - "params": { - "compression": [ - 85, - 100 - ] - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.arithmetic.JpegCompression(compression=(85, 100)))" + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.contrast.GammaContrast(gamma=(0.8, 1.2), per_channel=True))" }, { "category": "geometric", - "name": "Rotate", + "name": "Affine", "params": { + "scale": [ + 0.8, + 1.2 + ], + "translate_percent": { + "x": [-0.1, 0.1], + "y": [-0.1, 0.1] + }, "rotate": [ -30, 30 ], + "shear": { + "x": [-15, 15], + "y": [-15, 15] + }, "order": 1, "cval": 0, "mode": "constant", "fit_output": false }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.geometric.Rotate(rotate=(-30, 30), order=1, cval=0, mode='constant', fit_output=False))" + "sometimes": 0.4, + "python": "iaa.Sometimes(0.4, iaa.geometric.Affine(scale=(0.8, 1.2), translate_percent={'x': (-0.1, 0.1), 'y': (-0.1, 0.1)}, rotate=(-30, 30), shear={'x': (-15, 15), 'y': (-15, 15)}, order=1, cval=0, mode='constant', fit_output=False))" }, { "category": "size", "name": "CropAndPad", "params": { "percent": [ - -0.5, - 0.5 + -0.1, + 0.1 ], "pad_mode": "constant", "pad_cval": 0, "keep_size": false, "sample_independently": true }, + "sometimes": 0.4, + "python": "iaa.Sometimes(0.4, iaa.size.CropAndPad(percent=(-0.1, 0.1), pad_mode='constant', pad_cval=0, keep_size=False, sample_independently=True))" + }, + { + "category": "blur", + "name": "GaussianBlur", + "params": { + "sigma": [ + 0, + 3 + ] + }, + "sometimes": 0.2, + "python": "iaa.Sometimes(0.2, iaa.blur.GaussianBlur(sigma=(0, 3)))" + }, + { + "category": "arithmetic", + "name": "JpegCompression", + "params": { + "compression": [ + 0, + 10 + ] + }, "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.size.CropAndPad(percent=(-0.5, 0.5), pad_mode='constant', pad_cval=0, keep_size=False, sample_independently=True))" + "python": "iaa.Sometimes(0.2, iaa.arithmetic.JpegCompression(compression=(0, 10)))" }, { - "category": "flip", - "name": "Fliplr", + "category": "arithmetic", + "name": "AdditiveGaussianNoise", "params": { - "p": 1.0 + "loc": 0, + "scale": [ + 1, + 5 + ], + "per_channel": false }, - "sometimes": 0.3, - "python": "iaa.Sometimes(0.3, iaa.flip.Fliplr(p=1.0))" + "sometimes": 0.2, + "python": "iaa.Sometimes(0.2, iaa.arithmetic.AdditiveGaussianNoise(loc=0, scale=(1, 5), per_channel=False))" }, { - "category": "flip", - "name": "Flipud", + "category": "arithmetic", + "name": "SaltAndPepper", "params": { - "p": 1.0 + "p": [ + 0, + 0.2 + ], + "per_channel": false }, - "sometimes": 0.3, - "python": "iaa.Sometimes(0.3, iaa.flip.Flipud(p=1.0))" + "sometimes": 0.2, + "python": "iaa.Sometimes(0.2, iaa.arithmetic.SaltAndPepper(p=(0, 0.2), per_channel=False))" } ], "random_order": false diff --git a/train/augs/medium.json b/train/augs/medium.json new file mode 100644 index 0000000..1ae46bc --- /dev/null +++ b/train/augs/medium.json @@ -0,0 +1,90 @@ +{ + "pipeline": [ + { + "category": "color", + "name": "MultiplyAndAddToBrightness", + "params": { + "mul": [ + 0.7, + 1.3 + ], + "add": [ + -50, + 50 + ], + "to_colorspace": "YCrCb", + "from_colorspace": "RGB", + "random_order": true + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.color.MultiplyAndAddToBrightness(mul=(0.7, 1.3), add=(-50, 50), to_colorspace='YCrCb', from_colorspace='RGB', random_order=True))" + }, + { + "category": "contrast", + "name": "GammaContrast", + "params": { + "gamma": [ + 0.7, + 1.5 + ], + "per_channel": true + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.contrast.GammaContrast(gamma=(0.7, 1.5), per_channel=True))" + }, + { + "category": "geometric", + "name": "Affine", + "params": { + "scale": [ + 0.7, + 1.4 + ], + "translate_percent": { + "x": [-0.2, 0.2], + "y": [-0.2, 0.2] + }, + "rotate": [ + -60, + 60 + ], + "shear": { + "x": [-30, 30], + "y": [-30, 30] + }, + "order": 1, + "cval": 0, + "mode": "constant", + "fit_output": false + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.geometric.Affine(scale=(0.7, 1.4), translate_percent={'x': (-0.2, 0.2), 'y': (-0.2, 0.2)}, rotate=(-60, 60), shear={'x': (-30, 30), 'y': (-30, 30)}, order=1, cval=0, mode='constant', fit_output=False))" + }, + { + "category": "size", + "name": "CropAndPad", + "params": { + "percent": [ + -0.2, + 0.2 + ], + "pad_mode": "constant", + "pad_cval": 0, + "keep_size": false, + "sample_independently": true + }, + "sometimes": 0.4, + "python": "iaa.Sometimes(0.4, iaa.size.CropAndPad(percent=(-0.2, 0.2), pad_mode='constant', pad_cval=0, keep_size=False, sample_independently=True))" + }, + { + "category": "flip", + "name": "Fliplr", + "params": { + "p": 1.0 + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.flip.Fliplr(p=1.0))" + } + ], + "random_order": false +} \ No newline at end of file diff --git a/train/augs/medium_corrupt.json b/train/augs/medium_corrupt.json new file mode 100644 index 0000000..be940be --- /dev/null +++ b/train/augs/medium_corrupt.json @@ -0,0 +1,141 @@ +{ + "pipeline": [ + { + "category": "color", + "name": "MultiplyAndAddToBrightness", + "params": { + "mul": [ + 0.7, + 1.3 + ], + "add": [ + -50, + 50 + ], + "to_colorspace": "YCrCb", + "from_colorspace": "RGB", + "random_order": true + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.color.MultiplyAndAddToBrightness(mul=(0.7, 1.3), add=(-50, 50), to_colorspace='YCrCb', from_colorspace='RGB', random_order=True))" + }, + { + "category": "contrast", + "name": "GammaContrast", + "params": { + "gamma": [ + 0.7, + 1.5 + ], + "per_channel": true + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.contrast.GammaContrast(gamma=(0.7, 1.5), per_channel=True))" + }, + { + "category": "geometric", + "name": "Affine", + "params": { + "scale": [ + 0.7, + 1.4 + ], + "translate_percent": { + "x": [-0.2, 0.2], + "y": [-0.2, 0.2] + }, + "rotate": [ + -60, + 60 + ], + "shear": { + "x": [-30, 30], + "y": [-30, 30] + }, + "order": 1, + "cval": 0, + "mode": "constant", + "fit_output": false + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.geometric.Affine(scale=(0.7, 1.4), translate_percent={'x': (-0.2, 0.2), 'y': (-0.2, 0.2)}, rotate=(-60, 60), shear={'x': (-30, 30), 'y': (-30, 30)}, order=1, cval=0, mode='constant', fit_output=False))" + }, + { + "category": "size", + "name": "CropAndPad", + "params": { + "percent": [ + -0.2, + 0.2 + ], + "pad_mode": "constant", + "pad_cval": 0, + "keep_size": false, + "sample_independently": true + }, + "sometimes": 0.4, + "python": "iaa.Sometimes(0.4, iaa.size.CropAndPad(percent=(-0.2, 0.2), pad_mode='constant', pad_cval=0, keep_size=False, sample_independently=True))" + }, + { + "category": "flip", + "name": "Fliplr", + "params": { + "p": 1.0 + }, + "sometimes": 0.5, + "python": "iaa.Sometimes(0.5, iaa.flip.Fliplr(p=1.0))" + }, + { + "category": "blur", + "name": "GaussianBlur", + "params": { + "sigma": [ + 0, + 3 + ] + }, + "sometimes": 0.3, + "python": "iaa.Sometimes(0.3, iaa.blur.GaussianBlur(sigma=(0, 3)))" + }, + { + "category": "arithmetic", + "name": "JpegCompression", + "params": { + "compression": [ + 0, + 15 + ] + }, + "sometimes": 0.3, + "python": "iaa.Sometimes(0.3, iaa.arithmetic.JpegCompression(compression=(0, 15)))" + }, + { + "category": "arithmetic", + "name": "AdditiveGaussianNoise", + "params": { + "loc": 0, + "scale": [ + 1, + 10 + ], + "per_channel": false + }, + "sometimes": 0.3, + "python": "iaa.Sometimes(0.3, iaa.arithmetic.AdditiveGaussianNoise(loc=0, scale=(1, 10), per_channel=False))" + }, + { + "category": "arithmetic", + "name": "SaltAndPepper", + "params": { + "p": [ + 0, + 0.3 + ], + "per_channel": false + }, + "sometimes": 0.3, + "python": "iaa.Sometimes(0.3, iaa.arithmetic.SaltAndPepper(p=(0, 0.3), per_channel=False))" + } + ], + "random_order": false +} \ No newline at end of file diff --git a/train/augs/seg_simple.json b/train/augs/seg_simple.json deleted file mode 100644 index 04b4f40..0000000 --- a/train/augs/seg_simple.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "pipeline": [ - { - "category": "arithmetic", - "name": "SaltAndPepper", - "params": { - "p": [ - 0, - 0.23 - ], - "per_channel": false - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.arithmetic.SaltAndPepper(p=(0, 0.23), per_channel=False))" - }, - { - "category": "color", - "name": "MultiplyAndAddToBrightness", - "params": { - "mul": [ - 0.7, - 1.3 - ], - "add": [ - -30, - 30 - ], - "to_colorspace": "YCrCb", - "from_colorspace": "RGB", - "random_order": true - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.color.MultiplyAndAddToBrightness(mul=(0.7, 1.3), add=(-30, 30), to_colorspace='YCrCb', from_colorspace='RGB', random_order=True))" - }, - { - "category": "blur", - "name": "GaussianBlur", - "params": { - "sigma": [ - 0, - 3 - ] - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.blur.GaussianBlur(sigma=(0, 3)))" - }, - { - "category": "contrast", - "name": "GammaContrast", - "params": { - "gamma": [ - 0.7, - 1.7 - ], - "per_channel": false - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.contrast.GammaContrast(gamma=(0.7, 1.7), per_channel=False))" - }, - { - "category": "arithmetic", - "name": "JpegCompression", - "params": { - "compression": [ - 85, - 100 - ] - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.arithmetic.JpegCompression(compression=(85, 100)))" - } - ], - "random_order": false -} \ No newline at end of file diff --git a/train/augs/seg_simple_rotate.json b/train/augs/seg_simple_rotate.json deleted file mode 100644 index 56e4e30..0000000 --- a/train/augs/seg_simple_rotate.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "pipeline": [ - { - "category": "arithmetic", - "name": "SaltAndPepper", - "params": { - "p": [ - 0, - 0.23 - ], - "per_channel": false - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.arithmetic.SaltAndPepper(p=(0, 0.23), per_channel=False))" - }, - { - "category": "color", - "name": "MultiplyAndAddToBrightness", - "params": { - "mul": [ - 0.7, - 1.3 - ], - "add": [ - -30, - 30 - ], - "to_colorspace": "YCrCb", - "from_colorspace": "RGB", - "random_order": true - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.color.MultiplyAndAddToBrightness(mul=(0.7, 1.3), add=(-30, 30), to_colorspace='YCrCb', from_colorspace='RGB', random_order=True))" - }, - { - "category": "blur", - "name": "GaussianBlur", - "params": { - "sigma": [ - 0, - 3 - ] - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.blur.GaussianBlur(sigma=(0, 3)))" - }, - { - "category": "contrast", - "name": "GammaContrast", - "params": { - "gamma": [ - 0.7, - 1.7 - ], - "per_channel": false - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.contrast.GammaContrast(gamma=(0.7, 1.7), per_channel=False))" - }, - { - "category": "arithmetic", - "name": "JpegCompression", - "params": { - "compression": [ - 85, - 100 - ] - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.arithmetic.JpegCompression(compression=(85, 100)))" - }, - { - "category": "geometric", - "name": "Rotate", - "params": { - "rotate": [ - -30, - 30 - ], - "order": 1, - "cval": 0, - "mode": "constant", - "fit_output": false - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.geometric.Rotate(rotate=(-30, 30), order=1, cval=0, mode='constant', fit_output=False))" - } - ], - "random_order": false -} \ No newline at end of file diff --git a/train/augs/seg_simple_rotate_crop.json b/train/augs/seg_simple_rotate_crop.json deleted file mode 100644 index c600299..0000000 --- a/train/augs/seg_simple_rotate_crop.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "pipeline": [ - { - "category": "arithmetic", - "name": "SaltAndPepper", - "params": { - "p": [ - 0, - 0.23 - ], - "per_channel": false - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.arithmetic.SaltAndPepper(p=(0, 0.23), per_channel=False))" - }, - { - "category": "color", - "name": "MultiplyAndAddToBrightness", - "params": { - "mul": [ - 0.7, - 1.3 - ], - "add": [ - -30, - 30 - ], - "to_colorspace": "YCrCb", - "from_colorspace": "RGB", - "random_order": true - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.color.MultiplyAndAddToBrightness(mul=(0.7, 1.3), add=(-30, 30), to_colorspace='YCrCb', from_colorspace='RGB', random_order=True))" - }, - { - "category": "blur", - "name": "GaussianBlur", - "params": { - "sigma": [ - 0, - 3 - ] - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.blur.GaussianBlur(sigma=(0, 3)))" - }, - { - "category": "contrast", - "name": "GammaContrast", - "params": { - "gamma": [ - 0.7, - 1.7 - ], - "per_channel": false - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.contrast.GammaContrast(gamma=(0.7, 1.7), per_channel=False))" - }, - { - "category": "arithmetic", - "name": "JpegCompression", - "params": { - "compression": [ - 85, - 100 - ] - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.arithmetic.JpegCompression(compression=(85, 100)))" - }, - { - "category": "geometric", - "name": "Rotate", - "params": { - "rotate": [ - -30, - 30 - ], - "order": 1, - "cval": 0, - "mode": "constant", - "fit_output": false - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.geometric.Rotate(rotate=(-30, 30), order=1, cval=0, mode='constant', fit_output=False))" - }, - { - "category": "size", - "name": "CropAndPad", - "params": { - "percent": [ - -0.5, - 0.5 - ], - "pad_mode": "constant", - "pad_cval": 0, - "keep_size": false, - "sample_independently": true - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.size.CropAndPad(percent=(-0.5, 0.5), pad_mode='constant', pad_cval=0, keep_size=False, sample_independently=True))" - } - ], - "random_order": false -} \ No newline at end of file diff --git a/train/augs/seg_simple_rotate_crop_flipLR.json b/train/augs/seg_simple_rotate_crop_flipLR.json deleted file mode 100644 index 4b3454f..0000000 --- a/train/augs/seg_simple_rotate_crop_flipLR.json +++ /dev/null @@ -1,115 +0,0 @@ -{ - "pipeline": [ - { - "category": "arithmetic", - "name": "SaltAndPepper", - "params": { - "p": [ - 0, - 0.23 - ], - "per_channel": false - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.arithmetic.SaltAndPepper(p=(0, 0.23), per_channel=False))" - }, - { - "category": "color", - "name": "MultiplyAndAddToBrightness", - "params": { - "mul": [ - 0.7, - 1.3 - ], - "add": [ - -30, - 30 - ], - "to_colorspace": "YCrCb", - "from_colorspace": "RGB", - "random_order": true - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.color.MultiplyAndAddToBrightness(mul=(0.7, 1.3), add=(-30, 30), to_colorspace='YCrCb', from_colorspace='RGB', random_order=True))" - }, - { - "category": "blur", - "name": "GaussianBlur", - "params": { - "sigma": [ - 0, - 3 - ] - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.blur.GaussianBlur(sigma=(0, 3)))" - }, - { - "category": "contrast", - "name": "GammaContrast", - "params": { - "gamma": [ - 0.7, - 1.7 - ], - "per_channel": false - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.contrast.GammaContrast(gamma=(0.7, 1.7), per_channel=False))" - }, - { - "category": "arithmetic", - "name": "JpegCompression", - "params": { - "compression": [ - 85, - 100 - ] - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.arithmetic.JpegCompression(compression=(85, 100)))" - }, - { - "category": "geometric", - "name": "Rotate", - "params": { - "rotate": [ - -30, - 30 - ], - "order": 1, - "cval": 0, - "mode": "constant", - "fit_output": false - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.geometric.Rotate(rotate=(-30, 30), order=1, cval=0, mode='constant', fit_output=False))" - }, - { - "category": "size", - "name": "CropAndPad", - "params": { - "percent": [ - -0.5, - 0.5 - ], - "pad_mode": "constant", - "pad_cval": 0, - "keep_size": false, - "sample_independently": true - }, - "sometimes": 0.2, - "python": "iaa.Sometimes(0.2, iaa.size.CropAndPad(percent=(-0.5, 0.5), pad_mode='constant', pad_cval=0, keep_size=False, sample_independently=True))" - }, - { - "category": "flip", - "name": "Fliplr", - "params": { - "p": 1.0 - }, - "sometimes": 0.3, - "python": "iaa.Sometimes(0.3, iaa.flip.Fliplr(p=1.0))" - } - ], - "random_order": false -} \ No newline at end of file diff --git a/train/src/init_cfg.py b/train/src/init_cfg.py index ac2228c..5e55078 100644 --- a/train/src/init_cfg.py +++ b/train/src/init_cfg.py @@ -81,46 +81,52 @@ def init_cfg_optimizer(cfg, state): cfg.optimizer.momentum_decay = state["momentumDecay"] def init_cfg_pipelines(cfg): - cfg.train_pipeline = [ - dict(type='LoadImageFromFile'), - dict(type='LoadAnnotations'), - dict(type='SlyImgAugs', config_path=augs.augs_config_path), - dict(type='Resize', img_scale=(cfg.crop_size[0], cfg.crop_size[1])), - dict(type='Normalize', **cfg.img_norm_cfg), - dict(type='DefaultFormatBundle'), - dict(type='Collect', keys=['img', 'gt_semantic_seg'], meta_keys=('filename', 'ori_filename', 'ori_shape', - 'img_shape', 'scale_factor', 'img_norm_cfg')), - ] + + train_steps_to_remove = ["RandomFlip", "PhotoMetricDistortion"] + train_pipeline = [] + for config_step in cfg.data.train.pipeline: + if config_step["type"] in train_steps_to_remove: + continue + elif config_step["type"] == "LoadAnnotations": + config_step["reduce_zero_label"] = False + train_pipeline.append(config_step) + train_pipeline.append(dict(type='SlyImgAugs', config_path=augs.augs_config_path)) + continue + elif config_step["type"] == "Resize": + if config_step["img_scale"][0] < cfg.crop_size[0] or config_step["img_scale"][1] < cfg.crop_size[1]: + config_step["img_scale"] = cfg.crop_size + elif config_step["type"] == "Normalize": + train_pipeline.append(dict(type='Normalize', **cfg.img_norm_cfg)) + continue + elif config_step["type"] == "RandomCrop": + config_step["crop_size"] = cfg.crop_size + elif config_step["type"] == "Pad": + config_step["size"] = cfg.crop_size + elif config_step["type"] == "Collect": + config_step["meta_keys"] = ('filename', 'ori_filename', 'ori_shape', 'img_shape', 'scale_factor', 'img_norm_cfg') - cfg.val_pipeline = [ - dict(type='LoadImageFromFile'), - dict( - type='MultiScaleFlipAug', - img_scale=(cfg.crop_size[0], cfg.crop_size[1]), - flip=False, - transforms=[ - dict(type='Resize', keep_ratio=True), - dict(type='RandomFlip'), - dict(type='Normalize', **cfg.img_norm_cfg), - dict(type='ImageToTensor', keys=['img']), - dict(type='Collect', keys=['img']), - ]) - ] + train_pipeline.append(config_step) + cfg.train_pipeline = train_pipeline + + test_pipeline = cfg.data.test.pipeline + for config_step in test_pipeline: + if config_step["type"] == "MultiScaleFlipAug": + if config_step["img_scale"][0] < cfg.crop_size[0] or config_step["img_scale"][1] < cfg.crop_size[1]: + config_step["img_scale"] = cfg.crop_size + transform_pipeline = [] + for transform_step in config_step["transforms"]: + if transform_step["type"] == "Normalize": + transform_pipeline.append(dict(type='Normalize', **cfg.img_norm_cfg)) + continue + elif transform_step["type"] == "Resize": + transform_step["keep_ratio"] = False + transform_pipeline.append(transform_step) + config_step["transforms"] = transform_pipeline + + cfg.val_pipeline = test_pipeline + cfg.test_pipeline = test_pipeline + - cfg.test_pipeline = [ - dict(type='LoadImageFromFile'), - dict( - type='MultiScaleFlipAug', - img_scale=(cfg.crop_size[0], cfg.crop_size[1]), - flip=False, - transforms=[ - dict(type='Resize', keep_ratio=True), - dict(type='RandomFlip'), - dict(type='Normalize', **cfg.img_norm_cfg), - dict(type='ImageToTensor', keys=['img']), - dict(type='Collect', keys=['img']), - ]) - ] def init_cfg_splits(cfg, img_dir, ann_dir, classes, palette): cfg.data.train.type = cfg.dataset_type @@ -167,6 +173,7 @@ def init_cfg_training(cfg, state): cfg.data.samples_per_gpu = state["batchSizePerGPU"] cfg.data.workers_per_gpu = state["workersPerGPU"] + cfg.data.persistent_workers = True # TODO: sync with state["gpusId"] if it will be needed cfg.gpu_ids = range(1) @@ -260,14 +267,7 @@ def init_cfg_lr(cfg, state): lr_config["three_phase"] = state["threePhase"] cfg.lr_config = lr_config -def init_cfg(state, img_dir, ann_dir, classes, palette): - cfg = architectures.cfg - - # Since we use ony one GPU, BN is used instead of SyncBN - cfg.norm_cfg = dict(type='BN', requires_grad=True) - if cfg.pretrained_model not in ["DPT", "Segformer", "SETR", "Swin Transformer", "Twins", "ViT"]: - cfg.model.backbone.norm_cfg = cfg.norm_cfg - +def init_cfg_model(cfg, state, classes): class_weights = init_class_weights(state, classes) if hasattr(cfg.model.backbone, "pretrained"): delattr(cfg.model.backbone, "pretrained") @@ -298,6 +298,10 @@ def init_cfg(state, img_dir, ann_dir, classes, palette): for key in head: cfg.model.auxiliary_head[key] = head[key] +def init_cfg(state, img_dir, ann_dir, classes, palette): + cfg = architectures.cfg + + init_cfg_model(cfg, state, classes) init_cfg_optimizer(cfg, state) init_cfg_training(cfg, state) init_cfg_pipelines(cfg) diff --git a/train/src/init_default_cfg.py b/train/src/init_default_cfg.py index 3f009d2..5b3602f 100644 --- a/train/src/init_default_cfg.py +++ b/train/src/init_default_cfg.py @@ -122,9 +122,11 @@ def init_default_cfg_args(cfg): if hasattr(cfg, "lr_config"): if hasattr(cfg.lr_config, "policy"): policy = cfg.lr_config.policy.capitalize() + if policy == "Step": + policy = "Fixed" # Sorry but it's difficult to calculate correct N steps params.extend([{ "field": "state.lrPolicy", - "payload": "Cyclic" + "payload": policy }]) if hasattr(cfg.lr_config, "warmup"): warmup = cfg.lr_config.warmup diff --git a/train/src/sly_imgaugs.py b/train/src/sly_imgaugs.py index 4cff9ad..d41ae65 100644 --- a/train/src/sly_imgaugs.py +++ b/train/src/sly_imgaugs.py @@ -1,7 +1,84 @@ import supervisely as sly from mmseg.datasets.builder import PIPELINES +from supervisely.sly_logger import logger +import imgaug.augmenters as iaa +def get_function(category_name, aug_name): + try: + submodule = getattr(iaa, category_name) + aug_f = getattr(submodule, aug_name) + return aug_f + except Exception as e: + logger.error(repr(e)) + # raise e + return None + +def build_pipeline(aug_infos, random_order=False): + pipeline = [] + for aug_info in aug_infos: + category_name = aug_info["category"] + aug_name = aug_info["name"] + params = aug_info["params"] + for param_name, param_val in params.items(): + if isinstance(param_val, dict): + if "x" in param_val.keys() and "y" in param_val.keys(): + param_val["x"] = tuple(param_val["x"]) + param_val["y"] = tuple(param_val["y"]) + elif isinstance(param_val, list): + params[param_name] = tuple(param_val) + + aug_func = get_function(category_name, aug_name) + + aug = aug_func(**params) + + sometimes = aug_info.get("sometimes", None) + if sometimes is not None: + aug = iaa.meta.Sometimes(sometimes, aug) + pipeline.append(aug) + augs = iaa.Sequential(pipeline, random_order=random_order) + return augs + + +def aug_to_python(aug_info): + pstr = "" + for name, value in aug_info["params"].items(): + v = value + if type(v) is list: #name != 'nb_iterations' and + v = (v[0], v[1]) + elif type(v) is dict and "x" in v.keys() and "y" in v.keys(): + v = {"x": (v["x"][0], v["x"][1]), "y": (v["y"][0], v["y"][1])} + + if type(value) is str: + pstr += f"{name}='{v}', " + else: + pstr += f"{name}={v}, " + method_py = f"iaa.{aug_info['category']}.{aug_info['name']}({pstr[:-2]})" + + res = method_py + if "sometimes" in aug_info: + res = f"iaa.Sometimes({aug_info['sometimes']}, {method_py})" + return res + + +def pipeline_to_python(aug_infos, random_order=False): + template = \ +"""import imgaug.augmenters as iaa +seq = iaa.Sequential([ +{} +], random_order={}) +""" + py_lines = [] + for info in aug_infos: + line = aug_to_python(info) + _validate = info["python"] + if line != _validate: + raise ValueError("Generated python line differs from the one from config: \n\n{!r}\n\n{!r}" + .format(line, _validate)) + py_lines.append(line) + res = template.format('\t' + ',\n\t'.join(py_lines), random_order) + return res + @PIPELINES.register_module() class SlyImgAugs(object): def __init__(self, config_path): diff --git a/train/src/ui/architectures.py b/train/src/ui/architectures.py index 0bc0d90..f3a7698 100644 --- a/train/src/ui/architectures.py +++ b/train/src/ui/architectures.py @@ -12,7 +12,7 @@ cfg = None def init(data, state): - state['pretrainedModel'] = 'Segformer' + state['pretrainedModel'] = 'ConvNeXt' data["pretrainedModels"], metrics = get_pretrained_models(return_metrics=True) model_select_info = [] for model_name, params in data["pretrainedModels"].items(): @@ -187,10 +187,10 @@ def download_weights(api: sly.Api, task_id, context, state, app_logger): cfg = Config.fromfile(g.model_config_local_path) if state["weightsInitialization"] != "custom": cfg.pretrained_model = state["pretrainedModel"] - # print(f'Config:\n{cfg.pretty_text}') + # print(f'Config:\n{cfg.pretty_text}') # TODO: debug params = init_dc.init_default_cfg_args(cfg) fields.extend(params) - if cfg.pretrained_model in ["CGNet", "DPT", "ERFNet", "HRNet", "MobileNetV3", "OCRNet", "PointRend", "Segformer", "SemanticFPN", "Twins"]: + if not hasattr(cfg.model, "auxiliary_head") or cfg.model.auxiliary_head is None: fields.extend([ {"field": "state.useAuxiliaryHead", "payload": False} ]) diff --git a/train/src/ui/augs.py b/train/src/ui/augs.py index 6e4d414..fa2c236 100644 --- a/train/src/ui/augs.py +++ b/train/src/ui/augs.py @@ -3,28 +3,33 @@ import sly_globals as g from supervisely.app.v1.widgets.compare_gallery import CompareGallery import input_project +from sly_imgaugs import build_pipeline, pipeline_to_python _templates = [ { - "config": "train/augs/seg_simple.json", - "name": "Only Color", + "config": "train/augs/light.json", + "name": "Light", }, { - "config": "train/augs/seg_simple_rotate.json", - "name": "Light: color + rotate", + "config": "train/augs/light_corrupt.json", + "name": "Light + corruption", }, { - "config": "train/augs/seg_simple_rotate_crop.json", - "name": "Medium: light + crop", + "config": "train/augs/medium.json", + "name": "Medium", }, { - "config": "train/augs/seg_simple_rotate_crop_flipLR.json", - "name": "Heavy: medium + flipLR", + "config": "train/augs/medium_corrupt.json", + "name": "Medium + corruption", }, { - "config": "train/augs/seg_simple_rotate_crop_flipLR_flipUD.json", - "name": "Heavy + flipUD", + "config": "train/augs/hard.json", + "name": "Heavy", + }, + { + "config": "train/augs/hard_corrupt.json", + "name": "Heavy + corruption", } ] @@ -36,13 +41,13 @@ augs_json_config = None augs_py_preview = None -augs_config_path = None +augs_config_path = os.path.join(g.my_app.data_dir, "augs_config.json") def _load_template(json_path): config = sly.json.load_json_file(json_path) - pipeline = sly.imgaug_utils.build_pipeline(config["pipeline"], random_order=config["random_order"]) # to validate - py_code = sly.imgaug_utils.pipeline_to_python(config["pipeline"], config["random_order"]) + pipeline = build_pipeline(config["pipeline"], random_order=config["random_order"]) # to validate + py_code = pipeline_to_python(config["pipeline"], config["random_order"]) return pipeline, py_code, config @@ -65,11 +70,7 @@ def get_template_by_name(name): for template in _templates: if template["name"] == name: json_path = os.path.join(g.root_source_dir, template["config"]) - pipeline, py_code, config = _load_template(json_path) - global augs_json_config, augs_py_preview - augs_json_config = config - augs_py_preview = py_code - return pipeline + return _load_template(json_path) raise KeyError(f"Template \"{name}\" not found") @@ -79,7 +80,11 @@ def init(data, state): templates_info, name_to_py = get_aug_templates_list() data["augTemplates"] = templates_info data["augPythonCode"] = name_to_py - state["augsTemplateName"] = templates_info[0]["name"] + state["augsTemplateName"] = templates_info[2]["name"] + _, py_code, config = get_template_by_name(state["augsTemplateName"]) + global augs_json_config, augs_py_preview + augs_json_config = config + augs_py_preview = py_code data["pyViewOptions"] = { "mode": 'ace/mode/python', @@ -89,7 +94,7 @@ def init(data, state): "highlightActiveLine": False } - state["customAugsPath"] = "" # "/mmclass-heavy-no-fliplr.json" # @TODO: for debug + state["customAugsPath"] = "" data["customAugsPy"] = None global gallery1, gallery2 @@ -132,7 +137,7 @@ def preview_augs(api: sly.Api, task_id, context, state, app_logger): if state["augsType"] == "template": gallery = gallery1 - augs_ppl = get_template_by_name(state["augsTemplateName"]) + augs_ppl, _, _ = get_template_by_name(state["augsTemplateName"]) else: gallery = gallery2 augs_ppl = custom_pipeline @@ -160,14 +165,11 @@ def use_augs(api: sly.Api, task_id, context, state, app_logger): global augs_py_preview if state["useAugs"]: - augs_config_path = os.path.join(g.my_app.data_dir, "augs_config.json") - if augs_json_config is None: - augs_json_config = sly.json.load_json_file(os.path.join(g.root_source_dir, _templates[0]["config"])) - sly.json.dump_json_file(augs_json_config, augs_config_path) - + _, py_code, config = get_template_by_name(state["augsTemplateName"]) + augs_json_config = config + augs_py_preview = py_code augs_py_path = os.path.join(g.my_app.data_dir, "augs_preview.py") - if augs_py_preview is None: - augs_py_preview = sly.imgaug_utils.pipeline_to_python(augs_json_config["pipeline"], augs_json_config["random_order"]) + sly.json.dump_json_file(augs_json_config, augs_config_path) with open(augs_py_path, 'w') as f: f.write(augs_py_preview) else: diff --git a/train/src/ui/hyperparameters.html b/train/src/ui/hyperparameters.html index 06a1369..7a9ad0f 100644 --- a/train/src/ui/hyperparameters.html +++ b/train/src/ui/hyperparameters.html @@ -6,7 +6,7 @@ ref="step6" > - + @@ -46,7 +46,7 @@
- +
@@ -90,7 +90,7 @@ - +
Choose optimizer and its settings, learn more in official @@ -142,7 +142,7 @@
- + @@ -211,7 +211,7 @@ - +
Choose LR scheduler and its settings, learn more in official diff --git a/train/src/ui/monitoring.py b/train/src/ui/monitoring.py index 4cec501..1b4fb38 100644 --- a/train/src/ui/monitoring.py +++ b/train/src/ui/monitoring.py @@ -197,7 +197,7 @@ def train(api: sly.Api, task_id, context, state, app_logger): prepare_segmentation_data(state, img_dir, ann_dir, palette) cfg = init_cfg(state, img_dir, ann_dir, classes, palette) - + # print(f'Config:\n{cfg.pretty_text}') # TODO: debug os.makedirs(os.path.join(g.checkpoints_dir, cfg.work_dir.split('/')[-1]), exist_ok=True) cfg.dump(os.path.join(g.checkpoints_dir, cfg.work_dir.split('/')[-1], "config.py")) From dfbc8c04256b74a4a5100f6de3d497fbdc039490 Mon Sep 17 00:00:00 2001 From: Arzamazov Nikita Date: Wed, 6 Apr 2022 07:57:08 +0000 Subject: [PATCH 3/4] upgrade docker image version --- serve/config.json | 2 +- train/config.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/serve/config.json b/serve/config.json index 24d1294..5a929db 100644 --- a/serve/config.json +++ b/serve/config.json @@ -7,7 +7,7 @@ "semantic segmentation" ], "description": "Deploy model as REST API service", - "docker_image": "supervisely/mmseg:1.1.0", + "docker_image": "supervisely/mmseg:1.2.0", "main_script": "serve/src/sly_serve.py", "gui_template": "serve/src/gui.html", "task_location": "application_sessions", diff --git a/train/config.json b/train/config.json index 44d786d..a95c179 100644 --- a/train/config.json +++ b/train/config.json @@ -7,7 +7,7 @@ "semantic segmentation" ], "description": "Dashboard to configure, start and monitor training", - "docker_image": "supervisely/mmseg:1.1.0", + "docker_image": "supervisely/mmseg:1.2.0", "main_script": "train/src/main.py", "gui_template": "train/src/gui.html", "task_location": "workspace_tasks", From dae490e1ac3daea5d65dbeb798019d670a3ec462 Mon Sep 17 00:00:00 2001 From: Arzamazov Nikita Date: Mon, 11 Apr 2022 16:18:44 +0000 Subject: [PATCH 4/4] use augs functions from sly lib --- requirements.txt | 2 - serve/README.md | 3 ++ serve/config.json | 2 +- train/README.md | 3 ++ train/config.json | 2 +- train/src/sly_imgaugs.py | 77 -------------------------------------- train/src/ui/augs.py | 5 +-- train/src/ui/monitoring.py | 1 - 8 files changed, 10 insertions(+), 85 deletions(-) delete mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 4a81f79..0000000 --- a/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -supervisely==6.7.21 -supervisely[apps]==6.7.21 diff --git a/serve/README.md b/serve/README.md index 663291a..39e4b4d 100644 --- a/serve/README.md +++ b/serve/README.md @@ -44,6 +44,8 @@ Supported backbones: - [x] [Vision Transformer (ICLR'2021)](https://github.com/open-mmlab/mmsegmentation/tree/master/configs/vit) - [x] [Swin Transformer (ICCV'2021)](https://github.com/open-mmlab/mmsegmentation/tree/master/configs/swin) - [x] [Twins (NeurIPS'2021)](https://github.com/open-mmlab/mmsegmentation/tree/master/configs/twins) +- [x] [BEiT (ICLR'2022)](https://github.com/open-mmlab/mmsegmentation/blob/master/configs/beit) +- [x] [ConvNeXt (CVPR'2022)](https://github.com/open-mmlab/mmsegmentation/blob/master/configs/convnext) Supported methods: @@ -80,6 +82,7 @@ Supported methods: - [x] [DPT (ArXiv'2021)](https://github.com/open-mmlab/mmsegmentation/tree/master/configs/dpt) - [x] [Segmenter (ICCV'2021)](https://github.com/open-mmlab/mmsegmentation/tree/master/configs/segmenter) - [x] [SegFormer (NeurIPS'2021)](https://github.com/open-mmlab/mmsegmentation/tree/master/configs/segformer) +- [x] [K-Net (NeurIPS'2021)](https://github.com/open-mmlab/mmsegmentation/blob/master/configs/knet) # How to Run diff --git a/serve/config.json b/serve/config.json index 5a929db..47edd88 100644 --- a/serve/config.json +++ b/serve/config.json @@ -7,7 +7,7 @@ "semantic segmentation" ], "description": "Deploy model as REST API service", - "docker_image": "supervisely/mmseg:1.2.0", + "docker_image": "supervisely/mmseg:1.3.0", "main_script": "serve/src/sly_serve.py", "gui_template": "serve/src/gui.html", "task_location": "application_sessions", diff --git a/train/README.md b/train/README.md index 1a9ba36..20a9f00 100644 --- a/train/README.md +++ b/train/README.md @@ -50,6 +50,8 @@ Supported backbones: - [x] [Vision Transformer (ICLR'2021)](https://github.com/open-mmlab/mmsegmentation/tree/master/configs/vit) - [x] [Swin Transformer (ICCV'2021)](https://github.com/open-mmlab/mmsegmentation/tree/master/configs/swin) - [x] [Twins (NeurIPS'2021)](https://github.com/open-mmlab/mmsegmentation/tree/master/configs/twins) +- [x] [BEiT (ICLR'2022)](https://github.com/open-mmlab/mmsegmentation/blob/master/configs/beit) +- [x] [ConvNeXt (CVPR'2022)](https://github.com/open-mmlab/mmsegmentation/blob/master/configs/convnext) Supported methods: @@ -86,6 +88,7 @@ Supported methods: - [x] [DPT (ArXiv'2021)](https://github.com/open-mmlab/mmsegmentation/tree/master/configs/dpt) - [x] [Segmenter (ICCV'2021)](https://github.com/open-mmlab/mmsegmentation/tree/master/configs/segmenter) - [x] [SegFormer (NeurIPS'2021)](https://github.com/open-mmlab/mmsegmentation/tree/master/configs/segformer) +- [x] [K-Net (NeurIPS'2021)](https://github.com/open-mmlab/mmsegmentation/blob/master/configs/knet) # How to Run diff --git a/train/config.json b/train/config.json index a95c179..030474b 100644 --- a/train/config.json +++ b/train/config.json @@ -7,7 +7,7 @@ "semantic segmentation" ], "description": "Dashboard to configure, start and monitor training", - "docker_image": "supervisely/mmseg:1.2.0", + "docker_image": "supervisely/mmseg:1.3.0", "main_script": "train/src/main.py", "gui_template": "train/src/gui.html", "task_location": "workspace_tasks", diff --git a/train/src/sly_imgaugs.py b/train/src/sly_imgaugs.py index d41ae65..4cff9ad 100644 --- a/train/src/sly_imgaugs.py +++ b/train/src/sly_imgaugs.py @@ -1,84 +1,7 @@ import supervisely as sly from mmseg.datasets.builder import PIPELINES -from supervisely.sly_logger import logger -import imgaug.augmenters as iaa -def get_function(category_name, aug_name): - try: - submodule = getattr(iaa, category_name) - aug_f = getattr(submodule, aug_name) - return aug_f - except Exception as e: - logger.error(repr(e)) - # raise e - return None - -def build_pipeline(aug_infos, random_order=False): - pipeline = [] - for aug_info in aug_infos: - category_name = aug_info["category"] - aug_name = aug_info["name"] - params = aug_info["params"] - for param_name, param_val in params.items(): - if isinstance(param_val, dict): - if "x" in param_val.keys() and "y" in param_val.keys(): - param_val["x"] = tuple(param_val["x"]) - param_val["y"] = tuple(param_val["y"]) - elif isinstance(param_val, list): - params[param_name] = tuple(param_val) - - aug_func = get_function(category_name, aug_name) - - aug = aug_func(**params) - - sometimes = aug_info.get("sometimes", None) - if sometimes is not None: - aug = iaa.meta.Sometimes(sometimes, aug) - pipeline.append(aug) - augs = iaa.Sequential(pipeline, random_order=random_order) - return augs - - -def aug_to_python(aug_info): - pstr = "" - for name, value in aug_info["params"].items(): - v = value - if type(v) is list: #name != 'nb_iterations' and - v = (v[0], v[1]) - elif type(v) is dict and "x" in v.keys() and "y" in v.keys(): - v = {"x": (v["x"][0], v["x"][1]), "y": (v["y"][0], v["y"][1])} - - if type(value) is str: - pstr += f"{name}='{v}', " - else: - pstr += f"{name}={v}, " - method_py = f"iaa.{aug_info['category']}.{aug_info['name']}({pstr[:-2]})" - - res = method_py - if "sometimes" in aug_info: - res = f"iaa.Sometimes({aug_info['sometimes']}, {method_py})" - return res - - -def pipeline_to_python(aug_infos, random_order=False): - template = \ -"""import imgaug.augmenters as iaa -seq = iaa.Sequential([ -{} -], random_order={}) -""" - py_lines = [] - for info in aug_infos: - line = aug_to_python(info) - _validate = info["python"] - if line != _validate: - raise ValueError("Generated python line differs from the one from config: \n\n{!r}\n\n{!r}" - .format(line, _validate)) - py_lines.append(line) - res = template.format('\t' + ',\n\t'.join(py_lines), random_order) - return res - @PIPELINES.register_module() class SlyImgAugs(object): def __init__(self, config_path): diff --git a/train/src/ui/augs.py b/train/src/ui/augs.py index fa2c236..1bc5b87 100644 --- a/train/src/ui/augs.py +++ b/train/src/ui/augs.py @@ -3,7 +3,6 @@ import sly_globals as g from supervisely.app.v1.widgets.compare_gallery import CompareGallery import input_project -from sly_imgaugs import build_pipeline, pipeline_to_python _templates = [ @@ -46,8 +45,8 @@ def _load_template(json_path): config = sly.json.load_json_file(json_path) - pipeline = build_pipeline(config["pipeline"], random_order=config["random_order"]) # to validate - py_code = pipeline_to_python(config["pipeline"], config["random_order"]) + pipeline = sly.imgaug_utils.build_pipeline(config["pipeline"], random_order=config["random_order"]) # to validate + py_code = sly.imgaug_utils.pipeline_to_python(config["pipeline"], config["random_order"]) return pipeline, py_code, config diff --git a/train/src/ui/monitoring.py b/train/src/ui/monitoring.py index 1b4fb38..cb540b1 100644 --- a/train/src/ui/monitoring.py +++ b/train/src/ui/monitoring.py @@ -171,7 +171,6 @@ def prepare_segmentation_data(state, img_dir, ann_dir, palette): shutil.move(os.path.join(temp_project_seg_dir, dataset, img_dir, filename), os.path.join(g.project_seg_dir, img_dir)) - shutil.rmtree(g.project_dir) shutil.rmtree(temp_project_seg_dir) g.api.app.set_field(g.task_id, "state.preparingData", False)