Exemplo n.º 1
0
    def __init__(self, server_env=False):

        #########################
        #    Preprocessing      #
        #########################

        self.root_dir = '/home/matthew/datasets/platelet-instance-3d'
        self.min_volume = 100

        #########################
        #         I/O           #
        #########################

        # Either 'cell' or 'organelle'
        self.label_type = 'organelle'

        # one out of [2, 3]. dimension the model operates in.
        self.dim = 3

        # one out of ['mrcnn', 'retina_net', 'retina_unet', 'detection_unet', 'ufrcnn'].
        self.model = 'mrcnn'

        DefaultConfigs.__init__(self, self.model, server_env, self.dim)

        # int [0 < dataset_size]. select n patients from dataset for prototyping.
        self.select_prototype_subset = None
        self.hold_out_test_set = True
        # including val set. will be 3/4 train, 1/4 val.
        self.n_train_val_data = 1

        # path to preprocessed data.
        self.input_df_name = 'info_df.pickle'
        self.pp_name = os.path.join('mdt', self.label_type, 'train')
        self.pp_data_path = os.path.join(self.root_dir, self.pp_name)
        self.pp_test_name = os.path.join('mdt', self.label_type, 'test')
        self.pp_test_data_path = os.path.join(self.root_dir, self.pp_test_name)

        # settings for deployment in cloud.
        if server_env:
            # path to preprocessed data.
            pp_root_dir = '/datasets/datasets_ramien/toy_exp/data'
            self.pp_name = os.path.join('mdt', self.label_type, 'train')
            self.pp_data_path = os.path.join(pp_root_dir, self.pp_name)
            self.pp_test_name = os.path.join('mdt', self.label_type, 'test')
            self.pp_test_data_path = os.path.join(pp_root_dir,
                                                  self.pp_test_name)
            self.select_prototype_subset = None

        #########################
        #      Data Loader      #
        #########################

        # select modalities from preprocessed data
        self.channels = [0]
        self.n_channels = len(self.channels)

        # patch_size to be used for training. pre_crop_size is the patch_size before data augmentation.
        self.pre_crop_size_3D = [288, 288, 40]
        self.patch_size_3D = [288, 288, 40]

        self.patch_size = self.patch_size_3D
        self.pre_crop_size = self.pre_crop_size_3D

        # ratio of free sampled batch elements before class balancing is triggered
        # (>0 to include "empty"/background patches.)
        self.batch_sample_slack = 0.2

        # set 2D network to operate in 3D images.
        self.merge_2D_to_3D_preds = False

        # feed +/- n neighbouring slices into channel dimension. set to None for no context.
        self.n_3D_context = None
        if self.n_3D_context is not None and self.dim == 2:
            self.n_channels *= (self.n_3D_context * 2 + 1)

        #########################
        #      Architecture      #
        #########################

        self.start_filts = 48 if self.dim == 2 else 24
        self.end_filts = self.start_filts * 4 if self.dim == 2 else self.start_filts * 2
        self.res_architecture = 'resnet50'  # 'resnet101', 'resnet50'
        self.norm = None  # one of None, 'instance_norm', 'batch_norm'
        # 0 for no weight decay
        self.weight_decay = 3e-8
        # which weights to exclude from weight decay, options: ["norm", "bias"].
        self.exclude_from_wd = ("norm", )

        # one of 'xavier_uniform', 'xavier_normal', or 'kaiming_normal', None (= default = 'kaiming_uniform')
        self.weight_init = None

        #########################
        #  Schedule / Selection #
        #########################

        self.num_epochs = 60
        self.num_train_batches = 50
        self.batch_size = 1

        self.do_validation = True
        # decide whether to validate on entire patient volumes (like testing) or sampled patches (like training)
        # the former is more accurate, while the latter is faster (depending on volume size)
        self.val_mode = 'val_sampling'  # one of 'val_sampling' , 'val_patient'
        if self.val_mode == 'val_patient':
            self.max_val_patients = None  # if 'None' iterates over entire val_set once.
        if self.val_mode == 'val_sampling':
            self.num_val_batches = 8

        # set dynamic_lr_scheduling to True to apply LR scheduling with below settings.
        self.dynamic_lr_scheduling = True
        self.lr_decay_factor = 0.7
        self.scheduling_patience = np.ceil(
            7200 / (self.num_train_batches * self.batch_size))
        self.scheduling_criterion = 'all_ap'
        self.scheduling_mode = 'min' if "loss" in self.scheduling_criterion else 'max'

        #########################
        #   Testing / Plotting  #
        #########################

        # set the top-n epochs to be saved for temporal averaging in testing.
        self.save_n_models = 5
        self.test_n_epochs = 5

        # set a minimum epoch number for saving in case of instabilities in the first phase of training.
        self.min_save_thresh = 0 if self.dim == 2 else 0

        self.report_score_level = ['patient', 'rois'
                                   ]  # choose list from 'patient', 'rois'
        self.class_dict = {1: 'all'}  # 0 is background.
        self.patient_class_of_interest = 1  # patient metrics are only plotted for one class.
        self.ap_match_ious = [0.1, 0.5, 0.7, 0.8, 0.9
                              ]  # list of ious to be evaluated for ap-scoring.

        self.model_selection_criteria = [
            'all_ap'
        ]  # criteria to average over for saving epochs.
        self.min_det_thresh = 0.1  # minimum confidence value to select predictions for evaluation.

        # threshold for clustering predictions together (wcs = weighted cluster scoring).
        # needs to be >= the expected overlap of predictions coming from one model (typically NMS threshold).
        # if too high, preds of the same object are separate clusters.
        self.wcs_iou = 1e-2

        self.plot_prediction_histograms = True
        self.plot_stat_curves = True

        #########################
        #   Data Augmentation   #
        #########################

        self.da_kwargs = {
            'do_elastic_deform':
            True,
            'alpha': (0., 150.),
            'sigma': (10., 30.),
            'do_rotation':
            False,
            'angle_x': (0., 2 * np.pi),
            'angle_y': (0., 0),
            'angle_z': (0., 0),
            'do_scale':
            False,
            'scale': (0.8, 1.1),
            'random_crop':
            False,
            'rand_crop_dist':
            (self.patch_size[0] / 2. - 3, self.patch_size[1] / 2. - 3),
            'border_mode_data':
            'constant',
            'border_cval_data':
            0,
            'order_data':
            1
        }

        if self.dim == 3:
            self.da_kwargs['do_elastic_deform'] = False
            self.da_kwargs['angle_x'] = (0, 0.0)
            self.da_kwargs['angle_y'] = (0, 0.0)  #must be 0!!
            self.da_kwargs['angle_z'] = (0., 2 * np.pi)

        #########################
        #   Add model specifics #
        #########################

        {
            'detection_unet': self.add_det_unet_configs,
            'mrcnn': self.add_mrcnn_configs,
            'ufrcnn': self.add_mrcnn_configs,
            'retina_net': self.add_mrcnn_configs,
            'retina_unet': self.add_mrcnn_configs,
        }[self.model]()
    def __init__(self, server_env=None):

        #########################
        #    Preprocessing      #
        #########################

        self.root_dir = '../../../Moscow_NRRD_Output'
        # self.root_dir = '/path/to/raw/data'
        self.raw_data_dir = '{}/nrrd_file'.format(self.root_dir)
        self.pp_dir_preq = '../../../Moscow_NRRD_Full-Numpy'
        self.pp_dir = '{}/pp_norm'.format(self.pp_dir_preq)
        # self.pp_dir = '{}/pp_norm'.format(self.root_dir)
        self.target_spacing = (0.7, 0.7, 1.25)

        #########################
        #         I/O           #
        #########################

        # one out of [2, 3]. dimension the model operates in.
        self.dim = 3

        # one out of ['mrcnn', 'retina_net', 'retina_unet', 'detection_unet', 'ufrcnn', 'detection_unet'].
        self.model = 'retina_net'
        # self.model = 'mrcnn'

        DefaultConfigs.__init__(self, self.model, server_env, self.dim)

        # int [0 < dataset_size]. select n patients from dataset for prototyping. If None, all data is used.
        self.select_prototype_subset = None

        # path to preprocessed data.
        self.pp_name = 'pp_norm'
        self.input_df_name = 'info_df.pickle'
        self.pp_data_path = '../Moscow_NRRD_Full-Numpy/{}'.format(self.pp_name)
        # self.pp_data_path = '/path/to/preprocessed/data/{}'.format(self.pp_name)
        self.pp_test_data_path = self.pp_data_path  #change if test_data in separate folder.

        # settings for deployment in cloud.
        if server_env:
            # path to preprocessed data.
            self.pp_name = 'pp_fg_slices'
            self.crop_name = 'pp_fg_slices_packed'
            self.pp_data_path = '/path/to/preprocessed/data/{}/{}'.format(
                self.pp_name, self.crop_name)
            self.pp_test_data_path = self.pp_data_path
            self.select_prototype_subset = None

        #########################
        #      Data Loader      #
        #########################

        # select modalities from preprocessed data
        self.channels = [0]
        self.n_channels = len(self.channels)

        # patch_size to be used for training. pre_crop_size is the patch_size before data augmentation.
        self.pre_crop_size_2D = [300, 300]
        self.patch_size_2D = [288, 288]
        self.pre_crop_size_3D = [156, 156, 96]
        self.patch_size_3D = [128, 128, 64]
        self.patch_size = self.patch_size_2D if self.dim == 2 else self.patch_size_3D
        self.pre_crop_size = self.pre_crop_size_2D if self.dim == 2 else self.pre_crop_size_3D

        # ratio of free sampled batch elements before class balancing is triggered
        # (>0 to include "empty"/background patches.)
        self.batch_sample_slack = 0.1

        # set 2D network to operate in 3D images.
        self.merge_2D_to_3D_preds = True

        # feed +/- n neighbouring slices into channel dimension. set to None for no context.
        self.n_3D_context = None
        if self.n_3D_context is not None and self.dim == 2:
            self.n_channels *= (self.n_3D_context * 2 + 1)

        #########################
        #      Architecture      #
        #########################

        self.start_filts = 48 if self.dim == 2 else 18
        self.end_filts = self.start_filts * 4 if self.dim == 2 else self.start_filts * 2
        self.res_architecture = 'resnet50'  # 'resnet101' , 'resnet50'
        self.norm = None  # one of None, 'instance_norm', 'batch_norm'
        self.weight_decay = 0

        # one of 'xavier_uniform', 'xavier_normal', or 'kaiming_normal', None (=default = 'kaiming_uniform')
        self.weight_init = None

        #########################
        #  Schedule / Selection #
        #########################

        # self.num_epochs = 150
        # self.num_epochs = 2 ##### debug
        self.num_epochs = 100
        # self.num_epochs = 5
        self.num_train_batches = 80
        # self.num_train_batches = 1
        # self.num_train_batches = 200 if self.dim == 2 else 200
        self.batch_size = 32 if self.dim == 2 else 15
        # self.batch_size = 2 ##### debug

        self.do_validation = True
        # decide whether to validate on entire patient volumes (like testing) or sampled patches (like training)
        # the former is morge accurate, while the latter is faster (depending on volume size)
        self.val_mode = 'val_sampling'  # one of 'val_sampling' , 'val_patient'
        if self.val_mode == 'val_patient':
            # self.max_val_patients = 50
            self.max_val_patients = 1
            # self.max_val_patients = 2  # if 'None' iterates over entire val_set once.
        if self.val_mode == 'val_sampling':
            # self.num_val_batches = 50
            # self.num_val_batches = 2
            self.max_val_patients = 1

        #########################
        #   Testing / Plotting  #
        #########################

        # set the top-n-epochs to be saved for temporal averaging in testing.
        self.save_n_models = 5
        self.test_n_epochs = 5
        # set a minimum epoch number for saving in case of instabilities in the first phase of training.
        self.min_save_thresh = 0 if self.dim == 2 else 0

        self.report_score_level = ['patient', 'rois'
                                   ]  # choose list from 'patient', 'rois'
        self.class_dict = {1: 'truenod'}  # 0 is background.
        self.patient_class_of_interest = 1  # patient metrics are only plotted for one class.
        self.ap_match_ious = [0.1
                              ]  # list of ious to be evaluated for ap-scoring.

        self.model_selection_criteria = [
            'truenod_ap'
        ]  # criteria to average over for saving epochs.
        self.min_det_thresh = 0.1  # minimum confidence value to select predictions for evaluation.

        # threshold for clustering predictions together (wcs = weighted cluster scoring).
        # needs to be >= the expected overlap of predictions coming from one model (typically NMS threshold).
        # if too high, preds of the same object are separate clusters.
        self.wcs_iou = 1e-5

        self.plot_prediction_histograms = True
        self.plot_stat_curves = True

        #########################
        #   Data Augmentation   #
        #########################

        self.da_kwargs = {
            'do_elastic_deform':
            True,
            'alpha': (0., 1500.),
            'sigma': (30., 50.),
            'do_rotation':
            True,
            'angle_x': (0., 2 * np.pi),
            'angle_y': (0., 0),
            'angle_z': (0., 0),
            'do_scale':
            True,
            'scale': (0.8, 1.1),
            'random_crop':
            False,
            'rand_crop_dist':
            (self.patch_size[0] / 2. - 3, self.patch_size[1] / 2. - 3),
            'border_mode_data':
            'constant',
            'border_cval_data':
            0,
            'order_data':
            1
        }

        if self.dim == 3:
            self.da_kwargs['do_elastic_deform'] = False
            self.da_kwargs['angle_x'] = (0, 0.0)
            self.da_kwargs['angle_y'] = (0, 0.0)  #must be 0!!
            self.da_kwargs['angle_z'] = (0., 2 * np.pi)

        #########################
        #   Add model specifics #
        #########################

        {
            'detection_unet': self.add_det_unet_configs,
            'mrcnn': self.add_mrcnn_configs,
            'ufrcnn': self.add_mrcnn_configs,
            'retina_net': self.add_mrcnn_configs,
            'retina_unet': self.add_mrcnn_configs,
        }[self.model]()
Exemplo n.º 3
0
    def __init__(self):

        self.gpu = '4'
        os.environ['CUDA_VISIBLE_DEVICES'] = self.gpu

        #########################
        #         I/O           #
        #########################

        # one out of [2, 3]. dimension the model operates in.
        self.dim = 3

        # one out of ['mrcnn', 'seg_mrcnn','retina_net', 'retina_unet', 'detection_unet', 'ufrcnn', 'detection_unet'].
        self.model = 'mrcnn'

        DefaultConfigs.__init__(self, self.model, self.dim)

        # path to preprocessed data.
        self.pp_name = 'abus_npy'
        self.input_df_name = 'info_df.pickle'
        self.input_id_name = 'fold_ids.pickle'
        self.pid_pth = 'fold_ids.txt'
        self.pp_data_path = '/shenlab/lab_stor6/yuezhou/ABUSdata/{}/'.format(
            self.pp_name)
        self.pp_test_data_path = self.pp_data_path  #change if test_data in separate folder.

        #########################
        #      Data Loader      #
        #########################

        # data aug in training
        self.data_aug_training = False
        # select modalities from preprocessed data
        self.channels = [0]
        self.n_channels = len(self.channels)

        # patch_size to be used for training. pre_crop_size is the patch_size before data augmentation.
        #self.pre_crop_size_2D = [300, 300]
        #self.patch_size_2D = [288, 288]
        if self.data_aug_training == True:
            self.pre_crop_size_3D = [72, 144, 144]
        else:
            self.pre_crop_size_3D = [64, 128, 128]
        self.patch_size_3D = [64, 128, 128]  #[128, 128, 64]
        self.patch_size = self.patch_size_3D  #self.patch_size_2D if self.dim == 2 else self.patch_size_3D
        self.pre_crop_size = self.pre_crop_size_3D  #self.pre_crop_size_2D if self.dim == 2 else self.pre_crop_size_3D

        # ratio of free sampled batch elements before class balancing is triggered
        # (>0 to include "empty"/background patches.)
        self.batch_sample_slack = 0.5  #0.2

        #########################
        #      Architecture      #
        #########################

        self.backbone_path = 'models/backbone_vnet.py'
        self.multi_scale_det = False
        self.start_filts = 48 if self.dim == 2 else 18
        if 'vnet' in self.backbone_path:
            if self.multi_scale_det == False:
                self.end_filts = [32, 64, 128, 256, 256]
            else:
                self.end_filts = [
                    36, 36, 36, 36, 36
                ]  #self.start_filts * 4 if self.dim == 2 else self.start_filts * 2
        if 'fpn' in self.backbone_path:
            self.end_filts = [
                36, 36, 36, 36, 36
            ]  #self.start_filts * 4 if self.dim == 2 else self.start_filts * 2
        self.res_architecture = 'resnet50'  # 'resnet101' , 'resnet50'
        self.norm = None  # one of None, 'instance_norm', 'batch_norm'
        self.weight_decay = 0

        # one of 'xavier_uniform', 'xavier_normal', or 'kaiming_normal', None (=default = 'kaiming_uniform')
        self.weight_init = None

        #########################
        #  Schedule / Selection #
        #########################
        self.debug = 0
        if self.debug == 1:
            self.num_epochs = 2
            self.num_train_batches = 2  #2 if self.dim == 2 else 2
            self.batch_size = 2  #20 if self.dim == 2 else 2
            self.n_workers = 1
        else:
            self.num_epochs = 250
            self.num_train_batches = 200 if self.dim == 2 else 200
            self.batch_size = 20 if self.dim == 2 else 2
            self.n_workers = 16

        self.do_validation = True
        # decide whether to validate on entire patient volumes (like testing) or sampled patches (like training)
        # the former is morge accurate, while the latter is faster (depending on volume size)
        self.val_mode = 'val_sampling'  # this is a bug only sampling one of 'val_sampling' , 'val_patient'
        if self.debug == 1:
            self.num_val_batches = 2
        else:
            self.num_val_batches = None
        self.new_data = True
        self.text_for_next = False
        #########################
        # loss  #
        #########################
        # in ['BCE','roiDice','mapDice']
        self.mask_loss_flag = 'BCE'
        # in ['seg-only','mrcnn-only','frcnn-only','mrcnn-seg','frcnn-seg','mrcnn-seg-fusion']
        self.loss_flag = 'mrcnn-seg-fusion'
        #########################
        # fusion method  #
        #########################
        #fusion in prob or feature
        self.fusion_prob_feature = 'prob'
        # in ['cat-only','add-only','weight-cat','weight-add']
        self.fusion_method = 'weight-add'
        # in ['before','after']
        self.fusion_feature_method = 'after'
        #fusion conoral number
        self.fusion_conv_num = 'no'  #'no' or 'more' or 'less' or 'one'

        #########################
        #   Testing / Plotting  #
        #########################
        # show detection box score
        self.show_det_source_th = 0.1
        # patch stride during testing
        self.testing_patch_stride = [64, 128, 128]
        # set the top-n-epochs to be saved for temporal averaging in testing.
        self.save_n_models = 5
        self.test_n_epochs = 5
        self.testing_epoch_num = 0
        # test the best epoch or the last epoch
        self.test_last_epoch = False
        # show image
        if self.debug == 1:
            self.show_train_images = 1
            self.show_val_images = 1
        else:
            self.show_train_images = 5
            self.show_val_images = 5

        #select detected box score
        #self.source_th = 0.1

        # set a minimum epoch number for saving in case of instabilities in the first phase of training.
        self.min_save_thresh = 0 if self.dim == 2 else 0

        self.report_score_level = ['patient', 'rois'
                                   ]  # choose list from 'patient', 'rois'
        self.class_dict = {
            1: 'mass'
        }  #{1: 'benign', 2: 'malignant'}  # 0 is background.
        self.patient_class_of_interest = 1  # patient metrics are only plotted for one class.
        self.ap_match_ious = [0.1
                              ]  # list of ious to be evaluated for ap-scoring.

        #['val_dice_seg','val_dice_mask','val_dice_fusion']#criteria to average over for saving epochs.
        if 'seg' in self.loss_flag and 'seg-only' not in self.loss_flag:
            self.model_selection_criteria = [
                'val_dice_fusion'
            ]  #criteria to average over for saving epochs.
        if 'seg-only' in self.loss_flag:
            self.model_selection_criteria = ['val_deice_seg']
        if 'seg' not in self.loss_flag:
            self.model_selection_criteria = ['val_precision', 'val_recall']
        self.min_det_thresh = 0.1  # minimum confidence value to select predictions for evaluation.

        #########################
        #   Data Augmentation   #
        #########################

        self.da_kwargs = {
            'do_elastic_deform':
            True,
            'alpha': (0., 1500.),
            'sigma': (30., 50.),
            'do_rotation':
            True,
            'angle_x': (0., 2 * np.pi),
            'angle_y': (0., 0),
            'angle_z': (0., 0),
            'do_scale':
            True,
            'scale': (0.8, 1.1),
            'random_crop':
            False,
            'rand_crop_dist':
            (self.patch_size[0] / 2. - 3, self.patch_size[1] / 2. - 3),
            'border_mode_data':
            'constant',
            'border_cval_data':
            0,
            'order_data':
            1
        }

        if self.dim == 3:
            self.da_kwargs['do_elastic_deform'] = False
            self.da_kwargs['angle_x'] = (0, 0.0)
            self.da_kwargs['angle_y'] = (0, 0.0)  #must be 0!!
            self.da_kwargs['angle_z'] = (0., 2 * np.pi)

        #########################
        #   Add model specifics #
        #########################

        {
            'detection_unet': self.add_det_unet_configs,
            'mrcnn': self.add_mrcnn_configs,
            'ufrcnn': self.add_mrcnn_configs,
            'retina_net': self.add_mrcnn_configs,
            'retina_unet': self.add_mrcnn_configs,
        }[self.model]()
Exemplo n.º 4
0
    def __init__(self, server_env=None):

        #########################
        #    Preprocessing      #
        #########################

        self.root_dir = '/media/gregor/HDD2TB/data/toy_mdt'

        #########################
        #         I/O           #
        #########################

        # one out of [2, 3]. dimension the model operates in.
        self.dim = 2

        # one out of ['mrcnn', 'retina_net', 'retina_unet', 'detection_unet', 'ufrcnn', 'detection_unet'].
        self.model = 'mrcnn'

        DefaultConfigs.__init__(self, self.model, server_env, self.dim)

        # int [0 < dataset_size]. select n patients from dataset for prototyping.
        self.select_prototype_subset = None
        self.hold_out_test_set = True
        self.n_train_data = 2500

        # choose one of the 3 toy experiments described in https://arxiv.org/pdf/1811.08661.pdf
        # one of ['donuts_shape', 'donuts_pattern', 'circles_scale'].
        toy_mode = 'donuts_shape_nonoise_dia12'

        # path to preprocessed data.
        self.input_df_name = 'info_df.pickle'
        self.pp_name = os.path.join(toy_mode, 'train')
        self.pp_data_path = os.path.join(self.root_dir, self.pp_name)
        self.pp_test_name = os.path.join(toy_mode, 'test')
        self.pp_test_data_path = os.path.join(self.root_dir, self.pp_test_name)

        # settings for deployment in cloud.
        if server_env:
            # path to preprocessed data.
            pp_root_dir = '/datasets/datasets_ramien/toy_exp/data'
            self.pp_name = os.path.join(toy_mode, 'train')
            self.pp_data_path = os.path.join(pp_root_dir, self.pp_name)
            self.pp_test_name = os.path.join(toy_mode, 'test')
            self.pp_test_data_path = os.path.join(pp_root_dir,
                                                  self.pp_test_name)
            self.select_prototype_subset = None

        #########################
        #      Data Loader      #
        #########################

        # select modalities from preprocessed data
        self.channels = [0]
        self.n_channels = len(self.channels)

        # patch_size to be used for training. pre_crop_size is the patch_size before data augmentation.
        self.pre_crop_size_2D = [320, 320]
        self.patch_size_2D = [320, 320]

        self.patch_size = self.patch_size_2D if self.dim == 2 else self.patch_size_3D
        self.pre_crop_size = self.pre_crop_size_2D if self.dim == 2 else self.pre_crop_size_3D

        # ratio of free sampled batch elements before class balancing is triggered
        # (>0 to include "empty"/background patches.)
        self.batch_sample_slack = 0.2

        # set 2D network to operate in 3D images.
        self.merge_2D_to_3D_preds = False

        # feed +/- n neighbouring slices into channel dimension. set to None for no context.
        self.n_3D_context = None
        if self.n_3D_context is not None and self.dim == 2:
            self.n_channels *= (self.n_3D_context * 2 + 1)

        #########################
        #      Architecture      #
        #########################

        self.start_filts = 48 if self.dim == 2 else 18
        self.end_filts = self.start_filts * 4 if self.dim == 2 else self.start_filts * 2
        self.res_architecture = 'resnet50'  # 'resnet101' , 'resnet50'
        self.norm = None  # one of None, 'instance_norm', 'batch_norm'
        self.weight_decay = 0

        # one of 'xavier_uniform', 'xavier_normal', or 'kaiming_normal', None (=default = 'kaiming_uniform')
        self.weight_init = None

        #########################
        #  Schedule / Selection #
        #########################

        self.num_epochs = 24
        self.num_train_batches = 100 if self.dim == 2 else 200
        self.batch_size = 20 if self.dim == 2 else 8

        self.do_validation = True
        # decide whether to validate on entire patient volumes (like testing) or sampled patches (like training)
        # the former is morge accurate, while the latter is faster (depending on volume size)
        self.val_mode = 'val_patient'  # one of 'val_sampling' , 'val_patient'
        if self.val_mode == 'val_patient':
            self.max_val_patients = None  # if 'None' iterates over entire val_set once.
        if self.val_mode == 'val_sampling':
            self.num_val_batches = 50

        #########################
        #   Testing / Plotting  #
        #########################

        # set the top-n-epochs to be saved for temporal averaging in testing.
        self.save_n_models = 5
        self.test_n_epochs = 5

        # set a minimum epoch number for saving in case of instabilities in the first phase of training.
        self.min_save_thresh = 0 if self.dim == 2 else 0

        self.report_score_level = ['patient', 'rois'
                                   ]  # choose list from 'patient', 'rois'
        self.class_dict = {1: 'benign', 2: 'malignant'}  # 0 is background.
        self.patient_class_of_interest = 2  # patient metrics are only plotted for one class.
        self.ap_match_ious = [0.1
                              ]  # list of ious to be evaluated for ap-scoring.

        self.model_selection_criteria = [
            'benign_ap', 'malignant_ap'
        ]  # criteria to average over for saving epochs.
        self.min_det_thresh = 0.1  # minimum confidence value to select predictions for evaluation.

        # threshold for clustering predictions together (wcs = weighted cluster scoring).
        # needs to be >= the expected overlap of predictions coming from one model (typically NMS threshold).
        # if too high, preds of the same object are separate clusters.
        self.wcs_iou = 1e-5

        self.plot_prediction_histograms = True
        self.plot_stat_curves = False

        #########################
        #   Data Augmentation   #
        #########################

        self.da_kwargs = {
            'do_elastic_deform':
            True,
            'alpha': (0., 1500.),
            'sigma': (30., 50.),
            'do_rotation':
            True,
            'angle_x': (0., 2 * np.pi),
            'angle_y': (0., 0),
            'angle_z': (0., 0),
            'do_scale':
            True,
            'scale': (0.8, 1.1),
            'random_crop':
            False,
            'rand_crop_dist':
            (self.patch_size[0] / 2. - 3, self.patch_size[1] / 2. - 3),
            'border_mode_data':
            'constant',
            'border_cval_data':
            0,
            'order_data':
            1
        }

        if self.dim == 3:
            self.da_kwargs['do_elastic_deform'] = False
            self.da_kwargs['angle_x'] = (0, 0.0)
            self.da_kwargs['angle_y'] = (0, 0.0)  #must be 0!!
            self.da_kwargs['angle_z'] = (0., 2 * np.pi)

        #########################
        #   Add model specifics #
        #########################

        {
            'detection_unet': self.add_det_unet_configs,
            'mrcnn': self.add_mrcnn_configs,
            'ufrcnn': self.add_mrcnn_configs,
            'ufrcnn_surrounding': self.add_mrcnn_configs,
            'retina_net': self.add_mrcnn_configs,
            'retina_unet': self.add_mrcnn_configs,
            'prob_detector': self.add_mrcnn_configs,
        }[self.model]()
    def __init__(self, server_env=False):

        #Change some things if debugging
        #Set always to false, it is set to true by others
        self.debugging = False

        #########################
        #    Preprocessing      #
        #########################

        #Already done!
        self.root_dir = r'../'
        #self.raw_data_dir = os.path.join(self.root_dir, './')
        self.pp_dir = os.path.join(self.root_dir, 'out')
        self.target_spacing = (0.5, 0.5, 3.)

        #########################
        #         I/O           #
        #########################

        # one out of [2, 3]. dimension the model operates in.
        self.dim = 3

        # one out of ['mrcnn', 'retina_net', 'retina_unet', 'detection_unet', 'ufrcnn'].
        # Only retina_unet can be used with the current model setup
        self.model = 'retina_unet'
        self.model_path = '././'

        DefaultConfigs.__init__(self, self.model, server_env, self.dim)

        # int [0 < dataset_size]. select n patients from dataset for prototyping. If None, all data is used.
        self.select_prototype_subset = None

        # path to preprocessed data.
        self.pp_name = 'out'
        self.input_df_name = 'info_df.pickle'
        self.pp_data_path = os.path.join(self.root_dir, self.pp_name)
        self.pp_test_data_path = self.pp_data_path  #change if test_data in separate folder.

        # settings for deployment in cloud.
        if server_env:
            # path to preprocessed data.
            self.pp_name = ''
            self.crop_name = ''
            self.pp_data_path = ''
            self.pp_test_data_path = self.pp_data_path
            self.select_prototype_subset = None

        #########################
        #      Data Loader      #
        #########################

        #Use a single CV split
        self.n_cv_splits = 5

        # select modalities from preprocessed data
        self.channels = list(range(8))
        self.n_channels = len(self.channels)

        # patch_size to be used for training. pre_crop_size is the patch_size before data augmentation.
        self.pre_crop_size_2D = [160, 160]
        self.patch_size_2D = [160, 160]
        self.pre_crop_size_3D = [160, 160, 24]
        self.patch_size_3D = [160, 160, 24]
        self.patch_size = self.patch_size_2D if self.dim == 2 else self.patch_size_3D
        self.pre_crop_size = self.pre_crop_size_2D if self.dim == 2 else self.pre_crop_size_3D

        # ratio of free sampled batch elements before class balancing is triggered
        # (>0 to include "empty"/background patches.)
        self.batch_sample_slack = 0.2

        # set 2D network to operate in 3D images.
        self.merge_2D_to_3D_preds = self.dim == 2

        # feed +/- n neighbouring slices into channel dimension. set to None for no context.
        self.n_3D_context = 3
        if self.n_3D_context is not None and self.dim == 2:
            self.n_channels *= (self.n_3D_context * 2 + 1)

        #########################
        #      Architecture      #
        #########################

        self.start_filts = 48 if self.dim == 2 else 15
        self.end_filts = self.start_filts * 4 if self.dim == 2 else self.start_filts * 2
        self.n_blocks = [3, 7, 21, 3]  #[3, 4, 23, 3] 'resnet101'
        self.norm = 'batch_norm'  # one of None, 'instance_norm', 'batch_norm'
        # 0 for no weight decay
        self.weight_decay = 0

        # one of 'xavier_uniform', 'xavier_normal', or 'kaiming_normal', None (=default = 'kaiming_uniform')
        self.weight_init = None

        #########################
        #  Schedule / Selection #
        #########################

        self.num_epochs = 115  #99
        self.num_train_batches = 120 if self.dim == 2 else 120
        self.batch_size = 20 if self.dim == 2 else 6

        self.do_validation = True
        # decide whether to validate on entire patient volumes (like testing) or sampled patches (like training)
        # the former is more accurate, while the latter is faster (depending on volume size)
        self.val_mode = 'val_sampling'  # one of 'val_sampling' , 'val_patient'
        if self.val_mode == 'val_patient':
            self.max_val_patients = 50  # if 'None' iterates over entire val_set once.
        if self.val_mode == 'val_sampling':
            self.num_val_batches = 50

        self.optimizer = "Adam"

        # set dynamic_lr_scheduling to True to apply LR scheduling with below settings.
        self.dynamic_lr_scheduling = False
        self.lr_decay_factor = 0.25
        self.scheduling_patience = np.ceil(
            16000 / (self.num_train_batches * self.batch_size))
        self.scheduling_criterion = 'malignant_ap'
        self.scheduling_mode = 'min' if "loss" in self.scheduling_criterion else 'max'

        #########################
        #   Testing / Plotting  #
        #########################

        # General matching IOU
        self.match_iou = 1e-5

        # set the top-n-epochs to be saved for temporal averaging in testing.
        self.save_n_models = 5
        self.test_n_epochs = 5

        # If true, all epochs (not only best k) are kept
        self.keep_all_epochs = False

        # use 'train', 'val' or 'test' data for testing
        self.test_subset = 'test'

        # Drop some channels during test?
        #T2:[0], B500,B800+,ADC:[1,2,3], ktrans:[4], Perf:[5,6,7]
        self.drop_channels_test = []

        # use a temporal ensemble of a list of epochs, or None, to use instead the best validation cps
        def steps(start, end, n):
            if n < 2: raise Exception("Behaviour not defined for n<2")
            step = (end - start) / float(n - 1)
            return [int(round(start + x * step)) for x in range(n)]

        self.test_checkpoints = None  #steps(25, self.num_epochs, self.test_n_epochs)

        # set a minimum epoch number for saving in case of instabilities in the first phase of training.
        self.min_save_thresh = 0 if self.dim == 2 else 0
        self.scan_det_thresh = False  #Used in evaluator > return_metrics

        self.report_score_level = ['patient', 'rois'
                                   ]  # choose list from 'patient', 'rois'
        self.class_dict = {
            1: 'benign',
            2: 'GGG_1',
            3: 'GGG_2',
            4: 'GGG_3'
        }  # 0 is background.
        self.patient_class_of_interest = 3  # patient metrics are only plotted for one class.
        self.ap_match_ious = [self.match_iou
                              ]  # list of ious to be evaluated for ap-scoring.

        # criteria to average over for saving epochs.
        self.model_selection_criteria = [
            'GGG_%d_%s' % (g, metric) for g in range(1, 4)
            for metric in ['ap']
        ] + ['benign_ap']
        self.min_det_thresh = 0.  # minimum confidence value to select predictions for evaluation.

        #Use prostatex test set too with masked classification loss?
        self.use_prostatex_test = True

        # evaluates average precision per image and averages over images. instead computing one ap over data set.
        self.per_patient_ap = False

        # threshold for clustering 2D box predictions to 3D Cubes. Overlap is computed in XY.
        self.merge_3D_iou = self.match_iou

        #Custom dict preprocessing function to transform classes 10,1 -> 0, 2,3,4,5 -> 1, 20 -> 20
        #Please note that class 20 is a very special class for which bce loss is masked!
        #correspondance_dict= {0:0, 10:0, 1:0, 2:1, 3:1, 4:1, 5:1, 20:20}
        correspondance_dict = {
            0: 0,
            10: 0,
            1: 1,
            2: 2,
            3: 3,
            4: 3,
            5: 3,
            20: 20
        }

        def modify_class_target(class_targets):
            return [correspondance_dict[target] for target in class_targets]

        self.modify_class_target_fn = modify_class_target

        # threshold for clustering predictions together (wcs = weighted cluster scoring).
        # needs to be >= the expected overlap of predictions coming from one model (typically NMS threshold).
        # if too high, preds of the same object are separate clusters.
        self.wcs_iou = 1e-5

        self.plot_prediction_histograms = False
        self.plot_stat_curves = False

        # if True, test data lies in a separate folder and is not part of the cross validation.
        self.hold_out_test_set = True

        # if hold_out_test_set provided, ensemble predictions over models of all trained cv-folds.
        # implications for hold-out test sets: if True, evaluate folds separately on the test set, aggregate only the
        # evaluations. if False, aggregate the raw predictions across all folds, then evaluate.
        self.ensemble_folds = True

        #########################
        #   Data Augmentation   #
        #########################

        self.da_kwargs = {
            'do_elastic_deform':
            True,
            'alpha': (0., 300.),
            'sigma': (20., 40.),
            'do_rotation':
            True,
            'angle_x': (-np.pi / 30., np.pi / 30),
            'angle_y': (-np.pi / 20., np.pi / 20) if self.dim == 2 else
            (0., 0.),  #must be 0!!
            'angle_z': (-np.pi / 20., np.pi / 20),
            'do_scale':
            True,
            'scale': (1 / 1.15, 1.15),
            'random_crop':
            False,
            'rand_crop_dist':
            (self.patch_size[0] / 2. - 3, self.patch_size[1] / 2. - 3),
            'border_mode_data':
            'constant',
            'border_cval_data':
            0,
            'order_data':
            3
        }

        self.test_aug = False  #Seems to be true by default
        self.mirror_axes = (1, )

        #Custom augmentation: drop a channel with some prob
        #Do not drop T2 nor final channels & consider perfusion channels as one
        # 0:T2, 1:B500, 2:B800, 3:ADC, 4:ktrans,
        # 5:Prostate mask, 6:CZ mask, 7: PZ mask
        self.droppable_channels = [[1], [2], [3], [4]]
        self.channel_drop_p = 0.05

        #########################
        #   Add model specifics #
        #########################

        {
            'detection_unet': self.add_det_unet_configs,
            'mrcnn': self.add_mrcnn_configs,
            'ufrcnn': self.add_mrcnn_configs,
            'retina_net': self.add_mrcnn_configs,
            'retina_unet': self.add_mrcnn_configs,
            'retina_unet_coral': self.add_mrcnn_configs,
        }[self.model]()
Exemplo n.º 6
0
    def __init__(self, server_env=None):
        #########################
        #    Preprocessing      #
        #########################

        self.root_dir = '/home/gregor/datasets/toy_mdt'

        #########################
        #         I/O           #
        #########################


        # one out of [2, 3]. dimension the model operates in.
        self.dim = 2
        DefaultConfigs.__init__(self, server_env, self.dim)
        # one out of ['mrcnn', 'retina_net', 'retina_unet', 'detection_unet', 'ufrcnn'].

        self.model = 'mrcnn'

        self.model_path = 'models/{}.py'.format(self.model if not 'retina' in self.model else 'retina_net')
        self.model_path = os.path.join(self.source_dir, self.model_path)
        # int [0 < dataset_size]. select n patients from dataset for prototyping.
        self.select_prototype_subset = None

        self.hold_out_test_set = True

        # including val set. will be 3/4 train, 1/4 val.
        self.n_train_val_data = 2500

        # choose one of the 3 toy experiments described in https://arxiv.org/pdf/1811.08661.pdf
        # one of ['donuts_shape', 'donuts_pattern', 'circles_scale'].
        toy_mode = 'donuts_shape_noise'

        # path to preprocessed data.
        self.info_df_name = 'info_df.pickle'
        self.pp_name = os.path.join(toy_mode, 'train')
        self.data_sourcedir = os.path.join(self.root_dir, self.pp_name)
        self.pp_test_name = os.path.join(toy_mode, 'test')
        self.test_data_sourcedir = os.path.join(self.root_dir, self.pp_test_name)

        # settings for deployment in cloud.
        if server_env:
            # path to preprocessed data.
            pp_root_dir = '/datasets/datasets_ramien/toy_exp/data'
            self.pp_name = os.path.join(toy_mode, 'train')
            self.data_sourcedir = os.path.join(pp_root_dir, self.pp_name)
            self.pp_test_name = os.path.join(toy_mode, 'test')
            self.test_data_sourcedir = os.path.join(pp_root_dir, self.pp_test_name)
            self.select_prototype_subset = None

        #########################
        #      Data Loader      #
        #########################

        # select modalities from preprocessed data
        self.channels = [0]
        self.n_channels = len(self.channels)
        self.plot_bg_chan = 0

        # patch_size to be used for training. pre_crop_size is the patch_size before data augmentation.
        self.pre_crop_size_2D = [320, 320]
        self.patch_size_2D = [320, 320]

        self.patch_size = self.patch_size_2D if self.dim == 2 else self.patch_size_3D
        self.pre_crop_size = self.pre_crop_size_2D if self.dim == 2 else self.pre_crop_size_3D

        # ratio of free sampled batch elements before class balancing is triggered
        # (>0 to include "empty"/background patches.)
        self.batch_random_ratio = 0.2

        # set 2D network to operate in 3D images.
        self.merge_2D_to_3D_preds = False

        #########################
        #      Architecture      #
        #########################

        self.start_filts = 48 if self.dim == 2 else 18
        self.end_filts = self.start_filts * 4 if self.dim == 2 else self.start_filts * 2
        self.res_architecture = 'resnet50' # 'resnet101' , 'resnet50'
        self.norm = "instance_norm" # one of None, 'instance_norm', 'batch_norm'
        # one of 'xavier_uniform', 'xavier_normal', or 'kaiming_normal', None (=default = 'kaiming_uniform')
        self.weight_init = "xavier_uniform"

        # compatibility
        self.regression_n_features = 1
        self.num_classes = 2 # excluding bg
        self.num_seg_classes = 3 # incl bg

        #########################
        #  Schedule / Selection #
        #########################

        self.num_epochs = 26

        self.num_train_batches = 100 if self.dim == 2 else 200
        self.batch_size = 20 if self.dim == 2 else 8

        self.do_validation = True
        # decide whether to validate on entire patient volumes (like testing) or sampled patches (like training)
        # the former is morge accurate, while the latter is faster (depending on volume size)
        self.val_mode = 'val_patient' # one of 'val_sampling' , 'val_patient'
        if self.val_mode == 'val_patient':
            self.max_val_patients = "all"  # if 'None' iterates over entire val_set once.
        if self.val_mode == 'val_sampling':
            self.num_val_batches = 50

        self.optimizer = "ADAMW"

        # set dynamic_lr_scheduling to True to apply LR scheduling with below settings.
        self.dynamic_lr_scheduling = True
        self.lr_decay_factor = 0.25

        self.scheduling_patience = np.ceil(4800 / (self.num_train_batches * self.batch_size))
        self.scheduling_criterion = 'donuts_ap'
        self.scheduling_mode = 'min' if "loss" in self.scheduling_criterion else 'max'
        self.weight_decay = 1e-5
        self.exclude_from_wd = ["norm"]
        self.clip_norm = 200

        #########################
        #   Testing / Plotting  #
        #########################

        self.ensemble_folds = False

        # set the top-n-epochs to be saved for temporal averaging in testing.
        self.save_n_models = 5
        self.test_n_epochs = 5
        self.test_aug_axes = (0, 1, (0, 1))
        self.n_test_plots = 2
        self.clustering = "wbc"
        self.clustering_iou = 1e-5
        # set a minimum epoch number for saving in case of instabilities in the first phase of training.
        self.min_save_thresh = 0 if self.dim == 2 else 0

        self.report_score_level = ['patient', 'rois']  # choose list from 'patient', 'rois'
        self.class_labels = [Label(0, 'bg', (*self.white, 0.)),
                             Label(1, 'circles', (*self.orange, .9)),
                             Label(2, 'donuts', (*self.blue, .9)),]
        if self.class_specific_seg:
            self.seg_labels = self.class_labels

        self.box_type2label = {label.name: label for label in self.box_labels}
        self.class_id2label = {label.id: label for label in self.class_labels}
        self.class_dict = {label.id: label.name for label in self.class_labels if label.id != 0}

        self.seg_id2label = {label.id: label for label in self.seg_labels}
        self.cmap = {label.id: label.color for label in self.seg_labels}

        self.metrics = ["ap", "auc", "dice"]
        self.patient_class_of_interest = 2  # patient metrics are only plotted for one class.
        self.ap_match_ious = [0.1]  # list of ious to be evaluated for ap-scoring.

        self.model_selection_criteria = {name + "_ap": 1. for name in self.class_dict.values()}# criteria to average over for saving epochs.
        self.min_det_thresh = 0.1  # minimum confidence value to select predictions for evaluation.


        self.plot_prediction_histograms = True
        self.plot_stat_curves = False
        self.plot_class_ids = True

        #########################
        #   Data Augmentation   #
        #########################
        self.do_aug = False
        self.da_kwargs={
        'do_elastic_deform': True,
        'alpha':(0., 1500.),
        'sigma':(30., 50.),
        'do_rotation':True,
        'angle_x': (0., 2 * np.pi),
        'angle_y': (0., 0),
        'angle_z': (0., 0),
        'do_scale': True,
        'scale':(0.8, 1.1),
        'random_crop':False,
        'rand_crop_dist':  (self.patch_size[0] / 2. - 3, self.patch_size[1] / 2. - 3),
        'border_mode_data': 'constant',
        'border_cval_data': 0,
        'order_data': 1
        }

        if self.dim == 3:
            self.da_kwargs['do_elastic_deform'] = False
            self.da_kwargs['angle_x'] = (0, 0.0)
            self.da_kwargs['angle_y'] = (0, 0.0) #must be 0!!
            self.da_kwargs['angle_z'] = (0., 2 * np.pi)


        #########################
        #   Add model specifics #
        #########################

        {'detection_fpn': self.add_det_fpn_configs,
         'mrcnn': self.add_mrcnn_configs,
         'retina_net': self.add_mrcnn_configs,
         'retina_unet': self.add_mrcnn_configs,
        }[self.model]()
    def __init__(self, server_env=False):

        #########################
        #      Predictions      #
        #########################

        self.patient_path = None
        self.output_dir = None

        #########################
        #    Preprocessing      #
        #########################

        datasets_dir = os.getenv('MDT_DATASETS_DIR')
        self.root_dir = os.path.join(datasets_dir, 'MDT-LIDC-IDRI')
        self.raw_data_dir = f'{self.root_dir}/NRRDs'
        self.pp_dir = os.path.join(datasets_dir, 'MDT-PP')
        self.target_spacing = (0.7, 0.7, 1.25)

        #########################
        #         I/O           #
        #########################

        # one out of [2, 3]. dimension the model operates in.
        self.dim = 3

        # one out of ['mrcnn', 'retina_net', 'retina_unet', 'detection_unet', 'ufrcnn'].
        self.model = 'retina_unet'

        DefaultConfigs.__init__(self, self.model, server_env, self.dim)

        # int [0 < dataset_size]. select n patients from dataset for prototyping. If None, all data is used.
        self.select_prototype_subset = None

        # path to preprocessed data.
        self.pp_name = 'lidc_mdt'
        self.input_df_name = 'info_df.pickle'
        self.pp_data_path = self.pp_dir
        self.pp_test_data_path = self.pp_data_path  #change if test_data in separate folder.

        # settings for deployment in cloud.
        if server_env:
            # path to preprocessed data.
            self.pp_name = 'lidc_mdt_npz'
            self.crop_name = 'pp_fg_slices_packed'
            self.pp_data_path = '/datasets/datasets_ramien/lidc_exp/data/{}'.format(
                self.pp_name)
            self.pp_test_data_path = self.pp_data_path
            self.select_prototype_subset = None

        #########################
        #      Data Loader      #
        #########################

        self.gan_dataset = False
        self.train_set_proportion = 1.0

        self.n_cv_splits = 10  # 10 to split data 80 train - 10 val - 10 test

        # select modalities from preprocessed data
        self.channels = [0]
        self.n_channels = len(self.channels)

        # patch_size to be used for training. pre_crop_size is the patch_size before data augmentation.
        self.pre_crop_size_2D = [300, 300]
        self.patch_size_2D = [288, 288]
        self.pre_crop_size_3D = [156, 156, 96]
        self.patch_size_3D = [128, 128, 64]
        self.patch_size = self.patch_size_2D if self.dim == 2 else self.patch_size_3D
        self.pre_crop_size = self.pre_crop_size_2D if self.dim == 2 else self.pre_crop_size_3D

        # ratio of free sampled batch elements before class balancing is triggered
        # (>0 to include "empty"/background patches.)
        self.batch_sample_slack = 0.2

        # set 2D network to operate in 3D images.
        self.merge_2D_to_3D_preds = self.dim == 2

        # feed +/- n neighbouring slices into channel dimension. set to None for no context.
        self.n_3D_context = None
        if self.n_3D_context is not None and self.dim == 2:
            self.n_channels *= (self.n_3D_context * 2 + 1)

        #########################
        #      Architecture      #
        #########################

        self.start_filts = 48 if self.dim == 2 else 18
        self.end_filts = self.start_filts * 4 if self.dim == 2 else self.start_filts * 2
        self.res_architecture = 'resnet50'  # 'resnet101' , 'resnet50'
        self.norm = None  # one of None, 'instance_norm', 'batch_norm'
        # 0 for no weight decay
        self.weight_decay = 0

        # one of 'xavier_uniform', 'xavier_normal', or 'kaiming_normal', None (=default = 'kaiming_uniform')
        self.weight_init = None

        #########################
        #  Schedule / Selection #
        #########################

        self.num_epochs = 50
        self.num_train_batches = 200 if self.dim == 2 else 200
        self.batch_size = 20 if self.dim == 2 else 10

        self.do_validation = True
        # decide whether to validate on entire patient volumes (like testing) or sampled patches (like training)
        # the former is more accurate, while the latter is faster (depending on volume size)
        self.val_mode = 'val_sampling'  # one of 'val_sampling' , 'val_patient'
        if self.val_mode == 'val_patient':
            self.max_val_patients = 50  # if 'None' iterates over entire val_set once.
        if self.val_mode == 'val_sampling':
            self.num_val_batches = 25

        self.optimizer = "Adam"

        # set dynamic_lr_scheduling to True to apply LR scheduling with below settings.
        self.dynamic_lr_scheduling = False
        self.lr_decay_factor = 0.25
        self.scheduling_patience = np.ceil(
            16000 / (self.num_train_batches * self.batch_size))
        self.scheduling_criterion = 'malignant_ap'
        self.scheduling_mode = 'min' if "loss" in self.scheduling_criterion else 'max'

        #########################
        #   Testing / Plotting  #
        #########################

        # set the top-n-epochs to be saved for temporal averaging in testing.
        self.save_n_models = 5
        self.test_n_epochs = 5
        # set a minimum epoch number for saving in case of instabilities in the first phase of training.
        self.min_save_thresh = 0 if self.dim == 2 else 0

        self.report_score_level = ['patient', 'rois'
                                   ]  # choose list from 'patient', 'rois'
        #self.class_dict = {1: 'benign', 2: 'malignant'}  # 0 is background.
        #self.patient_class_of_interest = 2  # patient metrics are only plotted for one class.
        self.class_dict = {1: 'nodule'}  # 1 output class
        self.patient_class_of_interest = 1
        self.ap_match_ious = [0.1
                              ]  # list of ious to be evaluated for ap-scoring.

        self.model_selection_criteria = [
            'nodule_ap'
        ]  # ['malignant_ap', 'benign_ap'] # criteria to average over for saving epochs.
        self.min_det_thresh = 0.1  # minimum confidence value to select predictions for evaluation.

        # threshold for clustering predictions together (wcs = weighted cluster scoring).
        # needs to be >= the expected overlap of predictions coming from one model (typically NMS threshold).
        # if too high, preds of the same object are separate clusters.
        self.wcs_iou = 1e-5

        self.plot_prediction_histograms = True
        self.plot_stat_curves = True

        #########################
        #   Data Augmentation   #
        #########################

        self.da_kwargs = {
            'do_elastic_deform':
            True,
            'alpha': (0., 1500.),
            'sigma': (30., 50.),
            'do_rotation':
            True,
            'angle_x': (0., 2 * np.pi),
            'angle_y': (0., 0),
            'angle_z': (0., 0),
            'do_scale':
            True,
            'scale': (0.8, 1.1),
            'random_crop':
            False,
            'rand_crop_dist':
            (self.patch_size[0] / 2. - 3, self.patch_size[1] / 2. - 3),
            'border_mode_data':
            'constant',
            'border_cval_data':
            0,
            'order_data':
            1
        }

        if self.dim == 3:
            self.da_kwargs['do_elastic_deform'] = False
            self.da_kwargs['angle_x'] = (0, 0.0)
            self.da_kwargs['angle_y'] = (0, 0.0)  #must be 0!!
            self.da_kwargs['angle_z'] = (0., 2 * np.pi)

        #########################
        #   Add model specifics #
        #########################

        {
            'detection_unet': self.add_det_unet_configs,
            'mrcnn': self.add_mrcnn_configs,
            'ufrcnn': self.add_mrcnn_configs,
            'retina_net': self.add_mrcnn_configs,
            'retina_unet': self.add_mrcnn_configs,
        }[self.model]()
Exemplo n.º 8
0
    def __init__(self, server_env=None):

        #########################
        #    Preprocessing      #
        #########################

        self.root_dir = '/path/to/raw/data'
        self.raw_data_dir = '{}/data_nrrd'.format(self.root_dir)
        self.pp_dir = '{}/pp_norm'.format(self.root_dir)
        self.target_spacing = (0.7, 0.7, 1.25)

        #########################
        #         I/O           #
        #########################

        # one out of [2, 3]. dimension the model operates in.
        self.dim = 3

        # one out of ['mrcnn', 'retina_net', 'retina_unet', 'generic_unet', 'ufrcnn', 'probabilistic_unet'].
        self.model = 'generic_unet'

        DefaultConfigs.__init__(self, self.model, server_env, self.dim)

        # int [0 < dataset_size]. select n patients from dataset for prototyping. If None, all data is used.
        self.select_prototype_subset = None

        # path to preprocessing data.
        self.pp_name = 'pp_norm'
        self.input_df_name = 'info_df.pickle'
        self.pp_data_path = '/path/to/preprocessing/data/{}'.format(
            self.pp_name)
        self.pp_test_data_path = self.pp_data_path  #change if test_data in separate folder.

        # settings for deployment in cloud.
        if server_env:
            # path to preprocessing data.
            self.pp_name = 'pp_fg_slices'
            self.crop_name = 'pp_fg_slices_packed'
            self.pp_data_path = '/path/to/preprocessing/data/{}/{}'.format(
                self.pp_name, self.crop_name)
            self.pp_test_data_path = self.pp_data_path
            self.select_prototype_subset = None

        #########################
        #      Data Loader      #
        #########################

        # select modalities from preprocessing data
        self.channels = [0]
        self.n_channels = len(self.channels)

        # patch_size to be used for training. pre_crop_size is the patch_size before data augmentation.
        self.pre_crop_size_2D = [300, 300]
        self.patch_size_2D = [288, 288]
        self.pre_crop_size_3D = [156, 156, 96]
        self.patch_size_3D = [128, 128, 64]
        self.patch_size = self.patch_size_2D if self.dim == 2 else self.patch_size_3D
        self.pre_crop_size = self.pre_crop_size_2D if self.dim == 2 else self.pre_crop_size_3D

        # ratio of free sampled batch elements before class balancing is triggered
        # (>0 to include "empty"/background patches.)
        self.batch_sample_slack = 0.2

        # set 2D net to operate in 3D images.
        self.merge_2D_to_3D_preds = True

        # feed +/- n neighbouring slices into channel dimension. set to None for no context.
        self.n_3D_context = None
        if self.n_3D_context is not None and self.dim == 2:
            self.n_channels *= (self.n_3D_context * 2 + 1)

        #########################
        #      Data Analysis      #
        #########################

        # be set to background if the volume is less than X times of the minimum volume of
        # that class in the training data
        self.MIN_SIZE_PER_CLASS_FACTOR = 0.5
        self.TARGET_SPACING_PERCENTILE = 50

        self.FEATUREMAP_MIN_EDGE_LENGTH_BOTTLENECK = 4
        self.FEATUREMAP_MIN_EDGE_LENGTH_BOTTLENECK2 = 6
        # z is defined as the axis with the highest spacing, also used to
        # determine whether to use 2d or 3d data augmentation
        self.RESAMPLING_SEPARATE_Z_ANISOTROPY_THRESHOLD = 3
        # 1/4 of a patient
        self.HOW_MUCH_OF_A_PATIENT_MUST_THE_NETWORK_SEE_AT_STAGE0 = 4
        # all samples in the batch cannot cover more than 5% of the entire dataset
        self.batch_size_covers_max_percent_of_dataset = 0.05
        # minimum batch size >= 2
        self.dataset_min_batch_size_cap = 2

        #########################
        #      Architecture      #
        #########################

        self.start_filts = 48 if self.dim == 2 else 18
        self.end_filts = self.start_filts * 4 if self.dim == 2 else self.start_filts * 2
        self.res_architecture = 'resnet50'  # 'resnet101' , 'resnet50'
        self.norm = None  # one of None, 'instance_norm', 'batch_norm'
        self.weight_decay = 0

        # one of 'xavier_uniform', 'xavier_normal', or 'kaiming_normal', None (=default = 'kaiming_uniform')
        self.weight_init = None

        #########################
        #  Schedule / Selection #
        #########################

        self.num_epochs = 100
        self.num_train_batches = 200 if self.dim == 2 else 200
        self.batch_size = 20 if self.dim == 2 else 8

        self.do_validation = True
        # decide whether to validate on entire patient volumes (like testing) or sampled patches (like training)
        # the former is morge accurate, while the latter is faster (depending on volume size)
        self.val_mode = 'val_sampling'  # one of 'val_sampling' , 'val_patient'
        if self.val_mode == 'val_patient':
            self.max_val_patients = 50  # if 'None' iterates over entire val_set once.
        if self.val_mode == 'val_sampling':
            self.num_val_batches = 50

        #########################
        #   Testing / Plotting  #
        #########################

        # set the top-n-epochs to be saved for temporal averaging in testing.
        self.save_n_models = 5
        self.test_n_epochs = 5
        # set a minimum epoch number for saving in case of instabilities in the first phase of training.
        self.min_save_thresh = 0 if self.dim == 2 else 0

        self.report_score_level = ['patient', 'rois'
                                   ]  # choose list from 'patient', 'rois'
        self.class_dict = {1: 'benign', 2: 'malignant'}  # 0 is background.
        self.patient_class_of_interest = 2  # patient metrics are only plotted for one class.
        self.ap_match_ious = [0.1
                              ]  # list of ious to be evaluated for ap-scoring.

        self.model_selection_criteria = [
            'malignant_ap', 'benign_ap'
        ]  # criteria to average over for saving epochs.
        self.min_det_thresh = 0.1  # minimum confidence value to select predictions for evaluation.

        # threshold of wcs (weighted cluster scoring), used for clustering predictions together.
        # needs to be >= the expected overlap of predictions coming from one model.(typically NMS threshold).
        self.wcs_iou = 1e-5

        self.plot_prediction_histograms = True
        self.plot_stat_curves = False

        #########################
        #   Data Augmentation   #
        #########################

        self.da_kwargs = {
            'do_elastic_deform':
            True,
            'alpha': (0., 1500.),
            'sigma': (30., 50.),
            'do_rotation':
            True,
            'angle_x': (0., 2 * np.pi),
            'angle_y': (0., 0),
            'angle_z': (0., 0),
            'do_scale':
            True,
            'scale': (0.8, 1.1),
            'random_crop':
            False,
            'rand_crop_dist':
            (self.patch_size[0] / 2. - 3, self.patch_size[1] / 2. - 3),
            'border_mode_data':
            'constant',
            'border_cval_data':
            0,
            'order_data':
            1
        }
        if self.dim == 3:
            self.da_kwargs['do_elastic_deform'] = False
            self.da_kwargs['angle_x'] = (0, 0.0)
            self.da_kwargs['angle_y'] = (0, 0.0)  #must be 0!!
            self.da_kwargs['angle_z'] = (0., 2 * np.pi)

        self.aug_3D_kwargs = {
            "selected_data_channels": None,
            "selected_seg_channels": None,
            "do_elastic": True,
            "elastic_deform_alpha": (0., 900.),
            "elastic_deform_sigma": (9., 13.),
            "do_scaling": True,
            "scale_range": (0.85, 1.25),
            "do_rotation": True,
            "rotation_x": (-15. / 360 * 2. * np.pi, 15. / 360 * 2. * np.pi),
            "rotation_y": (-15. / 360 * 2. * np.pi, 15. / 360 * 2. * np.pi),
            "rotation_z": (-15. / 360 * 2. * np.pi, 15. / 360 * 2. * np.pi),
            "random_crop": False,
            "random_crop_dist_to_border": None,
            "do_gamma": True,
            "gamma_retain_stats": True,
            "gamma_range": (0.7, 1.5),
            "p_gamma": 0.3,
            "num_threads": 12,
            "num_cached_per_thread": 1,
            "mirror": True,
            "mirror_axes": (0, 1, 2),
            "p_eldef": 0.2,
            "p_scale": 0.2,
            "p_rot": 0.2,
            "dummy_2D": False,
            "mask_was_used_for_normalization": False,
            "all_segmentation_labels": None,  # used for pyramid
            "move_last_seg_chanel_to_data": False,  # used for pyramid
            "border_mode_data": "constant",
            "advanced_pyramid_augmentations": False  # used for pyramid
        }
        self.aug_2D_kwargs = deepcopy(self.aug_3D_kwargs)
        self.aug_2D_kwargs["elastic_deform_alpha"] = (0., 200.)
        self.aug_2D_kwargs["elastic_deform_sigma"] = (9., 13.)
        self.aug_2D_kwargs["rotation_x"] = (-180. / 360 * 2. * np.pi,
                                            180. / 360 * 2. * np.pi)

        # according to unsupported 3d data augmentation, transfer 3d data into 2d data and
        # transform them back after augmentation
        self.aug_2D_kwargs["dummy_2D"] = False
        self.aug_2D_kwargs["mirror_axes"] = (
            0, 1)  # this can be (0, 1, 2) if dummy_2D=True

        #########################
        #   Add model specifics #
        #########################

        {
            'generic_unet': self.add_gen_unet_configs,
            'mrcnn': self.add_mrcnn_configs,
            'ufrcnn': self.add_mrcnn_configs,
            'retina_net': self.add_mrcnn_configs,
            'retina_unet': self.add_mrcnn_configs,
        }[self.model]()
Exemplo n.º 9
0
    def __init__(self, server_env=None):

        #########################
        #    Preprocessing      #
        #########################

        self.data = ["Thesis", "LiTS"]

        self.root_dir = '/home/rgunti/data/{}'.format(self.data[0])
        self.raw_data_dir = '{}/data_raw/data/'.format(self.root_dir)
        self.raw_seg_dir = '{}/data_raw/seg/'.format(self.root_dir)
        self.pp_dir = '{}/data_pp'.format(self.root_dir)
        self.pp_dir_wocrop = '{}/data_pp_wocrop'.format(self.root_dir)
        self.pp_dir_int = '{}/data_pp_int'.format(self.root_dir)
        self.pp_dir_int_wocrop = '{}/data_pp_int_wocrop'.format(self.root_dir)
        self.target_spacing = (1.0, 1.0, 2.5)

        if server_env:
            self.root_dir = "/content/drive/My\' \'Drive/Thesis/Thesis/"
            self.raw_data_dir = '{}/Dataset/data/'.format(self.root_dir)
            self.raw_seg_dir = '{}/Dataset/seg/'.format(self.root_dir)
            self.pp_dir = '{}/data_pp'.format(self.root_dir)

        #########################
        #         I/O           #
        #########################

        # one out of [2, 3]. dimension the model operates in.
        self.dim = 3

        # one out of ['mrcnn', 'retina_net', 'retina_unet', 'detection_unet', 'ufrcnn', 'decoupled_refinement'].
        self.model = 'retina_net'

        DefaultConfigs.__init__(self, self.model, server_env, self.dim)

        # int [0 < dataset_size]. select n patients from dataset for prototyping. If None, all data is used.
        self.select_prototype_subset = None
        self.subset_ixs = None
        self.subset_pids = None
        self.hold_out_test_set = True
        self.data_dest = ''

        # path to preprocessed data.
        # self.pp_name = 'data_pp'
        # self.pp_name = 'data_pp_int'
        # self.pp_name = 'data_pp_wocrop'
        self.pp_name = 'data_pp_int_wocrop'

        self.input_df_name = 'info_df.pickle'
        self.pp_data_path = '{}/{}/'.format(self.root_dir, self.pp_name)
        # change if test_data in separate folder.
        self.pp_test_data_path = self.pp_data_path
        # settings for deployment in cloud.
        if server_env:
            # path to preprocessed data.
            # self.pp_name = 'lidc_mdt_npz'
            self.crop_name = 'pp_fg_slices_packed'
            # self.pp_data_path = '/datasets/datasets_ramien/lidc_exp/data/{}'.format(self.pp_name)
            self.data_dest = '/content/'
            self.pp_test_data_path = self.pp_data_path
            self.select_prototype_subset = None

        #########################
        #      Data Loader      #
        #########################
        # select modalities from preprocessed data
        self.channels = [0]
        self.n_channels = len(self.channels)

        # patch_size to be used for training. pre_crop_size is the patch_size before data augmentation.
        self.pre_crop_size_2D = [256, 256]
        self.patch_size_2D = [224, 224]
        self.use_big_patch = 0
        if self.use_big_patch:
            self.pre_crop_size_3D = [256, 256, 112]
            self.patch_size_3D = [224, 224, 96]
        else:
            self.pre_crop_size_3D = [156, 156, 96]
            self.patch_size_3D = [128, 128, 64]
        self.pre_crop_size = self.pre_crop_size_2D if self.dim == 2 else self.pre_crop_size_3D
        self.patch_size = self.patch_size_2D if self.dim == 2 else self.patch_size_3D

        # ratio of free sampled batch elements before class balancing is triggered
        # (>0 to include "empty"/background patches.)
        self.batch_sample_slack = 0.2
        # self.batch_sample_slack = 0.5 if self.dim == 2 else 1.0

        # set 2D network to operate in 3D images.
        self.merge_2D_to_3D_preds = False

        # feed +/- n neighbouring slices into channel dimension. set to None for no context.
        self.n_3D_context = None
        if self.n_3D_context is not None and self.dim == 2:
            self.n_channels *= (self.n_3D_context * 2 + 1)

        #########################
        #      Architecture      #
        #########################

        self.start_filts = 48 if self.dim == 2 else 32
        self.end_filts = self.start_filts * 4 if self.dim == 2 else self.start_filts * 2
        self.res_architecture = 'resnet50'  # 'resnet101' , 'resnet50'
        self.norm = 'batch_norm'  # one of None, 'instance_norm', 'batch_norm'
        self.weight_decay = 0

        # one of 'xavier_uniform', 'xavier_normal', or 'kaiming_normal', None (=default = 'kaiming_uniform')
        self.weight_init = None
        # Path to checkpoint of an experiment. Models loads only the matching keys from net.state_dict
        self.pre_train_path = None

        #########################
        #  Schedule / Selection #
        #########################

        self.num_epochs = 1200
        self.num_train_batches = 50 if self.dim == 2 else 50
        self.batch_size = 64 if self.dim == 2 else 1 if self.use_big_patch else 4

        self.do_validation = True if self.select_prototype_subset is None else False
        # decide whether to validate on entire patient volumes (like testing) or sampled patches (like training)
        # the former is morge accurate, while the latter is faster (depending on volume size)
        self.val_mode = 'val_sampling'  # one of 'val_sampling' , 'val_patient'
        if self.val_mode == 'val_patient':
            # if 'None' iterates over entire val_set once.
            self.max_val_patients = None
        if self.val_mode == 'val_sampling':
            self.num_val_batches = 10

        #########################
        #   Testing / Plotting  #
        #########################

        # set the top-n-epochs to be saved for temporal averaging in testing.
        self.save_n_models = 5
        self.test_n_epochs = 1
        # set a minimum epoch number for saving in case of instabilities in the first phase of training.
        self.min_save_thresh = 0 if self.dim == 2 else 0
        self.test_aug = False
        # choose list from 'patient', 'rois'
        self.report_score_level = ['rois']
        # self.class_dict = {1: 'benign', 2: 'malignant'}  # 0 is background.
        self.class_dict = {1: 'lesion'}  # 0 is background.
        # self.patient_class_of_interest = 2  # patient metrics are only plotted for one class.
        self.patient_class_of_interest = 1
        # list of ious to be evaluated for ap-scoring.
        self.ap_match_ious = [0.1]

        # self.model_selection_criteria = ['malignant_ap', 'benign_ap'] # criteria to average over for saving epochs.
        self.model_selection_criteria = ['lesion_ap']
        # minimum confidence value to select predictions for evaluation.
        self.min_det_thresh = 0
        # analysis of the  hyper-parameter cf.min_det_thresh, for optimization on validation set.
        self.scan_det_thresh = False

        # threshold for clustering predictions together (wcs = weighted cluster scoring).
        # needs to be >= the expected overlap of predictions coming from one model (typically NMS threshold).
        # if too high, preds of the same object are separate clusters.
        self.wcs_iou = 1e-5

        self.plot_prediction_histograms = True
        self.plot_stat_curves = True

        #########################
        #   Data Augmentation   #
        #########################

        self.da_kwargs = {
            'do_elastic_deform': True,
            'alpha': (0., 1500.),
            'sigma': (30., 50.),
            'do_rotation': True,
            'angle_x': (0., 0. * np.pi),
            'angle_y': (0., 0),
            'angle_z': (0., 0),
            'do_scale': True,
            'scale': (0.8, 1.2),
            'random_crop': True,
            'rand_crop_dist':  (self.patch_size[0] / 2. - 3, self.patch_size[1] / 2. - 3),
            'border_mode_data': 'constant',
            'border_cval_data': 0,
            'order_data': 1
        }

        if self.dim == 3:
            self.da_kwargs['rand_crop_dist'] = (
                self.patch_size[0] / 2. - 3, self.patch_size[1] / 2. - 3, self.patch_size[2] / 2. - 3)
            self.da_kwargs['do_elastic_deform'] = True
            self.da_kwargs['angle_x'] = (0, 0.0)
            self.da_kwargs['angle_y'] = (0, 0.0)  # must be 0!!
            self.da_kwargs['angle_z'] = (0., 2 * np.pi)

        #########################
        #   Add model specifics #
        #########################

        {'detection_unet': self.add_det_unet_configs,
         'mrcnn': self.add_mrcnn_configs,
         'ufrcnn': self.add_mrcnn_configs,
         'retina_net': self.add_mrcnn_configs,
         'retina_unet': self.add_mrcnn_configs,
         'decoupled_refinement': self.add_mrcnn_configs,
         }[self.model]()