diff --git a/conf/chesapeake_cvpr.yaml b/conf/chesapeake_cvpr.yaml index 40c7412b028..00c5e3a05b7 100644 --- a/conf/chesapeake_cvpr.yaml +++ b/conf/chesapeake_cvpr.yaml @@ -8,10 +8,9 @@ experiment: name: "chesapeake_cvpr_example" module: loss: "ce" - segmentation_model: "unet" - encoder_name: "resnet18" - encoder_weights: null - encoder_output_stride: 16 + model: "unet" + backbone: "resnet18" + weights: null learning_rate: 1e-3 learning_rate_schedule_patience: 6 in_channels: 4 diff --git a/conf/etci2021.yaml b/conf/etci2021.yaml index a8e8a319f8a..c6e02005d10 100644 --- a/conf/etci2021.yaml +++ b/conf/etci2021.yaml @@ -2,9 +2,9 @@ experiment: task: "etci2021" module: loss: "ce" - segmentation_model: "unet" - encoder_name: "resnet18" - encoder_weights: "imagenet" + model: "unet" + backbone: "resnet18" + weights: "imagenet" learning_rate: 1e-3 learning_rate_schedule_patience: 6 in_channels: 6 diff --git a/conf/inria.yaml b/conf/inria.yaml index dacc83dbeca..462c873fda6 100644 --- a/conf/inria.yaml +++ b/conf/inria.yaml @@ -14,9 +14,9 @@ experiment: name: "inria_test" module: loss: "ce" - segmentation_model: "unet" - encoder_name: "resnet18" - encoder_weights: "imagenet" + model: "unet" + backbone: "resnet18" + weights: "imagenet" learning_rate: 1e-3 learning_rate_schedule_patience: 6 in_channels: 3 diff --git a/conf/landcoverai.yaml b/conf/landcoverai.yaml index 4bb37e73973..98648408028 100644 --- a/conf/landcoverai.yaml +++ b/conf/landcoverai.yaml @@ -7,9 +7,9 @@ experiment: task: "landcoverai" module: loss: "ce" - segmentation_model: "unet" - encoder_name: "resnet18" - encoder_weights: "imagenet" + model: "unet" + backbone: "resnet18" + weights: "imagenet" learning_rate: 1e-3 learning_rate_schedule_patience: 6 in_channels: 3 diff --git a/conf/naipchesapeake.yaml b/conf/naipchesapeake.yaml index 99ba7e8ecb0..709224eca9d 100644 --- a/conf/naipchesapeake.yaml +++ b/conf/naipchesapeake.yaml @@ -7,10 +7,9 @@ experiment: task: "naipchesapeake" module: loss: "ce" - segmentation_model: "deeplabv3+" - encoder_name: "resnet34" - encoder_weights: "imagenet" - encoder_output_stride: 16 + model: "deeplabv3+" + backbone: "resnet34" + weights: "imagenet" learning_rate: 1e-3 learning_rate_schedule_patience: 2 in_channels: 4 diff --git a/conf/oscd.yaml b/conf/oscd.yaml index 4a516fb9f3b..486dbb9b64b 100644 --- a/conf/oscd.yaml +++ b/conf/oscd.yaml @@ -7,9 +7,9 @@ experiment: task: "oscd" module: loss: "jaccard" - segmentation_model: "unet" - encoder_name: "resnet18" - encoder_weights: null + model: "unet" + backbone: "resnet18" + weights: null learning_rate: 1e-3 learning_rate_schedule_patience: 6 verbose: false diff --git a/conf/sen12ms.yaml b/conf/sen12ms.yaml index 02954dd8e71..1dba884add1 100644 --- a/conf/sen12ms.yaml +++ b/conf/sen12ms.yaml @@ -7,10 +7,9 @@ experiment: task: "sen12ms" module: loss: "ce" - segmentation_model: "unet" - encoder_name: "resnet18" - encoder_weights: null - encoder_output_stride: 16 + model: "unet" + backbone: "resnet18" + weights: null learning_rate: 1e-3 learning_rate_schedule_patience: 2 in_channels: 15 diff --git a/evaluate.py b/evaluate.py index a65dd5d2431..9e9962667ed 100755 --- a/evaluate.py +++ b/evaluate.py @@ -176,18 +176,18 @@ def main(args: argparse.Namespace) -> None: elif issubclass(TASK, SemanticSegmentationTask): val_row = { "split": "val", - "segmentation_model": hparams["segmentation_model"], - "encoder_name": hparams["encoder_name"], - "encoder_weights": hparams["encoder_weights"], + "model": hparams["model"], + "backbone": hparams["backbone"], + "weights": hparams["weights"], "learning_rate": hparams["learning_rate"], "loss": hparams["loss"], } test_row = { "split": "test", - "segmentation_model": hparams["segmentation_model"], - "encoder_name": hparams["encoder_name"], - "encoder_weights": hparams["encoder_weights"], + "model": hparams["model"], + "backbone": hparams["backbone"], + "weights": hparams["weights"], "learning_rate": hparams["learning_rate"], "loss": hparams["loss"], } diff --git a/experiments/run_chesapeake_cvpr_experiments.py b/experiments/run_chesapeake_cvpr_experiments.py index 37c1366bce0..f1f002947c4 100755 --- a/experiments/run_chesapeake_cvpr_experiments.py +++ b/experiments/run_chesapeake_cvpr_experiments.py @@ -16,7 +16,7 @@ # Hyperparameter options training_set_options = ["de"] model_options = ["unet"] -encoder_options = ["resnet18", "resnet50"] +backbone_options = ["resnet18", "resnet50"] lr_options = [1e-2, 1e-3, 1e-4] loss_options = ["ce", "jaccard"] weight_init_options = ["null", "imagenet"] @@ -36,16 +36,16 @@ def do_work(work: "Queue[str]", gpu_idx: int) -> bool: if __name__ == "__main__": work: "Queue[str]" = Queue() - for (train_state, model, encoder, lr, loss, weight_init) in itertools.product( + for (train_state, model, backbone, lr, loss, weight_init) in itertools.product( training_set_options, model_options, - encoder_options, + backbone_options, lr_options, loss_options, weight_init_options, ): - experiment_name = f"{train_state}_{model}_{encoder}_{lr}_{loss}_{weight_init}" + experiment_name = f"{train_state}_{model}_{backbone}_{lr}_{loss}_{weight_init}" output_dir = os.path.join("output", "chesapeake-cvpr_experiments") log_dir = os.path.join(output_dir, "logs") @@ -57,9 +57,9 @@ def do_work(work: "Queue[str]", gpu_idx: int) -> bool: "python train.py" + f" config_file={config_file}" + f" experiment.name={experiment_name}" - + f" experiment.module.segmentation_model={model}" - + f" experiment.module.encoder_name={encoder}" - + f" experiment.module.encoder_weights={weight_init}" + + f" experiment.module.model={model}" + + f" experiment.module.backbone={backbone}" + + f" experiment.module.weights={weight_init}" + f" experiment.module.learning_rate={lr}" + f" experiment.module.loss={loss}" + " experiment.module.class_set=7" diff --git a/experiments/run_landcoverai_experiments.py b/experiments/run_landcoverai_experiments.py index b5321970382..d64e22cb578 100755 --- a/experiments/run_landcoverai_experiments.py +++ b/experiments/run_landcoverai_experiments.py @@ -15,7 +15,7 @@ # Hyperparameter options model_options = ["unet"] -encoder_options = ["resnet18", "resnet50"] +backbone_options = ["resnet18", "resnet50"] lr_options = [1e-2, 1e-3, 1e-4] loss_options = ["ce", "jaccard"] weight_init_options = ["null", "imagenet"] @@ -35,11 +35,11 @@ def do_work(work: "Queue[str]", gpu_idx: int) -> bool: if __name__ == "__main__": work: "Queue[str]" = Queue() - for (model, encoder, lr, loss, weight_init) in itertools.product( - model_options, encoder_options, lr_options, loss_options, weight_init_options + for (model, backbone, lr, loss, weight_init) in itertools.product( + model_options, backbone_options, lr_options, loss_options, weight_init_options ): - experiment_name = f"{model}_{encoder}_{lr}_{loss}_{weight_init}" + experiment_name = f"{model}_{backbone}_{lr}_{loss}_{weight_init}" output_dir = os.path.join("output", "landcoverai_experiments") log_dir = os.path.join(output_dir, "logs") @@ -54,8 +54,8 @@ def do_work(work: "Queue[str]", gpu_idx: int) -> bool: + f" experiment.module.segmentation_model={model}" + f" experiment.module.learning_rate={lr}" + f" experiment.module.loss={loss}" - + f" experiment.module.encoder_name={encoder}" - + f" experiment.module.encoder_weights={weight_init}" + + f" experiment.module.backbone={backbone}" + + f" experiment.module.weights={weight_init}" + f" program.output_dir={output_dir}" + f" program.log_dir={log_dir}" + f" program.data_dir={DATA_DIR}" diff --git a/experiments/run_landcoverai_seed_experiments.py b/experiments/run_landcoverai_seed_experiments.py index b5321970382..a63ee6efbf8 100755 --- a/experiments/run_landcoverai_seed_experiments.py +++ b/experiments/run_landcoverai_seed_experiments.py @@ -15,7 +15,7 @@ # Hyperparameter options model_options = ["unet"] -encoder_options = ["resnet18", "resnet50"] +backbone_options = ["resnet18", "resnet50"] lr_options = [1e-2, 1e-3, 1e-4] loss_options = ["ce", "jaccard"] weight_init_options = ["null", "imagenet"] @@ -35,11 +35,11 @@ def do_work(work: "Queue[str]", gpu_idx: int) -> bool: if __name__ == "__main__": work: "Queue[str]" = Queue() - for (model, encoder, lr, loss, weight_init) in itertools.product( - model_options, encoder_options, lr_options, loss_options, weight_init_options + for (model, backbone, lr, loss, weight_init) in itertools.product( + model_options, backbone_options, lr_options, loss_options, weight_init_options ): - experiment_name = f"{model}_{encoder}_{lr}_{loss}_{weight_init}" + experiment_name = f"{model}_{backbone}_{lr}_{loss}_{weight_init}" output_dir = os.path.join("output", "landcoverai_experiments") log_dir = os.path.join(output_dir, "logs") @@ -51,11 +51,11 @@ def do_work(work: "Queue[str]", gpu_idx: int) -> bool: "python train.py" + f" config_file={config_file}" + f" experiment.name={experiment_name}" - + f" experiment.module.segmentation_model={model}" + + f" experiment.module.model={model}" + f" experiment.module.learning_rate={lr}" + f" experiment.module.loss={loss}" - + f" experiment.module.encoder_name={encoder}" - + f" experiment.module.encoder_weights={weight_init}" + + f" experiment.module.backbone={backbone}" + + f" experiment.module.weights={weight_init}" + f" program.output_dir={output_dir}" + f" program.log_dir={log_dir}" + f" program.data_dir={DATA_DIR}" diff --git a/tests/conf/chesapeake_cvpr_5.yaml b/tests/conf/chesapeake_cvpr_5.yaml index 1e3fb6ab9e9..5d9a18c9b65 100644 --- a/tests/conf/chesapeake_cvpr_5.yaml +++ b/tests/conf/chesapeake_cvpr_5.yaml @@ -2,10 +2,9 @@ experiment: task: "chesapeake_cvpr" module: loss: "ce" - segmentation_model: "unet" - encoder_name: "resnet50" - encoder_weights: null - encoder_output_stride: 16 + model: "unet" + backbone: "resnet50" + weights: null learning_rate: 1e-3 learning_rate_schedule_patience: 6 in_channels: 4 diff --git a/tests/conf/chesapeake_cvpr_7.yaml b/tests/conf/chesapeake_cvpr_7.yaml index a9ef7166ef7..88a032fa294 100644 --- a/tests/conf/chesapeake_cvpr_7.yaml +++ b/tests/conf/chesapeake_cvpr_7.yaml @@ -2,7 +2,7 @@ experiment: task: "chesapeake_cvpr" module: loss: "ce" - segmentation_model: "unet" + model: "unet" encoder_name: "resnet18" encoder_weights: null encoder_output_stride: 16 diff --git a/tests/conf/chesapeake_cvpr_prior.yaml b/tests/conf/chesapeake_cvpr_prior.yaml index 890ed9365e5..d8d85bc0d89 100644 --- a/tests/conf/chesapeake_cvpr_prior.yaml +++ b/tests/conf/chesapeake_cvpr_prior.yaml @@ -2,7 +2,7 @@ experiment: task: "chesapeake_cvpr" module: loss: "ce" - segmentation_model: "unet" + model: "unet" encoder_name: "resnet50" encoder_weights: null encoder_output_stride: 16 diff --git a/tests/conf/deepglobelandcover_0.yaml b/tests/conf/deepglobelandcover_0.yaml index 3867e1cc13b..a835df8995d 100644 --- a/tests/conf/deepglobelandcover_0.yaml +++ b/tests/conf/deepglobelandcover_0.yaml @@ -2,9 +2,9 @@ experiment: task: "deepglobelandcover" module: loss: "ce" - segmentation_model: "unet" - encoder_name: "resnet18" - encoder_weights: null + model: "unet" + backbone: "resnet18" + weights: null learning_rate: 1e-3 learning_rate_schedule_patience: 6 verbose: false diff --git a/tests/conf/deepglobelandcover_5.yaml b/tests/conf/deepglobelandcover_5.yaml index 74fa1a0542b..b3262962bd0 100644 --- a/tests/conf/deepglobelandcover_5.yaml +++ b/tests/conf/deepglobelandcover_5.yaml @@ -2,9 +2,9 @@ experiment: task: "deepglobelandcover" module: loss: "ce" - segmentation_model: "unet" - encoder_name: "resnet18" - encoder_weights: null + model: "unet" + backbone: "resnet18" + weights: null learning_rate: 1e-3 learning_rate_schedule_patience: 6 verbose: false diff --git a/tests/conf/etci2021.yaml b/tests/conf/etci2021.yaml index 364d6b16232..73fde1dfb87 100644 --- a/tests/conf/etci2021.yaml +++ b/tests/conf/etci2021.yaml @@ -2,9 +2,9 @@ experiment: task: "etci2021" module: loss: "ce" - segmentation_model: "unet" - encoder_name: "resnet18" - encoder_weights: null + model: "unet" + backbone: "resnet18" + weights: null learning_rate: 1e-3 learning_rate_schedule_patience: 6 in_channels: 6 diff --git a/tests/conf/inria.yaml b/tests/conf/inria.yaml index dc9e7994e02..6bc4b5bd7cc 100644 --- a/tests/conf/inria.yaml +++ b/tests/conf/inria.yaml @@ -2,9 +2,9 @@ experiment: task: "inria" module: loss: "ce" - segmentation_model: "unet" - encoder_name: "resnet18" - encoder_weights: "imagenet" + model: "unet" + backbone: "resnet18" + weights: "imagenet" learning_rate: 1e-3 learning_rate_schedule_patience: 6 in_channels: 3 diff --git a/tests/conf/landcoverai.yaml b/tests/conf/landcoverai.yaml index 357e573f39d..04ae4a33030 100644 --- a/tests/conf/landcoverai.yaml +++ b/tests/conf/landcoverai.yaml @@ -2,9 +2,9 @@ experiment: task: "landcoverai" module: loss: "ce" - segmentation_model: "unet" - encoder_name: "resnet18" - encoder_weights: null + model: "unet" + backbone: "resnet18" + weights: null learning_rate: 1e-3 learning_rate_schedule_patience: 6 verbose: false diff --git a/tests/conf/naipchesapeake.yaml b/tests/conf/naipchesapeake.yaml index 8ba07cbee13..b2d43c44f45 100644 --- a/tests/conf/naipchesapeake.yaml +++ b/tests/conf/naipchesapeake.yaml @@ -2,10 +2,9 @@ experiment: task: "naipchesapeake" module: loss: "ce" - segmentation_model: "deeplabv3+" - encoder_name: "resnet34" - encoder_weights: null - encoder_output_stride: 16 + model: "deeplabv3+" + backbone: "resnet34" + weights: null learning_rate: 1e-3 learning_rate_schedule_patience: 2 in_channels: 4 diff --git a/tests/conf/oscd_all.yaml b/tests/conf/oscd_all.yaml index 24a9a032e73..34857595cd4 100644 --- a/tests/conf/oscd_all.yaml +++ b/tests/conf/oscd_all.yaml @@ -2,9 +2,9 @@ experiment: task: "oscd" module: loss: "jaccard" - segmentation_model: "unet" - encoder_name: "resnet18" - encoder_weights: null + model: "unet" + backbone: "resnet18" + weights: null learning_rate: 1e-3 learning_rate_schedule_patience: 6 verbose: false diff --git a/tests/conf/oscd_rgb.yaml b/tests/conf/oscd_rgb.yaml index 735b3dbba99..ede707145b8 100644 --- a/tests/conf/oscd_rgb.yaml +++ b/tests/conf/oscd_rgb.yaml @@ -2,9 +2,9 @@ experiment: task: "oscd" module: loss: "jaccard" - segmentation_model: "unet" - encoder_name: "resnet18" - encoder_weights: null + model: "unet" + backbone: "resnet18" + weights: null learning_rate: 1e-3 learning_rate_schedule_patience: 6 verbose: false diff --git a/tests/conf/sen12ms_all.yaml b/tests/conf/sen12ms_all.yaml index 0a6b3b7ceea..ecf01b3bc72 100644 --- a/tests/conf/sen12ms_all.yaml +++ b/tests/conf/sen12ms_all.yaml @@ -2,10 +2,9 @@ experiment: task: "sen12ms" module: loss: "ce" - segmentation_model: "unet" - encoder_name: "resnet18" - encoder_weights: null - encoder_output_stride: 16 + model: "unet" + backbone: "resnet18" + weights: null learning_rate: 1e-3 learning_rate_schedule_patience: 2 in_channels: 15 diff --git a/tests/conf/sen12ms_s1.yaml b/tests/conf/sen12ms_s1.yaml index 0b74bcaa1de..a5a4f083d9c 100644 --- a/tests/conf/sen12ms_s1.yaml +++ b/tests/conf/sen12ms_s1.yaml @@ -2,11 +2,10 @@ experiment: task: "sen12ms" module: loss: "focal" - segmentation_model: "fcn" + model: "fcn" num_filters: 1 - encoder_name: "resnet18" - encoder_weights: null - encoder_output_stride: 16 + backbone: "resnet18" + weights: null learning_rate: 1e-3 learning_rate_schedule_patience: 2 in_channels: 2 diff --git a/tests/conf/sen12ms_s2_all.yaml b/tests/conf/sen12ms_s2_all.yaml index b46b1e6c92d..dafe781db89 100644 --- a/tests/conf/sen12ms_s2_all.yaml +++ b/tests/conf/sen12ms_s2_all.yaml @@ -2,10 +2,9 @@ experiment: task: "sen12ms" module: loss: "ce" - segmentation_model: "unet" - encoder_name: "resnet18" - encoder_weights: null - encoder_output_stride: 16 + model: "unet" + backbone: "resnet18" + weights: null learning_rate: 1e-3 learning_rate_schedule_patience: 2 in_channels: 13 diff --git a/tests/conf/sen12ms_s2_reduced.yaml b/tests/conf/sen12ms_s2_reduced.yaml index 647beadd945..9891c4b44ef 100644 --- a/tests/conf/sen12ms_s2_reduced.yaml +++ b/tests/conf/sen12ms_s2_reduced.yaml @@ -2,10 +2,9 @@ experiment: task: "sen12ms" module: loss: "ce" - segmentation_model: "unet" - encoder_name: "resnet18" - encoder_weights: null - encoder_output_stride: 16 + model: "unet" + backbone: "resnet18" + weights: null learning_rate: 1e-3 learning_rate_schedule_patience: 2 in_channels: 6 diff --git a/tests/trainers/test_segmentation.py b/tests/trainers/test_segmentation.py index 90c0a1e9ccd..c7f92259e2c 100644 --- a/tests/trainers/test_segmentation.py +++ b/tests/trainers/test_segmentation.py @@ -102,9 +102,9 @@ def test_no_logger(self) -> None: @pytest.fixture def model_kwargs(self) -> Dict[Any, Any]: return { - "segmentation_model": "unet", - "encoder_name": "resnet18", - "encoder_weights": None, + "model": "unet", + "backbone": "resnet18", + "weights": None, "in_channels": 3, "num_classes": 6, "loss": "ce", @@ -112,7 +112,7 @@ def model_kwargs(self) -> Dict[Any, Any]: } def test_invalid_model(self, model_kwargs: Dict[Any, Any]) -> None: - model_kwargs["segmentation_model"] = "invalid_model" + model_kwargs["model"] = "invalid_model" match = "Model type 'invalid_model' is not valid." with pytest.raises(ValueError, match=match): SemanticSegmentationTask(**model_kwargs) diff --git a/torchgeo/trainers/segmentation.py b/torchgeo/trainers/segmentation.py index fa025ad995d..f711aab7bd6 100644 --- a/torchgeo/trainers/segmentation.py +++ b/torchgeo/trainers/segmentation.py @@ -31,26 +31,26 @@ class SemanticSegmentationTask(pl.LightningModule): Supports `Segmentation Models Pytorch `_ as an architecture choice in combination with any of these - `TIMM encoders `_. + `TIMM backbones `_. """ def config_task(self) -> None: """Configures the task based on kwargs parameters passed to the constructor.""" - if self.hyperparams["segmentation_model"] == "unet": + if self.hyperparams["model"] == "unet": self.model = smp.Unet( - encoder_name=self.hyperparams["encoder_name"], - encoder_weights=self.hyperparams["encoder_weights"], + encoder_name=self.hyperparams["backbone"], + encoder_weights=self.hyperparams["weights"], in_channels=self.hyperparams["in_channels"], classes=self.hyperparams["num_classes"], ) - elif self.hyperparams["segmentation_model"] == "deeplabv3+": + elif self.hyperparams["model"] == "deeplabv3+": self.model = smp.DeepLabV3Plus( - encoder_name=self.hyperparams["encoder_name"], - encoder_weights=self.hyperparams["encoder_weights"], + encoder_name=self.hyperparams["backbone"], + encoder_weights=self.hyperparams["weights"], in_channels=self.hyperparams["in_channels"], classes=self.hyperparams["num_classes"], ) - elif self.hyperparams["segmentation_model"] == "fcn": + elif self.hyperparams["model"] == "fcn": self.model = FCN( in_channels=self.hyperparams["in_channels"], classes=self.hyperparams["num_classes"], @@ -58,7 +58,7 @@ def config_task(self) -> None: ) else: raise ValueError( - f"Model type '{self.hyperparams['segmentation_model']}' is not valid. " + f"Model type '{self.hyperparams['model']}' is not valid. " f"Currently, only supports 'unet', 'deeplabv3+' and 'fcn'." ) @@ -83,13 +83,14 @@ def __init__(self, **kwargs: Any) -> None: """Initialize the LightningModule with a model and loss function. Keyword Args: - segmentation_model: Name of the segmentation model type to use - encoder_name: Name of the encoder model backbone to use - encoder_weights: None or "imagenet" to use imagenet pretrained weights in - the encoder model + model: Name of the segmentation model type to use + backbone: Name of the timm backbone to use + weights: None or "imagenet" to use imagenet pretrained weights in + the backbone in_channels: Number of channels in input image num_classes: Number of semantic classes to predict - loss: Name of the loss function + loss: Name of the loss function, currently supports + 'ce', 'jaccard' or 'focal' loss ignore_index: Optional integer class index to ignore in the loss and metrics learning_rate: Learning rate for optimizer learning_rate_schedule_patience: Patience for learning rate scheduler @@ -99,6 +100,11 @@ def __init__(self, **kwargs: Any) -> None: .. versionchanged:: 0.3 The *ignore_zeros* parameter was renamed to *ignore_index*. + + .. versionchanged:: 0.4 + The *segmentation_model* parameter was renamed to *model*, + *encoder_name* renamed to *backbone*, and + *encoder_weights* to *weights*. """ super().__init__()