From 52791a38edb145fdfa0e195b8e0037b7622b567b Mon Sep 17 00:00:00 2001 From: Isabel Gallegos Date: Wed, 2 Feb 2022 16:50:23 -0800 Subject: [PATCH 01/10] Add configurable dropout rate --- medsegpy/config.py | 5 +++++ medsegpy/modeling/meta_arch/unet.py | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/medsegpy/config.py b/medsegpy/config.py index 44d0e9ca..39b9e7fc 100644 --- a/medsegpy/config.py +++ b/medsegpy/config.py @@ -106,6 +106,9 @@ class Config(object): EARLY_STOPPING_PATIENCE = 0 EARLY_STOPPING_CRITERION = "val_loss" + # Dropout rate + DROPOUT_RATE = 0.0 + # Batch sizes TRAIN_BATCH_SIZE = 12 VALID_BATCH_SIZE = 35 @@ -589,6 +592,8 @@ def summary(self, additional_vars=None): "EARLY_STOPPING_PATIENCE" if self.USE_EARLY_STOPPING else "", "EARLY_STOPPING_CRITERION" if self.USE_EARLY_STOPPING else "", "", + "DROPOUT_RATE", + "", "KERNEL_INITIALIZER", "SEED" if self.SEED else "", "" "INIT_WEIGHTS", diff --git a/medsegpy/modeling/meta_arch/unet.py b/medsegpy/modeling/meta_arch/unet.py index 07c70149..047e3a91 100644 --- a/medsegpy/modeling/meta_arch/unet.py +++ b/medsegpy/modeling/meta_arch/unet.py @@ -145,6 +145,7 @@ def build_model(self, input_tensor=None) -> Model: seed = cfg.SEED depth = cfg.DEPTH kernel_size = self.kernel_size + dropout_rate = cfg.DROPOUT_RATE self.use_attention = cfg.USE_ATTENTION self.use_deep_supervision = cfg.USE_DEEP_SUPERVISION @@ -178,7 +179,7 @@ def build_model(self, input_tensor=None) -> Model: num_conv=2, activation="relu", kernel_initializer=kernel_initializer, - dropout=0.0, + dropout=dropout_rate, ) # Maxpool until penultimate depth. @@ -220,7 +221,7 @@ def build_model(self, input_tensor=None) -> Model: num_conv=2, activation="relu", kernel_initializer=kernel_initializer, - dropout=0.0, + dropout=dropout_rate, ) if self.use_deep_supervision: From 848070b5d3770c6118c0d404ce1139f9a4bc40b6 Mon Sep 17 00:00:00 2001 From: Isabel Gallegos Date: Wed, 2 Feb 2022 21:11:11 -0800 Subject: [PATCH 02/10] Add MC dropout to model inference --- medsegpy/modeling/model.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/medsegpy/modeling/model.py b/medsegpy/modeling/model.py index d514653d..17e16fcf 100644 --- a/medsegpy/modeling/model.py +++ b/medsegpy/modeling/model.py @@ -255,6 +255,7 @@ def _inference_generator_tf2( ): """Inference generator for TensorFlow 2.""" outputs = [] + outputs_mc_dropout = [] xs = [] ys = [] with model.distribute_strategy.scope(): @@ -295,14 +296,21 @@ def _inference_generator_tf2( batch_x, batch_y, batch_x_raw = _extract_inference_inputs(next(iterator)) # tmp_batch_outputs = predict_function(iterator) tmp_batch_outputs = model.predict(batch_x) + + + tmp_batch_outputs_mc_dropout = None + if True: #mc_dropout: + tmp_batch_outputs_mc_dropout = np.stack([model(batch_x, training=True) for _ in range(100)]) # TODO: 100 -> T + if data_handler.should_sync: context.async_wait() # noqa: F821 batch_outputs = tmp_batch_outputs # No error, now safe to assign. + batch_outputs_mc_dropout = tmp_batch_outputs_mc_dropout if batch_x_raw is not None: batch_x = batch_x_raw for batch, running in zip( - [batch_x, batch_y, batch_outputs], [xs, ys, outputs] + [batch_x, batch_y, batch_outputs, batch_outputs_mc_dropout], [xs, ys, outputs, outputs_mc_dropout] ): nest.map_structure_up_to( batch, lambda x, batch_x: x.append(batch_x), running, batch @@ -318,7 +326,11 @@ def _inference_generator_tf2( all_xs = nest.map_structure_up_to(batch_x, np.concatenate, xs) all_ys = nest.map_structure_up_to(batch_y, np.concatenate, ys) all_outputs = nest.map_structure_up_to(batch_outputs, np.concatenate, outputs) - return all_xs, all_ys, all_outputs + all_outputs_mc_dropout = nest.map_structure_up_to(batch_outputs_mc_dropout, np.concatenate, outputs_mc_dropout) + + outputs = {'preds': all_outputs, 'preds_mc_dropout': all_outputs_mc_dropout} + + return all_xs, all_ys, outputs # all_xs = nest.map_structure_up_to(batch_x, concat, xs) # all_ys = nest.map_structure_up_to(batch_y, concat, ys) From 70bec9a707c58fa03a89da5a37fc90d08eb414e1 Mon Sep 17 00:00:00 2001 From: Isabel Gallegos Date: Wed, 2 Feb 2022 22:05:34 -0800 Subject: [PATCH 03/10] Save mc dropout output --- medsegpy/data/data_loader.py | 9 ++++++++- medsegpy/evaluation/sem_seg_evaluation.py | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/medsegpy/data/data_loader.py b/medsegpy/data/data_loader.py index 3208192a..7883e2f1 100644 --- a/medsegpy/data/data_loader.py +++ b/medsegpy/data/data_loader.py @@ -353,6 +353,13 @@ def inference(self, model: Model, **kwargs): ) time_elapsed = time.perf_counter() - start + preds_mc_dropout = None + if isinstance(preds, dict): + preds_mc_dropout = np.squeeze(preds['preds_mc_dropout']) + preds_mc_dropout = preds_mc_dropout.transpose((1, 2, 3, 0)) + + preds = preds['preds'] + x, y, preds = self._restructure_data((x, y, preds)) input = {"x": x, "scan_id": scan_id} @@ -363,7 +370,7 @@ def inference(self, model: Model, **kwargs): } input.update(scan_params) - output = {"y_pred": preds, "y_true": y, "time_elapsed": time_elapsed} + output = {"y_pred": preds, "y_mc_dropout":preds_mc_dropout, "y_true": y, "time_elapsed": time_elapsed} yield input, output diff --git a/medsegpy/evaluation/sem_seg_evaluation.py b/medsegpy/evaluation/sem_seg_evaluation.py index 6b8c192a..5327021e 100644 --- a/medsegpy/evaluation/sem_seg_evaluation.py +++ b/medsegpy/evaluation/sem_seg_evaluation.py @@ -134,6 +134,7 @@ def process(self, inputs, outputs): if includes_bg: y_true = output["y_true"][..., 1:] y_pred = output["y_pred"][..., 1:] + y_mc_dropout = None if output["y_mc_dropout"] is None else output["y_pred"][..., 1:] labels = labels[..., 1:] # if y_true.ndim == 3: # y_true = y_true[..., np.newaxis] @@ -141,6 +142,7 @@ def process(self, inputs, outputs): # labels = labels[..., np.newaxis] output["y_true"] = y_true output["y_pred"] = y_pred + output["y_mc_dropout"] = y_mc_dropout time_elapsed = output["time_elapsed"] if self.stream_evaluation: @@ -178,6 +180,7 @@ def eval_single_scan(self, input, output, labels, time_elapsed): with h5py.File(save_name, "w") as h5f: h5f.create_dataset("probs", data=output["y_pred"]) h5f.create_dataset("labels", data=labels) + h5f.create_dataset("mc_dropout", data=output["y_mc_dropout"]) def evaluate(self): """Evaluates popular medical segmentation metrics specified in config. From 4d45970682cc6cf49a38d14ee3e63fa37b36a890 Mon Sep 17 00:00:00 2001 From: Isabel Gallegos Date: Wed, 2 Feb 2022 22:58:28 -0800 Subject: [PATCH 04/10] Make mc dropout configurable --- medsegpy/config.py | 4 ++++ medsegpy/data/data_loader.py | 8 ++++++-- medsegpy/evaluation/sem_seg_evaluation.py | 3 ++- medsegpy/modeling/model.py | 16 +++++++++++----- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/medsegpy/config.py b/medsegpy/config.py index 39b9e7fc..f7d378d2 100644 --- a/medsegpy/config.py +++ b/medsegpy/config.py @@ -108,6 +108,8 @@ class Config(object): # Dropout rate DROPOUT_RATE = 0.0 + MC_DROPOUT = False + MC_DROPOUT_T = 100 # Batch sizes TRAIN_BATCH_SIZE = 12 @@ -593,6 +595,8 @@ def summary(self, additional_vars=None): "EARLY_STOPPING_CRITERION" if self.USE_EARLY_STOPPING else "", "", "DROPOUT_RATE", + "MC_DROPOUT", + "MC_DROPOUT_T" if self.MC_DROPOUT else "" "", "KERNEL_INITIALIZER", "SEED" if self.SEED else "", diff --git a/medsegpy/data/data_loader.py b/medsegpy/data/data_loader.py index 7883e2f1..3370c0f2 100644 --- a/medsegpy/data/data_loader.py +++ b/medsegpy/data/data_loader.py @@ -337,6 +337,10 @@ def inference(self, model: Model, **kwargs): workers = kwargs.pop("workers", self._cfg.NUM_WORKERS) use_multiprocessing = kwargs.pop("use_multiprocessing", workers > 1) + + kwargs["mc_dropout"] = self._cfg.MC_DROPOUT + kwargs["mc_dropout_T"] = self._cfg.MC_DROPOUT_T + for scan_id in scan_ids: self._dataset_dicts = scan_to_dict_mapping[scan_id] @@ -355,8 +359,8 @@ def inference(self, model: Model, **kwargs): preds_mc_dropout = None if isinstance(preds, dict): - preds_mc_dropout = np.squeeze(preds['preds_mc_dropout']) - preds_mc_dropout = preds_mc_dropout.transpose((1, 2, 3, 0)) + if preds['preds_mc_dropout'] is not None: + preds_mc_dropout = np.squeeze(preds['preds_mc_dropout']).transpose((1, 2, 3, 0)) preds = preds['preds'] diff --git a/medsegpy/evaluation/sem_seg_evaluation.py b/medsegpy/evaluation/sem_seg_evaluation.py index 5327021e..493143ad 100644 --- a/medsegpy/evaluation/sem_seg_evaluation.py +++ b/medsegpy/evaluation/sem_seg_evaluation.py @@ -180,7 +180,8 @@ def eval_single_scan(self, input, output, labels, time_elapsed): with h5py.File(save_name, "w") as h5f: h5f.create_dataset("probs", data=output["y_pred"]) h5f.create_dataset("labels", data=labels) - h5f.create_dataset("mc_dropout", data=output["y_mc_dropout"]) + if output["y_mc_dropout"] is not None: + h5f.create_dataset("mc_dropout", data=output["y_mc_dropout"]) def evaluate(self): """Evaluates popular medical segmentation metrics specified in config. diff --git a/medsegpy/modeling/model.py b/medsegpy/modeling/model.py index 17e16fcf..944d12f0 100644 --- a/medsegpy/modeling/model.py +++ b/medsegpy/modeling/model.py @@ -42,7 +42,9 @@ def inference_generator( max_queue_size=10, workers=1, use_multiprocessing=False, - verbose=0, + mc_dropout=False, + mc_dropout_T=100, + verbose=0 ): return self.inference_generator_static( self, generator, steps, max_queue_size, workers, use_multiprocessing, verbose @@ -57,7 +59,9 @@ def inference_generator_static( max_queue_size=10, workers=1, use_multiprocessing=False, - verbose=0, + mc_dropout=False, + mc_dropout_T=100, + verbose=0 ): """Generates predictions for the input samples from a data generator and returns inputs, ground truth, and predictions. @@ -252,6 +256,8 @@ def _inference_generator_tf2( max_queue_size=10, workers=1, use_multiprocessing=False, + mc_dropout=False, + mc_dropout_T=100 ): """Inference generator for TensorFlow 2.""" outputs = [] @@ -299,8 +305,8 @@ def _inference_generator_tf2( tmp_batch_outputs_mc_dropout = None - if True: #mc_dropout: - tmp_batch_outputs_mc_dropout = np.stack([model(batch_x, training=True) for _ in range(100)]) # TODO: 100 -> T + if mc_dropout: + tmp_batch_outputs_mc_dropout = np.stack([model(batch_x, training=True) for _ in range(mc_dropout_T)]) if data_handler.should_sync: context.async_wait() # noqa: F821 @@ -326,7 +332,7 @@ def _inference_generator_tf2( all_xs = nest.map_structure_up_to(batch_x, np.concatenate, xs) all_ys = nest.map_structure_up_to(batch_y, np.concatenate, ys) all_outputs = nest.map_structure_up_to(batch_outputs, np.concatenate, outputs) - all_outputs_mc_dropout = nest.map_structure_up_to(batch_outputs_mc_dropout, np.concatenate, outputs_mc_dropout) + all_outputs_mc_dropout = nest.map_structure_up_to(batch_outputs_mc_dropout, np.concatenate, outputs_mc_dropout) if mc_dropout else None outputs = {'preds': all_outputs, 'preds_mc_dropout': all_outputs_mc_dropout} From acffc062d1c16d6b5ac25cfe60065b1270c86d8b Mon Sep 17 00:00:00 2001 From: i-gallegos Date: Thu, 3 Feb 2022 16:45:32 -0800 Subject: [PATCH 05/10] Fix mc dropout bug --- medsegpy/data/data_loader.py | 2 +- medsegpy/modeling/model.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/medsegpy/data/data_loader.py b/medsegpy/data/data_loader.py index 3370c0f2..c60dc47d 100644 --- a/medsegpy/data/data_loader.py +++ b/medsegpy/data/data_loader.py @@ -337,7 +337,7 @@ def inference(self, model: Model, **kwargs): workers = kwargs.pop("workers", self._cfg.NUM_WORKERS) use_multiprocessing = kwargs.pop("use_multiprocessing", workers > 1) - + kwargs["mc_dropout"] = self._cfg.MC_DROPOUT kwargs["mc_dropout_T"] = self._cfg.MC_DROPOUT_T diff --git a/medsegpy/modeling/model.py b/medsegpy/modeling/model.py index 944d12f0..de0cdd2c 100644 --- a/medsegpy/modeling/model.py +++ b/medsegpy/modeling/model.py @@ -119,6 +119,8 @@ def inference_generator_static( max_queue_size=max_queue_size, workers=workers, use_multiprocessing=use_multiprocessing, + mc_dropout=mc_dropout, + mc_dropout_T=mc_dropout_T, verbose=verbose, ) else: From b6878377af79b0c0939d187605d3525bb852bc03 Mon Sep 17 00:00:00 2001 From: i-gallegos Date: Fri, 11 Feb 2022 01:25:04 -0800 Subject: [PATCH 06/10] Save y_true --- medsegpy/evaluation/sem_seg_evaluation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/medsegpy/evaluation/sem_seg_evaluation.py b/medsegpy/evaluation/sem_seg_evaluation.py index 493143ad..4994ab3f 100644 --- a/medsegpy/evaluation/sem_seg_evaluation.py +++ b/medsegpy/evaluation/sem_seg_evaluation.py @@ -180,6 +180,7 @@ def eval_single_scan(self, input, output, labels, time_elapsed): with h5py.File(save_name, "w") as h5f: h5f.create_dataset("probs", data=output["y_pred"]) h5f.create_dataset("labels", data=labels) + h5f.create_dataset("true", data=output["y_true"]) if output["y_mc_dropout"] is not None: h5f.create_dataset("mc_dropout", data=output["y_mc_dropout"]) From 20dc50165925b3e62b3f139887646949f32f6087 Mon Sep 17 00:00:00 2001 From: i-gallegos Date: Fri, 29 Apr 2022 14:20:33 -0700 Subject: [PATCH 07/10] Dicom inference --- medsegpy/data/data_loader.py | 20 +++++++++++++++----- medsegpy/evaluation/evaluator.py | 6 +++--- medsegpy/modeling/model.py | 4 +++- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/medsegpy/data/data_loader.py b/medsegpy/data/data_loader.py index c60dc47d..9bc5f67e 100644 --- a/medsegpy/data/data_loader.py +++ b/medsegpy/data/data_loader.py @@ -18,6 +18,7 @@ from medsegpy.config import Config from medsegpy.modeling import Model from medsegpy.utils import env +from pydicom import dcmread from .data_utils import add_background_labels, collect_mask, compute_patches from .transforms import apply_transform_gens, build_preprocessing @@ -242,8 +243,10 @@ def _load_input(self, dataset_dict): if self._cached_data is not None: image, mask = self._cached_data[(image_file, sem_seg_file)] else: - with h5py.File(image_file, "r") as f: - image = f["data"][:] + # with h5py.File(image_file, "r") as f: + # image = f["data"][:] + ds = dcmread(image_file) + image = ds.pixel_array if image.shape[-1] != 1: image = image[..., np.newaxis] @@ -323,7 +326,11 @@ def _restructure_data(self, vols: Sequence[np.ndarray]): axes = (1, 2, 0) if v.ndim > 3: axes = axes + tuple(i for i in range(3, v.ndim)) - new_vols.append(v.transpose(axes)) + # new_vols.append(v.transpose(axes)) + if v.ndim == 1: + new_vols.append(v) + else: + new_vols.append(v.transpose(axes)) vols = (np.squeeze(v) for v in new_vols) return tuple(vols) @@ -340,9 +347,12 @@ def inference(self, model: Model, **kwargs): kwargs["mc_dropout"] = self._cfg.MC_DROPOUT kwargs["mc_dropout_T"] = self._cfg.MC_DROPOUT_T + kwargs["batch_size"] = 1 - for scan_id in scan_ids: - self._dataset_dicts = scan_to_dict_mapping[scan_id] + # for scan_id in scan_ids: + # self._dataset_dicts = scan_to_dict_mapping[scan_id] + for scan_id in range(1): + self._dataset_dicts = dataset_dicts start = time.perf_counter() if not isinstance(model, Model): diff --git a/medsegpy/evaluation/evaluator.py b/medsegpy/evaluation/evaluator.py index 7103d3f5..a23cccfb 100644 --- a/medsegpy/evaluation/evaluator.py +++ b/medsegpy/evaluation/evaluator.py @@ -109,8 +109,8 @@ def inference_on_dataset( total_compute_time += time.perf_counter() - start_compute_time start_processing_time = time.perf_counter() - for e in evaluator: - e.process([input], [output]) + # for e in evaluator: + # e.process([input], [output]) total_processing_time += time.perf_counter() - start_processing_time total_inference_time += output["time_elapsed"] @@ -139,7 +139,7 @@ def inference_on_dataset( eval_start = time.perf_counter() logger.info("Begin evaluation...") - results = {e.__class__.__name__: e.evaluate() for e in evaluator} + # results = {e.__class__.__name__: e.evaluate() for e in evaluator} total_eval_time = time.perf_counter() - eval_start logger.info("Time Elapsed: {:.4f} seconds".format(total_compute_time + total_eval_time)) # An evaluator may return None when not in main process. diff --git a/medsegpy/modeling/model.py b/medsegpy/modeling/model.py index de0cdd2c..a1db9b7a 100644 --- a/medsegpy/modeling/model.py +++ b/medsegpy/modeling/model.py @@ -61,7 +61,8 @@ def inference_generator_static( use_multiprocessing=False, mc_dropout=False, mc_dropout_T=100, - verbose=0 + verbose=0, + batch_size=None ): """Generates predictions for the input samples from a data generator and returns inputs, ground truth, and predictions. @@ -122,6 +123,7 @@ def inference_generator_static( mc_dropout=mc_dropout, mc_dropout_T=mc_dropout_T, verbose=verbose, + batch_size=batch_size ) else: return model._inference_generator_tf1( From 57386f00ac6f3ba6c92ba9a7d813b89fbe275739 Mon Sep 17 00:00:00 2001 From: i-gallegos Date: Sat, 30 Apr 2022 16:13:36 -0700 Subject: [PATCH 08/10] Add INFERENCE_ONLY to config --- medsegpy/config.py | 4 ++++ medsegpy/data/data_loader.py | 6 ++---- medsegpy/evaluation/evaluator.py | 9 ++++++--- medsegpy/evaluation/sem_seg_evaluation.py | 19 ++++++++++--------- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/medsegpy/config.py b/medsegpy/config.py index f7d378d2..38ea507c 100644 --- a/medsegpy/config.py +++ b/medsegpy/config.py @@ -132,6 +132,9 @@ class Config(object): VAL_DATASET = "" TEST_DATASET = "" + # Inference only, with no evaluation + INFERENCE_ONLY = False + # Cross-Validation-Parameters USE_CROSS_VALIDATION = False CV_FILE = "" @@ -555,6 +558,7 @@ def summary(self, additional_vars=None): "TRAIN_DATASET", "VAL_DATASET", "TEST_DATASET", + "INFERENCE_ONLY", "", "CATEGORIES", "", diff --git a/medsegpy/data/data_loader.py b/medsegpy/data/data_loader.py index 9bc5f67e..b1dadc27 100644 --- a/medsegpy/data/data_loader.py +++ b/medsegpy/data/data_loader.py @@ -349,10 +349,8 @@ def inference(self, model: Model, **kwargs): kwargs["mc_dropout_T"] = self._cfg.MC_DROPOUT_T kwargs["batch_size"] = 1 - # for scan_id in scan_ids: - # self._dataset_dicts = scan_to_dict_mapping[scan_id] - for scan_id in range(1): - self._dataset_dicts = dataset_dicts + for scan_id in scan_ids: + self._dataset_dicts = scan_to_dict_mapping[scan_id] start = time.perf_counter() if not isinstance(model, Model): diff --git a/medsegpy/evaluation/evaluator.py b/medsegpy/evaluation/evaluator.py index a23cccfb..6230bfe2 100644 --- a/medsegpy/evaluation/evaluator.py +++ b/medsegpy/evaluation/evaluator.py @@ -109,8 +109,8 @@ def inference_on_dataset( total_compute_time += time.perf_counter() - start_compute_time start_processing_time = time.perf_counter() - # for e in evaluator: - # e.process([input], [output]) + for e in evaluator: + e.process([input], [output]) total_processing_time += time.perf_counter() - start_processing_time total_inference_time += output["time_elapsed"] @@ -139,7 +139,10 @@ def inference_on_dataset( eval_start = time.perf_counter() logger.info("Begin evaluation...") - # results = {e.__class__.__name__: e.evaluate() for e in evaluator} + if any([e._config.INFERENCE_ONLY for e in evaluator]): + results = None + else: + results = {e.__class__.__name__: e.evaluate() for e in evaluator} total_eval_time = time.perf_counter() - eval_start logger.info("Time Elapsed: {:.4f} seconds".format(total_compute_time + total_eval_time)) # An evaluator may return None when not in main process. diff --git a/medsegpy/evaluation/sem_seg_evaluation.py b/medsegpy/evaluation/sem_seg_evaluation.py index 4994ab3f..cc136a9e 100644 --- a/medsegpy/evaluation/sem_seg_evaluation.py +++ b/medsegpy/evaluation/sem_seg_evaluation.py @@ -165,15 +165,16 @@ def eval_single_scan(self, input, output, labels, time_elapsed): metrics_kwargs = {"spacing": spacing} if spacing is not None else {} - summary = metrics_manager( - scan_id, y_true=y_true, y_pred=labels, x=x, runtime=time_elapsed, **metrics_kwargs - ) - - logger_info_str = "Scan #{:03d} (name = {}, {:0.2f}s) = {}".format( - scan_cnt, scan_id, time_elapsed, summary - ) - self._results_str = self._results_str + logger_info_str + "\n" - logger.info(logger_info_str) + if not self._config.INFERENCE_ONLY: + summary = metrics_manager( + scan_id, y_true=y_true, y_pred=labels, x=x, runtime=time_elapsed, **metrics_kwargs + ) + + logger_info_str = "Scan #{:03d} (name = {}, {:0.2f}s) = {}".format( + scan_cnt, scan_id, time_elapsed, summary + ) + self._results_str = self._results_str + logger_info_str + "\n" + logger.info(logger_info_str) if output_dir and save_raw_data: save_name = "{}/{}.pred".format(output_dir, scan_id) From 0386e7463769d5f5a820fc1d5ab382356ca96876 Mon Sep 17 00:00:00 2001 From: i-gallegos Date: Mon, 16 May 2022 22:04:33 -0700 Subject: [PATCH 09/10] Bug fixes --- medsegpy/data/data_loader.py | 11 +++++++---- medsegpy/evaluation/sem_seg_evaluation.py | 2 +- medsegpy/modeling/model.py | 3 ++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/medsegpy/data/data_loader.py b/medsegpy/data/data_loader.py index b1dadc27..26f35184 100644 --- a/medsegpy/data/data_loader.py +++ b/medsegpy/data/data_loader.py @@ -243,10 +243,13 @@ def _load_input(self, dataset_dict): if self._cached_data is not None: image, mask = self._cached_data[(image_file, sem_seg_file)] else: - # with h5py.File(image_file, "r") as f: - # image = f["data"][:] - ds = dcmread(image_file) - image = ds.pixel_array + if image_file.endswith('.dcm'): + ds = dcmread(image_file) + image = ds.pixel_array + else: + with h5py.File(image_file, "r") as f: + image = f["data"][:] + if image.shape[-1] != 1: image = image[..., np.newaxis] diff --git a/medsegpy/evaluation/sem_seg_evaluation.py b/medsegpy/evaluation/sem_seg_evaluation.py index cc136a9e..07c8a8cb 100644 --- a/medsegpy/evaluation/sem_seg_evaluation.py +++ b/medsegpy/evaluation/sem_seg_evaluation.py @@ -134,7 +134,7 @@ def process(self, inputs, outputs): if includes_bg: y_true = output["y_true"][..., 1:] y_pred = output["y_pred"][..., 1:] - y_mc_dropout = None if output["y_mc_dropout"] is None else output["y_pred"][..., 1:] + y_mc_dropout = None if output["y_mc_dropout"] is None else output["y_mc_dropout"][..., 1:] labels = labels[..., 1:] # if y_true.ndim == 3: # y_true = y_true[..., np.newaxis] diff --git a/medsegpy/modeling/model.py b/medsegpy/modeling/model.py index a1db9b7a..610a4bac 100644 --- a/medsegpy/modeling/model.py +++ b/medsegpy/modeling/model.py @@ -44,7 +44,8 @@ def inference_generator( use_multiprocessing=False, mc_dropout=False, mc_dropout_T=100, - verbose=0 + verbose=0, + batch_size=None ): return self.inference_generator_static( self, generator, steps, max_queue_size, workers, use_multiprocessing, verbose From cac6a115fa872151cdf024798cdac4e22ba4da98 Mon Sep 17 00:00:00 2001 From: i-gallegos Date: Tue, 17 May 2022 13:38:30 -0700 Subject: [PATCH 10/10] Remove mc dropout changes --- medsegpy/config.py | 9 --------- medsegpy/data/data_loader.py | 11 +---------- medsegpy/evaluation/sem_seg_evaluation.py | 5 ----- medsegpy/modeling/meta_arch/unet.py | 5 ++--- medsegpy/modeling/model.py | 23 ++--------------------- 5 files changed, 5 insertions(+), 48 deletions(-) diff --git a/medsegpy/config.py b/medsegpy/config.py index 38ea507c..274d1dd4 100644 --- a/medsegpy/config.py +++ b/medsegpy/config.py @@ -106,11 +106,6 @@ class Config(object): EARLY_STOPPING_PATIENCE = 0 EARLY_STOPPING_CRITERION = "val_loss" - # Dropout rate - DROPOUT_RATE = 0.0 - MC_DROPOUT = False - MC_DROPOUT_T = 100 - # Batch sizes TRAIN_BATCH_SIZE = 12 VALID_BATCH_SIZE = 35 @@ -598,10 +593,6 @@ def summary(self, additional_vars=None): "EARLY_STOPPING_PATIENCE" if self.USE_EARLY_STOPPING else "", "EARLY_STOPPING_CRITERION" if self.USE_EARLY_STOPPING else "", "", - "DROPOUT_RATE", - "MC_DROPOUT", - "MC_DROPOUT_T" if self.MC_DROPOUT else "" - "", "KERNEL_INITIALIZER", "SEED" if self.SEED else "", "" "INIT_WEIGHTS", diff --git a/medsegpy/data/data_loader.py b/medsegpy/data/data_loader.py index 26f35184..fa080e3b 100644 --- a/medsegpy/data/data_loader.py +++ b/medsegpy/data/data_loader.py @@ -348,8 +348,6 @@ def inference(self, model: Model, **kwargs): workers = kwargs.pop("workers", self._cfg.NUM_WORKERS) use_multiprocessing = kwargs.pop("use_multiprocessing", workers > 1) - kwargs["mc_dropout"] = self._cfg.MC_DROPOUT - kwargs["mc_dropout_T"] = self._cfg.MC_DROPOUT_T kwargs["batch_size"] = 1 for scan_id in scan_ids: @@ -368,13 +366,6 @@ def inference(self, model: Model, **kwargs): ) time_elapsed = time.perf_counter() - start - preds_mc_dropout = None - if isinstance(preds, dict): - if preds['preds_mc_dropout'] is not None: - preds_mc_dropout = np.squeeze(preds['preds_mc_dropout']).transpose((1, 2, 3, 0)) - - preds = preds['preds'] - x, y, preds = self._restructure_data((x, y, preds)) input = {"x": x, "scan_id": scan_id} @@ -385,7 +376,7 @@ def inference(self, model: Model, **kwargs): } input.update(scan_params) - output = {"y_pred": preds, "y_mc_dropout":preds_mc_dropout, "y_true": y, "time_elapsed": time_elapsed} + output = {"y_pred": preds, "y_true": y, "time_elapsed": time_elapsed} yield input, output diff --git a/medsegpy/evaluation/sem_seg_evaluation.py b/medsegpy/evaluation/sem_seg_evaluation.py index 07c8a8cb..2da2b5d8 100644 --- a/medsegpy/evaluation/sem_seg_evaluation.py +++ b/medsegpy/evaluation/sem_seg_evaluation.py @@ -134,7 +134,6 @@ def process(self, inputs, outputs): if includes_bg: y_true = output["y_true"][..., 1:] y_pred = output["y_pred"][..., 1:] - y_mc_dropout = None if output["y_mc_dropout"] is None else output["y_mc_dropout"][..., 1:] labels = labels[..., 1:] # if y_true.ndim == 3: # y_true = y_true[..., np.newaxis] @@ -142,7 +141,6 @@ def process(self, inputs, outputs): # labels = labels[..., np.newaxis] output["y_true"] = y_true output["y_pred"] = y_pred - output["y_mc_dropout"] = y_mc_dropout time_elapsed = output["time_elapsed"] if self.stream_evaluation: @@ -181,9 +179,6 @@ def eval_single_scan(self, input, output, labels, time_elapsed): with h5py.File(save_name, "w") as h5f: h5f.create_dataset("probs", data=output["y_pred"]) h5f.create_dataset("labels", data=labels) - h5f.create_dataset("true", data=output["y_true"]) - if output["y_mc_dropout"] is not None: - h5f.create_dataset("mc_dropout", data=output["y_mc_dropout"]) def evaluate(self): """Evaluates popular medical segmentation metrics specified in config. diff --git a/medsegpy/modeling/meta_arch/unet.py b/medsegpy/modeling/meta_arch/unet.py index 047e3a91..07c70149 100644 --- a/medsegpy/modeling/meta_arch/unet.py +++ b/medsegpy/modeling/meta_arch/unet.py @@ -145,7 +145,6 @@ def build_model(self, input_tensor=None) -> Model: seed = cfg.SEED depth = cfg.DEPTH kernel_size = self.kernel_size - dropout_rate = cfg.DROPOUT_RATE self.use_attention = cfg.USE_ATTENTION self.use_deep_supervision = cfg.USE_DEEP_SUPERVISION @@ -179,7 +178,7 @@ def build_model(self, input_tensor=None) -> Model: num_conv=2, activation="relu", kernel_initializer=kernel_initializer, - dropout=dropout_rate, + dropout=0.0, ) # Maxpool until penultimate depth. @@ -221,7 +220,7 @@ def build_model(self, input_tensor=None) -> Model: num_conv=2, activation="relu", kernel_initializer=kernel_initializer, - dropout=dropout_rate, + dropout=0.0, ) if self.use_deep_supervision: diff --git a/medsegpy/modeling/model.py b/medsegpy/modeling/model.py index 610a4bac..34c650be 100644 --- a/medsegpy/modeling/model.py +++ b/medsegpy/modeling/model.py @@ -42,8 +42,6 @@ def inference_generator( max_queue_size=10, workers=1, use_multiprocessing=False, - mc_dropout=False, - mc_dropout_T=100, verbose=0, batch_size=None ): @@ -60,8 +58,6 @@ def inference_generator_static( max_queue_size=10, workers=1, use_multiprocessing=False, - mc_dropout=False, - mc_dropout_T=100, verbose=0, batch_size=None ): @@ -121,8 +117,6 @@ def inference_generator_static( max_queue_size=max_queue_size, workers=workers, use_multiprocessing=use_multiprocessing, - mc_dropout=mc_dropout, - mc_dropout_T=mc_dropout_T, verbose=verbose, batch_size=batch_size ) @@ -261,12 +255,9 @@ def _inference_generator_tf2( max_queue_size=10, workers=1, use_multiprocessing=False, - mc_dropout=False, - mc_dropout_T=100 ): """Inference generator for TensorFlow 2.""" outputs = [] - outputs_mc_dropout = [] xs = [] ys = [] with model.distribute_strategy.scope(): @@ -308,20 +299,14 @@ def _inference_generator_tf2( # tmp_batch_outputs = predict_function(iterator) tmp_batch_outputs = model.predict(batch_x) - - tmp_batch_outputs_mc_dropout = None - if mc_dropout: - tmp_batch_outputs_mc_dropout = np.stack([model(batch_x, training=True) for _ in range(mc_dropout_T)]) - if data_handler.should_sync: context.async_wait() # noqa: F821 batch_outputs = tmp_batch_outputs # No error, now safe to assign. - batch_outputs_mc_dropout = tmp_batch_outputs_mc_dropout if batch_x_raw is not None: batch_x = batch_x_raw for batch, running in zip( - [batch_x, batch_y, batch_outputs, batch_outputs_mc_dropout], [xs, ys, outputs, outputs_mc_dropout] + [batch_x, batch_y, batch_outputs], [xs, ys, outputs] ): nest.map_structure_up_to( batch, lambda x, batch_x: x.append(batch_x), running, batch @@ -337,11 +322,7 @@ def _inference_generator_tf2( all_xs = nest.map_structure_up_to(batch_x, np.concatenate, xs) all_ys = nest.map_structure_up_to(batch_y, np.concatenate, ys) all_outputs = nest.map_structure_up_to(batch_outputs, np.concatenate, outputs) - all_outputs_mc_dropout = nest.map_structure_up_to(batch_outputs_mc_dropout, np.concatenate, outputs_mc_dropout) if mc_dropout else None - - outputs = {'preds': all_outputs, 'preds_mc_dropout': all_outputs_mc_dropout} - - return all_xs, all_ys, outputs + return all_xs, all_ys, all_outputs # all_xs = nest.map_structure_up_to(batch_x, concat, xs) # all_ys = nest.map_structure_up_to(batch_y, concat, ys)