def create_pipeline_from_checkpoint_paths( config: ModelConfigBase, checkpoint_paths: List[Path]) -> Optional[InferencePipelineBase]: """ Attempt to create a pipeline from the provided checkpoint paths. If the files referred to by the paths do not exist, or if there are no paths, None will be returned. """ if len(checkpoint_paths) > 1: if config.is_segmentation_model: assert isinstance(config, SegmentationModelBase) return EnsemblePipeline.create_from_checkpoints( path_to_checkpoints=checkpoint_paths, model_config=config) elif config.is_scalar_model: assert isinstance(config, ScalarModelBase) return ScalarEnsemblePipeline.create_from_checkpoint( paths_to_checkpoint=checkpoint_paths, config=config) else: raise NotImplementedError( "Cannot create inference pipeline for unknown model type") if len(checkpoint_paths) == 1: if config.is_segmentation_model: assert isinstance(config, SegmentationModelBase) return InferencePipeline.create_from_checkpoint( path_to_checkpoint=checkpoint_paths[0], model_config=config) elif config.is_scalar_model: assert isinstance(config, ScalarModelBase) return ScalarInferencePipeline.create_from_checkpoint( path_to_checkpoint=checkpoint_paths[0], config=config) else: raise NotImplementedError( "Cannot create ensemble pipeline for unknown model type") return None
def create_inference_pipeline(model_config: SegmentationModelBase, full_path_to_checkpoints: List[Path], use_gpu: bool = True) \ -> Tuple[FullImageInferencePipelineBase, SegmentationModelBase]: """ Create pipeline for inference, this can be a single model inference pipeline or an ensemble, if multiple checkpoints provided. :param model_config: Model config to use to create the pipeline. :param full_path_to_checkpoints: Checkpoints to use for model inference. :param use_gpu: If GPU should be used or not. """ model_config.use_gpu = use_gpu logging.info('test_config: ' + model_config.model_name) inference_pipeline: Optional[FullImageInferencePipelineBase] if len(full_path_to_checkpoints) == 1: inference_pipeline = InferencePipeline.create_from_checkpoint( path_to_checkpoint=full_path_to_checkpoints[0], model_config=model_config) else: inference_pipeline = EnsemblePipeline.create_from_checkpoints( path_to_checkpoints=full_path_to_checkpoints, model_config=model_config) if inference_pipeline is None: raise ValueError("Cannot create inference pipeline") return inference_pipeline, model_config
def create_inference_pipeline(config: ModelConfigBase, checkpoint_paths: List[Path]) -> Optional[InferencePipelineBase]: """ If multiple checkpoints are found in run_recovery then create EnsemblePipeline otherwise InferencePipeline. If no checkpoint files exist in the run recovery or current run checkpoint folder, None will be returned. :param config: Model related configs. :param epoch: The epoch for which to create pipeline for. :param run_recovery: RunRecovery data if applicable :return: FullImageInferencePipelineBase or ScalarInferencePipelineBase """ if not checkpoint_paths: return None if len(checkpoint_paths) > 1: if config.is_segmentation_model: assert isinstance(config, SegmentationModelBase) return EnsemblePipeline.create_from_checkpoints(path_to_checkpoints=checkpoint_paths, model_config=config) elif config.is_scalar_model: assert isinstance(config, ScalarModelBase) return ScalarEnsemblePipeline.create_from_checkpoint(paths_to_checkpoint=checkpoint_paths, config=config) else: raise NotImplementedError("Cannot create inference pipeline for unknown model type") if len(checkpoint_paths) == 1: if config.is_segmentation_model: assert isinstance(config, SegmentationModelBase) return InferencePipeline.create_from_checkpoint(path_to_checkpoint=checkpoint_paths[0], model_config=config) elif config.is_scalar_model: assert isinstance(config, ScalarModelBase) return ScalarInferencePipeline.create_from_checkpoint(path_to_checkpoint=checkpoint_paths[0], config=config) else: raise NotImplementedError("Cannot create ensemble pipeline for unknown model type") return None
def create_from_checkpoints(path_to_checkpoints: List[Path], model_config: SegmentationModelBase) -> EnsemblePipeline: pipelines = [] for i, path in enumerate(path_to_checkpoints): pipeline = InferencePipeline.create_from_checkpoint(path, model_config, i) if pipeline is None: logging.warning(f"Cannot create pipeline from path {path}; dropping it from ensemble") else: pipelines.append(pipeline) if not pipelines: raise ValueError("Could not create ANY pipelines from checkpoint paths") return EnsemblePipeline(model_config=model_config, inference_pipelines=pipelines)
def inference_identity( test_output_dirs: OutputFolderForTests, image_size: Any = (4, 5, 8), crop_size: Any = (5, 5, 5), shrink_by: Any = (0, 0, 0), num_classes: int = 5, create_mask: bool = True, extract_largest_foreground_connected_component: bool = False, is_ensemble: bool = False, posterior_smoothing_mm: Any = None) -> None: """ Test to make sure inference pipeline is identity preserving, ie: we can recreate deterministic model output, ensuring the patching and stitching is robust. """ # fix random seed np.random.seed(0) ground_truth_ids = list(map(str, range(num_classes))) # image to run inference on: The mock model passes the input image through, hence the input # image must have as many channels as we have classes (plus background), such that the output is # also a valid posterior. num_channels = num_classes + 1 image_channels = np.random.randn(num_channels, *list(image_size)) # create a random mask if required mask = np.round(np.random.uniform( size=image_size)).astype(np.int) if create_mask else None config = InferenceIdentityModel(shrink_by=shrink_by) config.crop_size = crop_size config.test_crop_size = crop_size config.image_channels = list(map(str, range(num_channels))) config.ground_truth_ids = ground_truth_ids config.posterior_smoothing_mm = posterior_smoothing_mm # We have to set largest_connected_component_foreground_classes after creating the model config, # because this parameter is not overridable and hence will not be set by GenericConfig's constructor. if extract_largest_foreground_connected_component: config.largest_connected_component_foreground_classes = [ (c, None) for c in ground_truth_ids ] # set expected posteriors expected_posteriors = torch.nn.functional.softmax( torch.tensor(image_channels), dim=0).numpy() # apply the mask if required if mask is not None: expected_posteriors = image_util.apply_mask_to_posteriors( expected_posteriors, mask) if posterior_smoothing_mm is not None: expected_posteriors = image_util.gaussian_smooth_posteriors( posteriors=expected_posteriors, kernel_size_mm=posterior_smoothing_mm, voxel_spacing_mm=(1, 1, 1)) # compute expected segmentation expected_segmentation = image_util.posteriors_to_segmentation( expected_posteriors) if extract_largest_foreground_connected_component: largest_component = image_util.extract_largest_foreground_connected_component( multi_label_array=expected_segmentation) # make sure the test data is accurate by checking if more than one component exists assert not np.array_equal(largest_component, expected_segmentation) expected_segmentation = largest_component # instantiate the model checkpoint = test_output_dirs.root_dir / "checkpoint.ckpt" create_model_and_store_checkpoint(config, checkpoint_path=checkpoint) # create single or ensemble inference pipeline inference_pipeline = InferencePipeline.create_from_checkpoint( path_to_checkpoint=checkpoint, model_config=config) assert inference_pipeline is not None full_image_inference_pipeline = EnsemblePipeline([inference_pipeline], config) \ if is_ensemble else inference_pipeline # compute full image inference results inference_result = full_image_inference_pipeline \ .predict_and_post_process_whole_image(image_channels=image_channels, mask=mask, voxel_spacing_mm=(1, 1, 1)) # Segmentation must have same size as input image assert inference_result.segmentation.shape == image_size assert inference_result.posteriors.shape == (num_classes + 1, ) + image_size # check that the posteriors and segmentations are as expected. Flatten to a list so that the error # messages are more informative. assert np.allclose(inference_result.posteriors, expected_posteriors) assert np.array_equal(inference_result.segmentation, expected_segmentation)