diff --git a/configs/vision/dino_vit/offline/camelyon16.yaml b/configs/vision/dino_vit/offline/camelyon16.yaml index 90a1bf9b..29a55c1d 100644 --- a/configs/vision/dino_vit/offline/camelyon16.yaml +++ b/configs/vision/dino_vit/offline/camelyon16.yaml @@ -2,9 +2,9 @@ trainer: class_path: eva.Trainer init_args: - n_runs: &N_RUNS ${oc.env:N_RUNS, 3} - default_root_dir: &OUTPUT_ROOT ${oc.env:OUTPUT_ROOT, logs/${oc.env:DINO_BACKBONE, owkin/phikon}/offline/camelyon16} - max_steps: &MAX_STEPS ${oc.env:MAX_STEPS, 12500} + n_runs: &N_RUNS ${oc.env:N_RUNS, 5} + default_root_dir: &OUTPUT_ROOT ${oc.env:OUTPUT_ROOT, logs/${oc.env:DINO_BACKBONE, dino_vits16}/offline/camelyon16} + max_epochs: &MAX_EPOCHS ${oc.env:MAX_EPOCHS, 100} callbacks: - class_path: lightning.pytorch.callbacks.LearningRateMonitor init_args: @@ -19,12 +19,12 @@ trainer: - class_path: lightning.pytorch.callbacks.EarlyStopping init_args: min_delta: 0 - patience: 74 + patience: ${oc.env:PATIENCE, 10} monitor: *MONITOR_METRIC mode: *MONITOR_METRIC_MODE - class_path: eva.callbacks.EmbeddingsWriter init_args: - output_dir: &DATASET_EMBEDDINGS_ROOT ${oc.env:EMBEDDINGS_ROOT, ./data/embeddings}/${oc.env:DINO_BACKBONE, dino_vits16}/camelyon16 + output_dir: &DATASET_EMBEDDINGS_ROOT ${oc.env:EMBEDDINGS_ROOT, ./data/embeddings/${oc.env:DINO_BACKBONE, dino_vits16}/camelyon16} dataloader_idx_map: 0: train 1: val @@ -51,19 +51,19 @@ model: head: class_path: eva.vision.models.networks.ABMIL init_args: - input_size: ${oc.env:IN_FEATURES, 768} + input_size: ${oc.env:IN_FEATURES, 384} output_size: &NUM_CLASSES 1 projected_input_size: 128 criterion: torch.nn.BCEWithLogitsLoss optimizer: class_path: torch.optim.AdamW init_args: - lr: &LR_VALUE 0.000039 + lr: ${oc.env:LR_VALUE, 0.001} betas: [0.9, 0.999] lr_scheduler: class_path: torch.optim.lr_scheduler.CosineAnnealingLR init_args: - T_max: *MAX_STEPS + T_max: *MAX_EPOCHS eta_min: 0.0 metrics: common: @@ -123,7 +123,7 @@ data: split: test dataloaders: train: - batch_size: &BATCH_SIZE ${oc.env:BATCH_SIZE, 16} + batch_size: &BATCH_SIZE ${oc.env:BATCH_SIZE, 32} shuffle: true val: batch_size: *BATCH_SIZE @@ -131,5 +131,3 @@ data: batch_size: *BATCH_SIZE predict: batch_size: &PREDICT_BATCH_SIZE ${oc.env:PREDICT_BATCH_SIZE, 64} - num_workers: 12 #multiprocessing.cpu_count - prefetch_factor: 2 diff --git a/configs/vision/dino_vit/offline/panda.yaml b/configs/vision/dino_vit/offline/panda.yaml index 8977a7f1..600bfb12 100644 --- a/configs/vision/dino_vit/offline/panda.yaml +++ b/configs/vision/dino_vit/offline/panda.yaml @@ -2,9 +2,9 @@ trainer: class_path: eva.Trainer init_args: - n_runs: &N_RUNS ${oc.env:N_RUNS, 1} + n_runs: &N_RUNS ${oc.env:N_RUNS, 5} default_root_dir: &OUTPUT_ROOT ${oc.env:OUTPUT_ROOT, logs/${oc.env:DINO_BACKBONE, dino_vits16}/offline/panda} - max_steps: &MAX_STEPS ${oc.env:MAX_STEPS, 12500} + max_epochs: &MAX_EPOCHS ${oc.env:MAX_EPOCHS, 49} callbacks: - class_path: lightning.pytorch.callbacks.LearningRateMonitor init_args: @@ -19,12 +19,12 @@ trainer: - class_path: lightning.pytorch.callbacks.EarlyStopping init_args: min_delta: 0 - patience: 13 + patience: ${oc.env:PATIENCE, 8} monitor: *MONITOR_METRIC mode: *MONITOR_METRIC_MODE - class_path: eva.callbacks.EmbeddingsWriter init_args: - output_dir: &DATASET_EMBEDDINGS_ROOT ${oc.env:EMBEDDINGS_ROOT, ./data/embeddings}/${oc.env:DINO_BACKBONE, dino_vits16}/panda + output_dir: &DATASET_EMBEDDINGS_ROOT ${oc.env:EMBEDDINGS_ROOT, ./data/embeddings/${oc.env:DINO_BACKBONE, dino_vits16}/panda} dataloader_idx_map: 0: train 1: val @@ -53,17 +53,17 @@ model: init_args: input_size: ${oc.env:IN_FEATURES, 384} output_size: &NUM_CLASSES 6 + projected_input_size: 128 criterion: torch.nn.CrossEntropyLoss optimizer: - class_path: torch.optim.SGD + class_path: torch.optim.AdamW init_args: - lr: &LR_VALUE ${oc.env:LR_VALUE, 0.00004} - momentum: 0.9 - weight_decay: 0.0 + lr: ${oc.env:LR_VALUE, 0.001} + betas: [0.9, 0.999] lr_scheduler: class_path: torch.optim.lr_scheduler.CosineAnnealingLR init_args: - T_max: *MAX_STEPS + T_max: *MAX_EPOCHS eta_min: 0.0 metrics: common: @@ -123,11 +123,11 @@ data: split: test dataloaders: train: - batch_size: &BATCH_SIZE ${oc.env:BATCH_SIZE, 16} + batch_size: &BATCH_SIZE ${oc.env:BATCH_SIZE, 32} shuffle: true val: batch_size: *BATCH_SIZE + test: + batch_size: *BATCH_SIZE predict: batch_size: &PREDICT_BATCH_SIZE ${oc.env:PREDICT_BATCH_SIZE, 64} - num_workers: 12 #multiprocessing.cpu_count - prefetch_factor: 2 diff --git a/configs/vision/owkin/phikon/offline/camelyon16.yaml b/configs/vision/owkin/phikon/offline/camelyon16.yaml new file mode 100644 index 00000000..f7aca73f --- /dev/null +++ b/configs/vision/owkin/phikon/offline/camelyon16.yaml @@ -0,0 +1,129 @@ +--- +trainer: + class_path: eva.Trainer + init_args: + n_runs: &N_RUNS ${oc.env:N_RUNS, 5} + default_root_dir: &OUTPUT_ROOT ${oc.env:OUTPUT_ROOT, logs/owkin/phikon/offline/camelyon16} + max_epochs: &MAX_EPOCHS ${oc.env:MAX_EPOCHS, 100} + callbacks: + - class_path: lightning.pytorch.callbacks.LearningRateMonitor + init_args: + logging_interval: epoch + - class_path: lightning.pytorch.callbacks.ModelCheckpoint + init_args: + filename: best + save_last: true + save_top_k: 1 + monitor: &MONITOR_METRIC ${oc.env:MONITOR_METRIC, val/BinaryAccuracy} + mode: &MONITOR_METRIC_MODE ${oc.env:MONITOR_METRIC_MODE, max} + - class_path: lightning.pytorch.callbacks.EarlyStopping + init_args: + min_delta: 0 + patience: ${oc.env:PATIENCE, 10} + monitor: *MONITOR_METRIC + mode: *MONITOR_METRIC_MODE + - class_path: eva.callbacks.EmbeddingsWriter + init_args: + output_dir: &DATASET_EMBEDDINGS_ROOT ${oc.env:EMBEDDINGS_ROOT, ./data/embeddings/owkin/phikon/camelyon16} + dataloader_idx_map: + 0: train + 1: val + 2: test + metadata_keys: ["wsi_id"] + backbone: + class_path: eva.models.HuggingFaceModel + init_args: + model_name_or_path: owkin/phikon + tensor_transforms: + class_path: eva.core.models.networks.transforms.ExtractCLSFeatures + logger: + - class_path: lightning.pytorch.loggers.TensorBoardLogger + init_args: + save_dir: *OUTPUT_ROOT + name: "" +model: + class_path: eva.HeadModule + init_args: + head: + class_path: eva.vision.models.networks.ABMIL + init_args: + input_size: ${oc.env:IN_FEATURES, 768} + output_size: &NUM_CLASSES 1 + projected_input_size: 128 + criterion: torch.nn.BCEWithLogitsLoss + optimizer: + class_path: torch.optim.AdamW + init_args: + lr: ${oc.env:LR_VALUE, 0.001} + betas: [0.9, 0.999] + lr_scheduler: + class_path: torch.optim.lr_scheduler.CosineAnnealingLR + init_args: + T_max: *MAX_EPOCHS + eta_min: 0.0 + metrics: + common: + - class_path: eva.metrics.AverageLoss + - class_path: eva.metrics.BinaryClassificationMetrics +data: + class_path: eva.DataModule + init_args: + datasets: + train: + class_path: eva.datasets.MultiEmbeddingsClassificationDataset + init_args: &DATASET_ARGS + root: *DATASET_EMBEDDINGS_ROOT + manifest_file: manifest.csv + split: train + embeddings_transforms: + class_path: eva.core.data.transforms.Pad2DTensor + init_args: + pad_size: 10_000 + target_transforms: + class_path: eva.core.data.transforms.dtype.ArrayToFloatTensor + val: + class_path: eva.datasets.MultiEmbeddingsClassificationDataset + init_args: + <<: *DATASET_ARGS + split: val + test: + class_path: eva.datasets.MultiEmbeddingsClassificationDataset + init_args: + <<: *DATASET_ARGS + split: test + predict: + - class_path: eva.vision.datasets.Camelyon16 + init_args: &PREDICT_DATASET_ARGS + root: ${oc.env:DATA_ROOT, ./data}/camelyon16 + sampler: + class_path: eva.vision.data.wsi.patching.samplers.ForegroundGridSampler + init_args: + max_samples: 10_000 + width: 224 + height: 224 + target_mpp: 0.25 + split: train + image_transforms: + class_path: eva.vision.data.transforms.common.ResizeAndCrop + init_args: + size: ${oc.env:RESIZE_DIM, 224} + mean: ${oc.env:NORMALIZE_MEAN, [0.485, 0.456, 0.406]} + std: ${oc.env:NORMALIZE_STD, [0.229, 0.224, 0.225]} + - class_path: eva.vision.datasets.Camelyon16 + init_args: + <<: *PREDICT_DATASET_ARGS + split: val + - class_path: eva.vision.datasets.Camelyon16 + init_args: + <<: *PREDICT_DATASET_ARGS + split: test + dataloaders: + train: + batch_size: &BATCH_SIZE ${oc.env:BATCH_SIZE, 32} + shuffle: true + val: + batch_size: *BATCH_SIZE + test: + batch_size: *BATCH_SIZE + predict: + batch_size: &PREDICT_BATCH_SIZE ${oc.env:PREDICT_BATCH_SIZE, 64} diff --git a/configs/vision/owkin/phikon/offline/panda.yaml b/configs/vision/owkin/phikon/offline/panda.yaml new file mode 100644 index 00000000..32194554 --- /dev/null +++ b/configs/vision/owkin/phikon/offline/panda.yaml @@ -0,0 +1,128 @@ +--- +trainer: + class_path: eva.Trainer + init_args: + n_runs: &N_RUNS ${oc.env:N_RUNS, 5} + default_root_dir: &OUTPUT_ROOT ${oc.env:OUTPUT_ROOT, logs/owkin/phikon/offline/panda} + max_epochs: &MAX_EPOCHS ${oc.env:MAX_EPOCHS, 49} + callbacks: + - class_path: lightning.pytorch.callbacks.LearningRateMonitor + init_args: + logging_interval: epoch + - class_path: lightning.pytorch.callbacks.ModelCheckpoint + init_args: + filename: best + save_last: true + save_top_k: 1 + monitor: &MONITOR_METRIC ${oc.env:MONITOR_METRIC, val/MulticlassAccuracy} + mode: &MONITOR_METRIC_MODE ${oc.env:MONITOR_METRIC_MODE, max} + - class_path: lightning.pytorch.callbacks.EarlyStopping + init_args: + min_delta: 0 + patience: ${oc.env:PATIENCE, 8} + monitor: *MONITOR_METRIC + mode: *MONITOR_METRIC_MODE + - class_path: eva.callbacks.EmbeddingsWriter + init_args: + output_dir: &DATASET_EMBEDDINGS_ROOT ${oc.env:EMBEDDINGS_ROOT, ./data/embeddings/owkin/phikon/panda} + dataloader_idx_map: + 0: train + 1: val + 2: test + metadata_keys: ["wsi_id"] + backbone: + class_path: eva.models.HuggingFaceModel + init_args: + model_name_or_path: owkin/phikon + tensor_transforms: + class_path: eva.core.models.networks.transforms.ExtractCLSFeatures + logger: + - class_path: lightning.pytorch.loggers.TensorBoardLogger + init_args: + save_dir: *OUTPUT_ROOT + name: "" +model: + class_path: eva.HeadModule + init_args: + head: + class_path: eva.vision.models.networks.ABMIL + init_args: + input_size: ${oc.env:IN_FEATURES, 768} + output_size: &NUM_CLASSES 6 + criterion: torch.nn.CrossEntropyLoss + optimizer: + class_path: torch.optim.AdamW + init_args: + lr: ${oc.env:LR_VALUE, 0.001} + betas: [0.9, 0.999] + lr_scheduler: + class_path: torch.optim.lr_scheduler.CosineAnnealingLR + init_args: + T_max: *MAX_EPOCHS + eta_min: 0.0 + metrics: + common: + - class_path: eva.metrics.AverageLoss + - class_path: eva.metrics.MulticlassClassificationMetrics + init_args: + num_classes: *NUM_CLASSES +data: + class_path: eva.DataModule + init_args: + datasets: + train: + class_path: eva.datasets.MultiEmbeddingsClassificationDataset + init_args: &DATASET_ARGS + root: *DATASET_EMBEDDINGS_ROOT + manifest_file: manifest.csv + split: train + embeddings_transforms: + class_path: eva.core.data.transforms.Pad2DTensor + init_args: + pad_size: &N_PATCHES 1000 + val: + class_path: eva.datasets.MultiEmbeddingsClassificationDataset + init_args: + <<: *DATASET_ARGS + split: val + test: + class_path: eva.datasets.MultiEmbeddingsClassificationDataset + init_args: + <<: *DATASET_ARGS + split: test + predict: + - class_path: eva.vision.datasets.PANDA + init_args: &PREDICT_DATASET_ARGS + root: ${oc.env:DATA_ROOT, ./data}/panda/prostate-cancer-grade-assessment + sampler: + class_path: eva.vision.data.wsi.patching.samplers.ForegroundGridSampler + init_args: + max_samples: *N_PATCHES + width: 224 + height: 224 + target_mpp: 0.5 + split: train + image_transforms: + class_path: eva.vision.data.transforms.common.ResizeAndCrop + init_args: + size: ${oc.env:RESIZE_DIM, 224} + mean: ${oc.env:NORMALIZE_MEAN, [0.485, 0.456, 0.406]} + std: ${oc.env:NORMALIZE_STD, [0.229, 0.224, 0.225]} + - class_path: eva.vision.datasets.PANDA + init_args: + <<: *PREDICT_DATASET_ARGS + split: val + - class_path: eva.vision.datasets.PANDA + init_args: + <<: *PREDICT_DATASET_ARGS + split: test + dataloaders: + train: + batch_size: &BATCH_SIZE ${oc.env:BATCH_SIZE, 32} + shuffle: true + val: + batch_size: *BATCH_SIZE + test: + batch_size: *BATCH_SIZE + predict: + batch_size: &PREDICT_BATCH_SIZE ${oc.env:PREDICT_BATCH_SIZE, 64} diff --git a/tests/eva/vision/test_vision_cli.py b/tests/eva/vision/test_vision_cli.py index c09a1cae..174f0c32 100644 --- a/tests/eva/vision/test_vision_cli.py +++ b/tests/eva/vision/test_vision_cli.py @@ -28,6 +28,8 @@ "configs/vision/owkin/phikon/offline/crc.yaml", "configs/vision/owkin/phikon/offline/mhist.yaml", "configs/vision/owkin/phikon/offline/patch_camelyon.yaml", + "configs/vision/owkin/phikon/offline/panda.yaml", + "configs/vision/owkin/phikon/offline/camelyon16.yaml", ], ) def test_configuration_initialization(configuration_file: str, lib_path: str) -> None: