예제 #1
0
from delira.training import PyTorchExperiment, Parameters
from delira.models.classification import ClassificationNetworkBasePyTorch
from delira.data_loading import AbstractDataset, BaseDataManager
import torch


@pytest.mark.parametrize("params,dataset_length_train,dataset_length_test",
                         [(Parameters(
                             fixed_params={
                                 "model": {},
                                 "training": {
                                     "criterions": {
                                         "CE": torch.nn.CrossEntropyLoss()
                                     },
                                     "optimizer_cls": torch.optim.Adam,
                                     "optimizer_params": {
                                         "lr": 1e-3
                                     },
                                     "num_epochs": 2,
                                     "metrics": {},
                                     "lr_sched_cls": None,
                                     "lr_sched_params": {}
                                 }
                             }), 500, 50)])
def test_experiment(params, dataset_length_train, dataset_length_test):
    class DummyNetwork(ClassificationNetworkBasePyTorch):
        def __init__(self):
            super().__init__(32, 1)

        def forward(self, x):
            return self.module(x)
예제 #2
0
    def setUp(self) -> None:
        test_cases_torch, test_cases_tf = [], []
        from sklearn.metrics import mean_absolute_error

        # setup torch testcases
        if "TORCH" in get_backends():
            import torch
            from delira.models.classification import \
                ClassificationNetworkBasePyTorch
            from delira.training.callbacks import \
                ReduceLROnPlateauCallbackPyTorch

            class DummyNetworkTorch(ClassificationNetworkBasePyTorch):

                def __init__(self):
                    super().__init__(32, 1)

                def forward(self, x):
                    return {"pred": self.module(x)}

                @staticmethod
                def _build_model(in_channels, n_outputs):
                    return torch.nn.Sequential(
                        torch.nn.Linear(in_channels, 64),
                        torch.nn.ReLU(),
                        torch.nn.Linear(64, n_outputs)
                    )

                @staticmethod
                def prepare_batch(batch_dict, input_device, output_device):
                    return {"data": torch.from_numpy(batch_dict["data"]
                                                     ).to(input_device,
                                                          torch.float),
                            "label": torch.from_numpy(batch_dict["label"]
                                                      ).to(output_device,
                                                           torch.float)}

            test_cases_torch.append((
                Parameters(fixed_params={
                    "model": {},
                    "training": {
                        "losses": {"CE":
                                   torch.nn.BCEWithLogitsLoss()},
                        "optimizer_cls": torch.optim.Adam,
                        "optimizer_params": {"lr": 1e-3},
                        "num_epochs": 2,
                        "val_metrics": {"val_mae": mean_absolute_error},
                        "lr_sched_cls": ReduceLROnPlateauCallbackPyTorch,
                        "lr_sched_params": {"mode": "min"}
                    }
                }
                ),
                500,
                50,
                "mae",
                "lowest",
                DummyNetworkTorch))

            self._test_cases_torch = test_cases_torch

        # setup tf tescases
        if "TF" in get_backends():
            from delira.models import ClassificationNetworkBaseTf, \
                AbstractTfNetwork

            import tensorflow as tf

            class DummyNetworkTf(ClassificationNetworkBaseTf):
                def __init__(self):
                    AbstractTfNetwork.__init__(self)
                    self.model = self._build_model(1)

                    images = tf.placeholder(shape=[None, 32],
                                            dtype=tf.float32)
                    labels = tf.placeholder_with_default(
                        tf.zeros([tf.shape(images)[0], 1]), shape=[None, 1])

                    preds_train = self.model(images, training=True)
                    preds_eval = self.model(images, training=False)

                    self.inputs["images"] = images
                    self.inputs["labels"] = labels
                    self.outputs_train["pred"] = preds_train
                    self.outputs_eval["pred"] = preds_eval

                @staticmethod
                def _build_model(n_outputs):
                    return tf.keras.models.Sequential(
                        layers=[
                            tf.keras.layers.Dense(64, input_shape=(
                                32,), bias_initializer='glorot_uniform'),
                            tf.keras.layers.ReLU(),
                            tf.keras.layers.Dense(
                                n_outputs,
                                bias_initializer='glorot_uniform')]
                    )

            test_cases_tf.append(
                (
                    Parameters(fixed_params={
                        "model": {},
                        "training": {
                            "losses": {"CE":
                                       tf.losses.softmax_cross_entropy},
                            "optimizer_cls": tf.train.AdamOptimizer,
                            "optimizer_params": {"learning_rate": 1e-3},
                            "num_epochs": 2,
                            "val_metrics": {"val_mae": mean_absolute_error},
                            "lr_sched_cls": None,
                            "lr_sched_params": {}}
                    }
                    ),
                    500,
                    50,
                    DummyNetworkTf)
            )

        self._test_cases_tf = test_cases_tf
        logger.info(self._testMethodName)
예제 #3
0
def run_experiment(cp: str, test=True) -> str:
    """
    Run classification experiment on patches
    Imports moved inside because of logging setups

    Parameters
    ----------
    ch : str
        path to config file
    test : bool
        test best model on test set

    Returns
    -------
    str
        path to experiment folder
    """
    # setup config
    ch = ConfigHandlerPyTorchDelira(cp)
    ch = feature_map_params(ch)

    if 'mixed_precision' not in ch or ch['mixed_precision'] is None:
        ch['mixed_precision'] = True
    if 'debug_delira' in ch and ch['debug_delira'] is not None:
        delira.set_debug_mode(ch['debug_delira'])
        print("Debug mode active: settings n_process_augmentation to 1!")
        ch['augment.n_process'] = 1

    dset_keys = ['train', 'val', 'test']

    losses = {'class_ce': torch.nn.CrossEntropyLoss()}
    train_metrics = {}
    val_metrics = {'CE': metric_wrapper_pytorch(torch.nn.CrossEntropyLoss())}
    test_metrics = {'CE': metric_wrapper_pytorch(torch.nn.CrossEntropyLoss())}

    #########################
    #   Setup Parameters    #
    #########################
    params_dict = ch.get_params(losses=losses,
                                train_metrics=train_metrics,
                                val_metrics=val_metrics,
                                add_self=ch['add_config_to_params'])
    params = Parameters(**params_dict)

    #################
    #   Setup IO    #
    #################
    # setup io
    load_sample = load_pickle
    load_fn = LoadPatches(load_fn=load_sample,
                          patch_size=ch['patch_size'],
                          **ch['data.load_patch'])

    datasets = {}
    for key in dset_keys:
        p = os.path.join(ch["data.path"], str(key))

        datasets[key] = BaseExtendCacheDataset(p,
                                               load_fn=load_fn,
                                               **ch['data.kwargs'])

    #############################
    #   Setup Transformations   #
    #############################
    base_transforms = []
    base_transforms.append(PopKeys("mapping"))

    train_transforms = []
    if ch['augment.mode']:
        logger.info("Training augmentation enabled.")
        train_transforms.append(
            SpatialTransform(patch_size=ch['patch_size'],
                             **ch['augment.kwargs']))
        train_transforms.append(MirrorTransform(axes=(0, 1)))
    process = ch['augment.n_process'] if 'augment.n_process' in ch else 1

    #########################
    #   Setup Datamanagers  #
    #########################
    datamanagers = {}
    for key in dset_keys:
        if key == 'train':
            trafos = base_transforms + train_transforms
            sampler = WeightedPrevalenceRandomSampler
        else:
            trafos = base_transforms
            sampler = SequentialSampler

        datamanagers[key] = BaseDataManager(
            data=datasets[key],
            batch_size=params.nested_get('batch_size'),
            n_process_augmentation=process,
            transforms=Compose(trafos),
            sampler_cls=sampler,
        )

    #############################
    #   Initialize Experiment   #
    #############################
    experiment = \
        PyTorchExperiment(
            params=params,
            model_cls=ClassNetwork,
            name=ch['exp.name'],
            save_path=ch['exp.dir'],
            optim_builder=create_optims_default_pytorch,
            trainer_cls=PyTorchNetworkTrainer,
            mixed_precision=ch['mixed_precision'],
            mixed_precision_kwargs={'verbose': False},
            key_mapping={"input_batch": "data"},
            **ch['exp.kwargs'],
        )

    # save configurations
    ch.dump(os.path.join(experiment.save_path, 'config.json'))

    #################
    #   Training    #
    #################
    model = experiment.run(datamanagers['train'],
                           datamanagers['val'],
                           save_path_exp=experiment.save_path,
                           ch=ch,
                           metric_keys={'val_CE': ['pred', 'label']},
                           val_freq=1,
                           verbose=True)
    ################
    #   Testing    #
    ################
    if test and datamanagers['test'] is not None:
        # metrics and metric_keys are used differently than in original
        # Delira implementation in order to support Evaluator
        # see mscl.training.predictor
        preds = experiment.test(
            network=model,
            test_data=datamanagers['test'],
            metrics=test_metrics,
            metric_keys={'CE': ['pred', 'label']},
            verbose=True,
        )

        softmax_fn = metric_wrapper_pytorch(
            partial(torch.nn.functional.softmax, dim=1))
        preds = softmax_fn(preds[0]['pred'])
        labels = [d['label'] for d in datasets['test']]
        fpr, tpr, thresholds = roc_curve(labels, preds[:, 1])
        roc_auc = auc(fpr, tpr)

        plt.plot(fpr, tpr, label='ROC (AUC = %0.2f)' % roc_auc)
        plt.xlabel('False Positive Rate')
        plt.ylabel('True Positive Rate')
        plt.title('Receiver operating characteristic example')
        plt.legend(loc="lower right")
        plt.savefig(os.path.join(experiment.save_path, 'test_roc.pdf'))
        plt.close()

        preds = experiment.test(
            network=model,
            test_data=datamanagers['val'],
            metrics=test_metrics,
            metric_keys={'CE': ['pred', 'label']},
            verbose=True,
        )

        preds = softmax_fn(preds[0]['pred'])
        labels = [d['label'] for d in datasets['val']]
        fpr, tpr, thresholds = roc_curve(labels, preds[:, 1])
        roc_auc = auc(fpr, tpr)

        plt.plot(fpr, tpr, label='ROC (AUC = %0.2f)' % roc_auc)
        plt.xlabel('False Positive Rate')
        plt.ylabel('True Positive Rate')
        plt.title('Receiver operating characteristic example')
        plt.legend(loc="lower right")
        plt.savefig(os.path.join(experiment.save_path, 'best_val_roc.pdf'))
        plt.close()

    return experiment.save_path
예제 #4
0
params = Parameters(fixed_params={
    "model": {
        "image_size": args.image_size,
        "output_size": args.output_size,
        "input_c_dim": args.input_c_dim,
        "output_c_dim": args.output_c_dim,
        "df_dim": args.df_dim,
        "gf_dim": args.gf_dim,
        "f_size": args.f_size,
        "strides": args.strides,
        "l1_lambda": args.l1_lambda
    },
    "training": {
        "batch_size": args.batch_size,
        "num_epochs": args.num_epochs,

        "optimizer_cls": tf.train.AdamOptimizer, # optimization algorithm to use
        "optimizer_params": {'learning_rate': args.learning_rate,
                             #'momentum': 0.5
                             'beta1': 0.5,
                             #'beta2': 0.8
                            },
        "criterions": {'CE': tf.losses.sigmoid_cross_entropy}, # the original loss :tf.nn.sigmoid_cross_entropy_with_logits
        "lr_sched_cls": None,  # the learning rate scheduling algorithm to use
        "lr_sched_params": {}, # the corresponding initialization parameters
        "metrics": {'LPIPS': lpips_score([None, 3, args.image_size, args.image_size])}, # and some evaluation metrics
        "dataset_name": args.dataset_name,
        "val_dataset": args.val_dataset,
        "exp_name": args.exp_name
    }
})
예제 #5
0
    def test_parameters(self):
        def to_lookup_config(dictionary):
            tmp = LookupConfig()
            tmp.update(dictionary)
            return tmp

        test_cases = [({
            "a": 1,
            "b": [1, 2],
            "c": {
                "d": 3,
                "e": 56
            }
        }, {
            "f": 1,
            "g": {
                "h": {
                    "i": {
                        "a": 3
                    }
                }
            }
        }, {
            "j": 1,
            "k": 2
        }, {}, "e", 56, "a", "q")]

        for case in test_cases:
            with self.subTest(case=case):
                fixed_model_params, variable_model_params, \
                    fixed_training_params, variable_training_params, \
                    valid_nested_key, valid_nested_value, doubled_key, \
                    invalid_key = case

                fixed_model_params = to_lookup_config(fixed_model_params)
                variable_model_params = to_lookup_config(variable_model_params)
                fixed_training_params = to_lookup_config(fixed_training_params)
                variable_training_params = to_lookup_config(
                    variable_training_params)

                params = Parameters(fixed_params={
                    "model": fixed_model_params,
                    "training": fixed_training_params
                },
                                    variable_params={
                                        "model": variable_model_params,
                                        "training": variable_training_params
                                    })

                self.assertFalse(params.training_on_top)
                self.assertTrue(params.variability_on_top)
                self.assertEqual(
                    params.fixed,
                    to_lookup_config({
                        "model": fixed_model_params,
                        "training": fixed_training_params
                    }))

                self.assertEqual(
                    params.variable,
                    to_lookup_config({
                        "model": variable_model_params,
                        "training": variable_training_params
                    }))

                params = params.permute_training_on_top()

                self.assertFalse(params.variability_on_top)
                self.assertTrue(params.training_on_top)

                self.assertEqual(
                    params.model,
                    to_lookup_config({
                        "fixed": fixed_model_params,
                        "variable": variable_model_params
                    }))

                self.assertEqual(
                    params.training,
                    to_lookup_config({
                        "fixed": fixed_training_params,
                        "variable": variable_training_params
                    }))

                params_copy = params.deepcopy()
                params = params.permute_variability_on_top(
                ).permute_training_on_top()
                self.assertEqual(params_copy, params)

                self.assertEqual(params.nested_get(valid_nested_key),
                                 valid_nested_value)

                with self.assertRaises(KeyError):
                    params.nested_get(doubled_key)

                with self.assertRaises(KeyError):
                    params.nested_get(invalid_key)

                self.assertEqual("default",
                                 params.nested_get(invalid_key, "default"))
                self.assertEqual(
                    "default", params.nested_get(invalid_key,
                                                 default="default"))
params = Parameters(
    fixed_params={
        "model": {
            "image_size": int(args.image_size),
            "input_c_dim": args.input_c_dim,
            "output_c_dim": args.output_c_dim,
            "df_dim": args.df_dim,
            "gf_dim": args.gf_dim,
            "f_size": args.f_size,
            "strides": args.strides,
            "l1_lambda": args.l1_lambda
        },
        "training": {
            "batch_size": args.batch_size,
            "val_batch_size": args.val_batch_size,
            "num_epochs": args.num_epochs,
            "optimizer_cls":
            tf.train.AdamOptimizer,  # optimization algorithm to use
            "optimizer_params": {
                'learning_rate': args.learning_rate,
                #'momentum': 0.5
                'beta1': 0.5,
                #'beta2': 0.8
            },
            "criterions": {
                'CE': tf.losses.sigmoid_cross_entropy
            },
            "lr_sched_cls":
            None,  # the learning rate scheduling algorithm to use
            "lr_sched_params":
            {},  # the corresponding initialization parameters
            "metrics": {
                'LPIPS': lpips_score(
                    [None, 3, args.image_size, args.image_size])
            },  # and some evaluation metrics
            "dataset_name": args.dataset_name,
            "val_dataset": args.val_dataset,
            "exp_name": args.exp_name
        }
    })
예제 #7
0
#please check logger status

params = Parameters(
    fixed_params={
        "model": {
            "in_channels": 1,
            "num_classes": 26
        },
        "training": {
            "batch_size": 64,  # batchsize to use
            "num_epochs": 10,  # number of epochs to train
            "optimizer_cls": torch.optim.Adam,  # optimization algorithm to use
            "optimizer_params": {
                'lr': 1e-3
            },  # initialization parameters for this algorithm
            "losses": {
                "CE": torch.nn.CrossEntropyLoss()
            },  # the loss function
            "lr_sched_cls":
            None,  # the learning rate scheduling algorithm to use
            "lr_sched_params":
            {},  # the corresponding initialization parameters
            "criterions": accuracy_score,
            "metrics": {
                'img': {
                    'l1': accuracy_score
                }
            }  # and some evaluation metrics
        }
    })

import SimpleITK as sitk
예제 #8
0
seed = 0
val_score_key = "val_score_key"
val_score_mode = "val_score_mode"
n_process_augmentation = ch['n_process_augmentation']

# Parameters
losses = {"CE": torch.nn.CrossEntropyLoss()}
params = Parameters(fixed_params={
    "model": {
        "in_channels": 1,
        "n_outputs": 10
    },
    "training": {
        "batch_size": 64,  # batchsize to use
        "num_epochs": 10,  # number of epochs to train
        "optimizer_cls": torch.optim.Adam,  # optimization algorithm to use
        # initialization parameters for this algorithm
        "optimizer_params": {'lr': 1e-3},
        "losses": losses,  # the loss function
        "lr_sched_cls": None,  # the learning rate scheduling algorithm to use
        "lr_sched_params": {},  # the corresponding initialization parameters
        "metrics": {}  # and some evaluation metrics
    }
})

#################
#   Datasets    #
#################
dset = TorchvisionClassificationDataset("mnist",  # which dataset to use
                                        train=True,  # use trainset
                                        # resample to 224 x 224 pixels
예제 #9
0
params = Parameters(
    fixed_params={
        "model": {
            "image_size": args.image_size,
            "input_c_dim": args.input_c_dim,
            "output_c_dim": args.output_c_dim,
            "df_dim": args.df_dim,
            "gf_dim": args.gf_dim,
            "f_size": args.f_size,
            "latent_dim": int(args.latent_dim),
            "n_latent": int(args.n_latent),
            "coeff_reconstruct": float(args.coeff_reconstruct),
            "coeff_ds": int(args.coeff_ds),
            "is_batchnorm": args.is_batchnorm,
            #"d_layers": args.d_layers
        },
        "training": {
            "batch_size": args.batch_size,
            "val_batch_size": args.val_batch_size,
            "num_epochs": args.num_epochs,
            "optimizer_cls":
            tf.train.AdamOptimizer,  # optimization algorithm to use
            "optimizer_params": {
                'learning_rate': args.learning_rate,
                'beta1': 0.5,
                'beta2': 0.999
            },
            "criterions": {
                'L1': tf.losses.absolute_difference,
                'L2': tf.losses.mean_squared_error,
            },
            "lr_sched_cls":
            None,  # the learning rate scheduling algorithm to use
            "lr_sched_params":
            {},  # the corresponding initialization parameters
            "metrics": {
                'LPIPS': lpips_score(
                    [None, 3, args.image_size, args.image_size])
            },  # evaluation metrics
            "dataset_name": args.dataset_name,
            "val_dataset": args.val_dataset,
            "exp_name": args.exp_name
        }
    })
예제 #10
0
params = Parameters(fixed_params={
    "model": {
        "image_size": args.image_size,
        "input_c_dim": args.input_c_dim,
        "output_c_dim": args.output_c_dim,
        "df_dim": args.df_dim,
        "gf_dim": args.gf_dim,
        "f_size": args.f_size,
        "latent_dim": int(args.latent_dim),
        "n_latent": int(args.n_latent),
        "coeff_gan": float(args.coeff_gan),
        "coeff_vae": float(args.coeff_vae),
        "coeff_reconstruct": float(args.coeff_reconstruct),
        "coeff_kl": float(args.coeff_kl),
        "coeff_latent": float(args.coeff_latent),
        "coeff_ds": int(args.coeff_ds),
        "is_batchnorm": args.is_batchnorm,
        "with_DS": args.with_DS,
        "is_condD": args.is_condD
        #"d_layers": args.d_layers    # Could be refactored later for number of downsampling layers in discriminator
    },
    "training": {
        "batch_size": args.batch_size, # batchsize to use
        "val_batch_size": args.val_batch_size, # batchsize to use for validation
        "num_epochs": args.num_epochs, # number of epochs to train

        "optimizer_cls": tf.train.AdamOptimizer, # optimization algorithm to use
        "optimizer_params": {'learning_rate': args.learning_rate,
                             'beta1': 0.5,
                             'beta2': 0.999
                            },
        "criterions": {'L1': tf.losses.absolute_difference,
                       'L2': tf.losses.mean_squared_error,
                       },
        "lr_sched_cls": None,  # the learning rate scheduling algorithm to use
        "lr_sched_params": {}, # the corresponding initialization parameters
        "metrics": {'LPIPS': lpips_score([None, 3, args.image_size, args.image_size])}, # evaluation metrics
        "dataset_name": args.dataset_name,
        "val_dataset": args.val_dataset,
        "exp_name": args.exp_name
    }
})
예제 #11
0
    def test_experiment(self):

        from delira.training import PyTorchExperiment, Parameters
        from delira.training.callbacks import ReduceLROnPlateauCallbackPyTorch
        from delira.models.classification import ClassificationNetworkBasePyTorch
        from delira.data_loading import AbstractDataset, BaseDataManager
        import torch

        test_cases = [(Parameters(
            fixed_params={
                "model": {},
                "training": {
                    "criterions": {
                        "CE": torch.nn.CrossEntropyLoss()
                    },
                    "optimizer_cls": torch.optim.Adam,
                    "optimizer_params": {
                        "lr": 1e-3
                    },
                    "num_epochs": 2,
                    "metrics": {},
                    "lr_sched_cls": ReduceLROnPlateauCallbackPyTorch,
                    "lr_sched_params": {}
                }
            }), 500, 50)]

        class DummyNetwork(ClassificationNetworkBasePyTorch):
            def __init__(self):
                super().__init__(32, 1)

            def forward(self, x):
                return self.module(x)

            @staticmethod
            def _build_model(in_channels, n_outputs):
                return torch.nn.Sequential(torch.nn.Linear(in_channels, 64),
                                           torch.nn.ReLU(),
                                           torch.nn.Linear(64, n_outputs))

            @staticmethod
            def prepare_batch(batch_dict, input_device, output_device):
                return {
                    "data":
                    torch.from_numpy(batch_dict["data"]).to(
                        input_device, torch.float),
                    "label":
                    torch.from_numpy(batch_dict["label"]).to(
                        output_device, torch.long)
                }

        class DummyDataset(AbstractDataset):
            def __init__(self, length):
                super().__init__(None, None, None, None)
                self.length = length

            def __getitem__(self, index):
                return {
                    "data": np.random.rand(32),
                    "label": np.random.randint(0, 1, 1)
                }

            def __len__(self):
                return self.length

            def get_sample_from_index(self, index):
                return self.__getitem__(index)

        for case in test_cases:
            with self.subTest(case=case):

                params, dataset_length_train, dataset_length_test = case

                exp = PyTorchExperiment(params, DummyNetwork)
                dset_train = DummyDataset(dataset_length_train)
                dset_test = DummyDataset(dataset_length_test)

                dmgr_train = BaseDataManager(dset_train, 16, 4, None)
                dmgr_test = BaseDataManager(dset_test, 16, 1, None)

                net = exp.run(dmgr_train, dmgr_test)
                exp.test(
                    params=params,
                    network=net,
                    datamgr_test=dmgr_test,
                )

                exp.kfold(2, dmgr_train, num_splits=2)
                exp.stratified_kfold(2, dmgr_train, num_splits=2)
                exp.stratified_kfold_predict(2, dmgr_train, num_splits=2)
예제 #12
0
    def test_experiment(self):

        from delira.training import TfExperiment, Parameters
        from delira.models.classification import ClassificationNetworkBaseTf
        from delira.data_loading import AbstractDataset, BaseDataManager
        import tensorflow as tf

        test_cases = [(Parameters(
            fixed_params={
                "model": {
                    'in_channels': 32,
                    'n_outputs': 1
                },
                "training": {
                    "criterions": {
                        "CE": tf.losses.softmax_cross_entropy
                    },
                    "optimizer_cls": tf.train.AdamOptimizer,
                    "optimizer_params": {
                        "learning_rate": 1e-3
                    },
                    "num_epochs": 2,
                    "metrics": {},
                    "lr_sched_cls": None,
                    "lr_sched_params": {}
                }
            }), 500, 50)]

        class DummyNetwork(ClassificationNetworkBaseTf):
            def __init__(self):
                super().__init__(32, 1)
                self.model = self._build_model(1)

                images = tf.placeholder(shape=[None, 32], dtype=tf.float32)
                labels = tf.placeholder(shape=[None, 1], dtype=tf.float32)

                preds_train = self.model(images, training=True)
                preds_eval = self.model(images, training=False)

                self.inputs = [images, labels]
                self.outputs_train = [preds_train]
                self.outputs_eval = [preds_eval]

            @staticmethod
            def _build_model(n_outputs):
                return tf.keras.models.Sequential(layers=[
                    tf.keras.layers.Dense(64,
                                          input_shape=(32, ),
                                          bias_initializer='glorot_uniform'),
                    tf.keras.layers.ReLU(),
                    tf.keras.layers.Dense(n_outputs,
                                          bias_initializer='glorot_uniform')
                ])

        class DummyDataset(AbstractDataset):
            def __init__(self, length):
                super().__init__(None, None, None, None)
                self.length = length

            def __getitem__(self, index):
                return {
                    "data": np.random.rand(32),
                    "label": np.random.randint(0, 1, 1)
                }

            def __len__(self):
                return self.length

            def get_sample_from_index(self, index):
                return self.__getitem__(index)

        for case in test_cases:
            with self.subTest(case=case):

                params, dataset_length_train, dataset_length_test = case

                exp = TfExperiment(params, DummyNetwork)
                dset_train = DummyDataset(dataset_length_train)
                dset_test = DummyDataset(dataset_length_test)

                dmgr_train = BaseDataManager(dset_train, 16, 4, None)
                dmgr_test = BaseDataManager(dset_test, 16, 1, None)

                net = exp.run(dmgr_train, dmgr_test)
                exp.test(
                    params=params,
                    network=net,
                    datamgr_test=dmgr_test,
                )

                exp.kfold(2, dmgr_train, num_splits=2)
                exp.stratified_kfold(2, dmgr_train, num_splits=2)
                exp.stratified_kfold_predict(2, dmgr_train, num_splits=2)
예제 #13
0
def test_parameters(fixed_model_params, variable_model_params,
                    fixed_training_params, variable_training_params,
                    valid_nested_key, valid_nested_value, doubled_key,
                    invalid_key):
    def to_lookup_config(dictionary):
        tmp = LookupConfig()
        tmp.update(dictionary)
        return tmp

    fixed_model_params = to_lookup_config(fixed_model_params)
    variable_model_params = to_lookup_config(variable_model_params)
    fixed_training_params = to_lookup_config(fixed_training_params)
    variable_training_params = to_lookup_config(variable_training_params)

    params = Parameters(fixed_params={
        "model": fixed_model_params,
        "training": fixed_training_params
    },
                        variable_params={
                            "model": variable_model_params,
                            "training": variable_training_params
                        })

    assert params.training_on_top == False
    assert params.variability_on_top

    assert params.fixed == to_lookup_config({
        "model": fixed_model_params,
        "training": fixed_training_params
    })

    assert params.variable == to_lookup_config({
        "model":
        variable_model_params,
        "training":
        variable_training_params
    })

    params = params.permute_training_on_top()

    assert params.variability_on_top == False
    assert params.training_on_top

    print(
        params.model.difference_config(
            to_lookup_config({
                "fixed": fixed_model_params,
                "variable": variable_model_params
            })))

    assert params.model == to_lookup_config({
        "fixed": fixed_model_params,
        "variable": variable_model_params
    })

    assert params.training == to_lookup_config({
        "fixed":
        fixed_training_params,
        "variable":
        variable_training_params
    })

    params_copy = params.deepcopy()
    params = params.permute_variability_on_top().permute_training_on_top()
    assert params_copy == params

    assert params.nested_get(valid_nested_key) == valid_nested_value

    try:
        params.nested_get(doubled_key)
        assert False
    except KeyError:
        assert True

    try:
        params.nested_get(invalid_key)
        assert False
    except KeyError:
        assert True

    assert "default" == params.nested_get(invalid_key, "default")
    assert "default" == params.nested_get(invalid_key, default="default")
예제 #14
0
def main(args):
    ########################################
    #                                      #
    #      DEFINE THE HYPERPARAMETERS      #
    #                                      #
    ########################################

    # load settings from config file
    config_file = args.get("config_file")
    config_handler = ConfigHandler()
    config_dict = config_handler(config_file)

    # some are changed rarely and given manually if required
    train_size = args.get("train_size")
    val_size = args.get("val_size")
    margin = args.get("margin")
    optimizer = args.get("optimizer")

    if optimizer != "SGD" and optimizer != "Adam":
        ValueError("Invalid optimizer")
    elif optimizer == "Adam":
        optimizer_cls = torch.optim.Adam
    else:
        optimizer_cls = torch.optim.SGD

    params = Parameters(
        fixed_params={
            "model": config_dict["model"],
            "training": {
                **config_dict["training"],
                "optimizer_cls": optimizer_cls,
                **config_dict["optimizer"],
                "criterions": {
                    "FocalLoss": losses.FocalLoss(),
                    "SmoothL1Loss": losses.SmoothL1Loss()
                },
                #  "criterions": {"FocalMSELoss": losses.FocalMSELoss(),
                #                 "SmoothL1Loss": losses.SmoothL1Loss()},
                # "lr_sched_cls": ReduceLROnPlateauCallbackPyTorch,
                # "lr_sched_params": {"verbose": True},
                "lr_sched_cls": None,
                "lr_sched_params": {},
                "metrics": {}
            }
        })

    ########################################
    #                                      #
    #        DEFINE THE AUGMENTATIONS      #
    #                                      #
    ########################################

    my_transforms = []
    mirror_transform = MirrorTransform(axes=(1, 2))
    my_transforms.append(mirror_transform)
    crop_size = config_dict["data"]["crop_size"]
    img_shape = config_dict["data"]["img_shape"]
    shape_limit = config_dict["data"]["shape_limit"]

    if (crop_size is not None and crop_size[0] == crop_size[1]) or \
        (img_shape is not None and len(img_shape) > 1
            and img_shape[0] == img_shape[1]):
        rot_transform = Rot90Transform(axes=(0, 1), p_per_sample=0.5)
        my_transforms.append(rot_transform)
    else:
        rot_transform = Rot90Transform(axes=(0, 1),
                                       num_rot=(0, 2),
                                       p_per_sample=0.5)
        my_transforms.append(rot_transform)

    # apply a more extended augmentation (if desiered)
    if "ext_aug" in config_dict["data"].keys() and \
            config_dict["data"]["ext_aug"] is not None and \
            config_dict["data"]["ext_aug"]:

        if crop_size is not None:
            size = [crop_size[0] + 25, crop_size[1] + 25]
        elif img_shape is not None:
            size = [img_shape[0] + 5, img_shape[1] + 5]
        elif shape_limit is not None:
            size = [shape_limit[0] + 5, shape_limit[1] + 5]
        else:
            raise KeyError("Crop size or image shape requried!")

        if crop_size is not None:
            spatial_transforms = SpatialTransform([size[0] - 25, size[1] - 25],
                                                  np.asarray(size) // 2,
                                                  do_elastic_deform=False,
                                                  do_rotation=True,
                                                  angle_x=(0, 0.01 * np.pi),
                                                  do_scale=True,
                                                  scale=(0.9, 1.1),
                                                  random_crop=True,
                                                  border_mode_data="mirror",
                                                  border_mode_seg="mirror")
            my_transforms.append(spatial_transforms)

        elif img_shape is not None or shape_limit is not None:
            spatial_transforms = SpatialTransform(
                [size[0] - 5, size[1] - 5],
                np.asarray(size) // 2,
                do_elastic_deform=False,
                do_rotation=False,
                #angle_x=(0, 0.01 * np.pi),
                do_scale=True,
                scale=(0.9, 1.1),
                random_crop=True,
                border_mode_data="constant",
                border_mode_seg="nearest")
            my_transforms.append(spatial_transforms)

    # bbox generation
    bb_transform = ConvertSegToBB(dim=2, margin=margin)
    my_transforms.append(bb_transform)

    transforms = Compose(my_transforms)

    ########################################
    #                                      #
    #   DEFINE THE DATASETS and MANAGER    #
    #                                      #
    ########################################

    # paths to csv files containing labels (and other information)
    csv_calc_train = '/home/temp/moriz/data/' \
                     'calc_case_description_train_set.csv'
    csv_mass_train = '/home/temp/moriz/data/' \
                     'mass_case_description_train_set.csv'

    # path to data directory
    ddsm_dir = '/home/temp/moriz/data/CBIS-DDSM/'

    # path to data directory
    inbreast_dir = '/images/Mammography/INbreast/AllDICOMs/'

    # paths to csv files containing labels (and other information)
    xls_file = '/images/Mammography/INbreast/INbreast.xls'

    # determine class and load function
    if config_dict["data"]["dataset_type"] == "INbreast":
        dataset_cls = CacheINbreastDataset
        data_dir = inbreast_dir
        csv_file = None

        if config_dict["data"]["level"] == "crops":
            load_fn = inbreast_utils.load_pos_crops
        elif config_dict["data"]["level"] == "images":
            load_fn = inbreast_utils.load_sample
        elif config_dict["data"]["level"] == "both":
            #TODO: fix
            load_fn = inbreast_utils.load_sample_and_crops
        else:
            raise TypeError("Level required!")
    elif config_dict["data"]["dataset_type"] == "DDSM":
        data_dir = ddsm_dir

        if config_dict["data"]["level"] == "crops":
            load_fn = ddsm_utils.load_pos_crops
        elif config_dict["data"]["level"] == "images":
            load_fn = ddsm_utils.load_sample
        elif config_dict["data"]["level"] == "images+":
            load_fn = ddsm_utils.load_sample_with_crops
        else:
            raise TypeError("Level required!")

        if config_dict["data"]["type"] == "mass":
            csv_file = csv_mass_train
        elif config_dict["data"]["type"] == "calc":
            csv_file = csv_calc_train
        elif config_dict["data"]["type"] == "both":
            raise NotImplementedError("Todo")
        else:
            raise TypeError("Unknown lesion type!")

        if "mode" in config_dict["data"].keys():
            if config_dict["data"]["mode"] == "lazy":
                dataset_cls = LazyDDSMDataset

                if config_dict["data"]["level"] == "crops":
                    load_fn = ddsm_utils.load_single_pos_crops

            elif config_dict["data"]["mode"] == "cache":
                dataset_cls = CacheDDSMDataset
            else:
                raise TypeError("Unsupported loading mode!")
        else:
            dataset_cls = CacheDDSMDataset

    else:
        raise TypeError("Dataset is not supported!")

    dataset_train_dict = {
        'data_path': data_dir,
        'xls_file': xls_file,
        'csv_file': csv_file,
        'load_fn': load_fn,
        'num_elements': config_dict["debug"]["n_train"],
        **config_dict["data"]
    }

    dataset_val_dict = {
        'data_path': data_dir,
        'xls_file': xls_file,
        'csv_file': csv_file,
        'load_fn': load_fn,
        'num_elements': config_dict["debug"]["n_val"],
        **config_dict["data"]
    }

    datamgr_train_dict = {
        'batch_size': params.nested_get("batch_size"),
        'n_process_augmentation': 4,
        'transforms': transforms,
        'sampler_cls': RandomSampler,
        'data_loader_cls': BaseDataLoader
    }

    datamgr_val_dict = {
        'batch_size': params.nested_get("batch_size"),
        'n_process_augmentation': 4,
        'transforms': transforms,
        'sampler_cls': SequentialSampler,
        'data_loader_cls': BaseDataLoader
    }

    ########################################
    #                                      #
    #   INITIALIZE THE ACTUAL EXPERIMENT   #
    #                                      #
    ########################################
    checkpoint_path = config_dict["checkpoint_path"]["path"]
    # if "checkpoint_path" in args and args["checkpoint_path"] is not None:
    #     checkpoint_path = args.get("checkpoint_path")

    experiment = \
        RetinaNetExperiment(params,
                            RetinaNet,
                            name = config_dict["logging"]["name"],
                            save_path = checkpoint_path,
                            dataset_cls=dataset_cls,
                            dataset_train_kwargs=dataset_train_dict,
                            datamgr_train_kwargs=datamgr_train_dict,
                            dataset_val_kwargs=dataset_val_dict,
                            datamgr_val_kwargs=datamgr_val_dict,
                            optim_builder=create_optims_default_pytorch,
                            gpu_ids=list(range(args.get('gpus'))),
                            val_score_key="val_FocalLoss",
                            val_score_mode="lowest",
                            checkpoint_freq=2)

    ########################################
    #                                      #
    # LOGGING DEFINITION AND CONFIGURATION #
    #                                      #
    ########################################

    logger_kwargs = config_dict["logging"]

    # setup initial logging
    log_file = os.path.join(experiment.save_path, 'logger.log')

    logging.basicConfig(level=logging.INFO,
                        handlers=[
                            TrixiHandler(PytorchVisdomLogger,
                                         **config_dict["logging"]),
                            logging.StreamHandler(),
                            logging.FileHandler(log_file)
                        ])

    logger = logging.getLogger("RetinaNet Logger")

    with open(experiment.save_path + "/config.yml", 'w') as file:
        yaml.dump(config_dict, file)

    ########################################
    #                                      #
    #       LOAD PATHS AND EXECUTE MODEL   #
    #                                      #
    ########################################
    seed = config_dict["data"]["seed"]

    if "train_size" in config_dict["data"].keys():
        train_size = config_dict["data"]["train_size"]

    if "val_size" in config_dict["data"].keys():
        val_size = config_dict["data"]["val_size"]

    if config_dict["data"]["dataset_type"] == "INbreast":
        if not config_dict["kfold"]["enable"]:


            train_paths, _, val_paths = \
                inbreast_utils.load_single_set(inbreast_dir,
                                               xls_file=xls_file,
                                               train_size=train_size,
                                               val_size=val_size,
                                               type=config_dict["data"]["type"],
                                               random_state=seed)

            if img_shape is not None or crop_size is not None:
                experiment.run(train_paths, val_paths)
            else:
                experiment.run(train_paths, None)

        else:
            paths = inbreast_utils.get_paths(inbreast_dir,
                                             xls_file=xls_file,
                                             type=config_dict["data"]["type"])

            if "splits" in config_dict["kfold"].keys():
                num_splits = config_dict["kfold"]["splits"]
            else:
                num_splits = 5

            experiment.kfold(paths,
                             num_splits=num_splits,
                             random_seed=seed,
                             dataset_type="INbreast")

    else:
        train_paths, val_paths, _ = \
            ddsm_utils.load_single_set(ddsm_dir,
                                       csv_file=csv_file,
                                       train_size=train_size,
                                       val_size=None,
                                       random_state=seed)

        if img_shape is not None or crop_size is not None:
            experiment.run(train_paths, val_paths)
        else:
            experiment.run(train_paths, None)
예제 #15
0
def train(model_cls,
          model_kwargs: dict,
          outpath: str,
          data_path,
          exp_name=None,
          batchsize=64,
          num_epochs=1500,
          checkpoint_freq=10,
          additional_losses: dict = None,
          dset_type="mnist",
          key_mapping=None,
          create_optim_fn=None):

    if exp_name is None:
        exp_name = model_cls.__name__

    if additional_losses is None:
        additional_losses = {}

    if create_optim_fn is None:
        create_optim_fn = create_optims

    outpath = os.path.expanduser(outpath)

    losses = {"adversarial": AdversarialLoss()}
    losses.update(additional_losses)
    params = Parameters(
        fixed_params={
            "model": {
                **model_kwargs
            },
            "training": {
                "num_epochs": num_epochs,
                "batchsize": batchsize,
                "losses": losses,
                "val_metrics": {},
                "optimizer_cls": torch.optim.Adam,
                "optimizer_params": {
                    "lr": 0.001,
                    "betas": (0.5, 0.9995)
                },
                "scheduler_cls": None,
                "scheduler_params": {}
            }
        })
    data = setup_data(data_path, params.nested_get("batchsize"), 4,
                      RangeTransform(), RangeTransform(), dset_type)
    exp = PyTorchExperiment(params,
                            model_cls,
                            params.nested_get("num_epochs"),
                            name=exp_name,
                            save_path=outpath,
                            key_mapping=key_mapping,
                            optim_builder=create_optim_fn,
                            checkpoint_freq=checkpoint_freq,
                            gpu_ids=[0])

    model = exp.run(data["train"], data["val"])
    weight_dir = os.path.join(exp.save_path, "checkpoints", "run_00")

    return model, weight_dir