Beispiel #1
0
def train(arguments):
    dls = UpscalerDataset(arguments.dataset_path,
                          arguments.resized_dataset_path)
    feat_loss = get_loss(arguments.loss_model_path)

    learner = unet_learner(dls.get_dataloaders(bs, size),
                           arch,
                           loss_func=feat_loss,
                           metrics=LossMetrics(feat_loss.metric_names),
                           blur=True,
                           norm_type=NormType.Weight)

    # stage 1
    print('stage 1')
    do_fit(learner, wd, slice(lr * 10))
    learner.unfreeze()
    do_fit(learner, wd, slice(1e-5, lr))

    # checkpoint
    learner.save('checkpoint')
    learner.load('checkpoint')
    # stage 2
    print('stage 2')
    del learner.dls
    learner.dls = dls.get_dataloaders(5, size * 2)
    learner.freeze()
    do_fit(learner, wd, slice(lr))
    learner.unfreeze()
    do_fit(learner, wd, slice(1e-6, 1e-4), pct_start=0.3)

    # save
    torch.save({
        'model': learner.model,
        'meta': make_meta(arguments)
    }, arguments.output)
Beispiel #2
0
def multi_task_unet_learner(*args, log_vars=None, **kwargs):
    """
    Creates a learner suited for classification+segmentation multii-task
    learning problem

    args: positional arguments for cnn_learner and unet_learner
    kwargs: keayword arguments for cnn_learner and unet_learner

    return: learner that contains MultiTaskModel
    """
    unet_learn = unet_learner(*args, **kwargs)
    sfs_idxs = unet_learn.model.sfs_idxs
    cnn_learn = cnn_learner(*args, **kwargs)
    base = unet_learn.model[0]
    unet_head = unet_learn.model[1:]
    hooks = hook_outputs([base[i] for i in sfs_idxs])
    for block, hook in zip(unet_head[3:7], hooks):
        block.hook = hook
    heads = [cnn_learn.model[1:], unet_head]
    unet_learn.model = MultiTaskModel(base, heads, log_vars=log_vars).to(
        unet_learn.data.device)
    lg = unet_learn.layer_groups
    lg[2] = nn.Sequential(*list(lg[2]), *flatten_model(heads[0]),
                          unet_learn.model.log_vars)
    unet_learn.layer_groups = lg
    unet_learn.create_opt(slice(1e-3))
    return unet_learn
Beispiel #3
0
    def __init__(self, data, backbone=None, pretrained_path=None):
      
        super().__init__()

        self._device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')

        if not HAS_FASTAI:
            _raise_fastai_import_error()

        self._emd_template = _EMD_TEMPLATE
        self._code = image_classifier_prf

        if backbone is None:
            self._backbone = models.resnet34
        elif type(backbone) is str:
            self._backbone = getattr(models, backbone)
        else:
            self._backbone = backbone

        acc_metric = partial(accuracy, void_code=0, class_mapping=data.class_mapping)
        self._data = data
        self.learn = unet_learner(data, arch=self._backbone, metrics=acc_metric, wd=1e-2, bottle=True, last_cross=True)
        self.learn.model = self.learn.model.to(self._device)

        if pretrained_path is not None:
            self.load(pretrained_path)
Beispiel #4
0
 def __init__(self, data, backbone=None, pretrained_path=None, *args, **kwargs):
     super().__init__(data, backbone)
     feat_loss = create_loss(self._device.type)
     data.c = 3
     self.learn = unet_learner(data, arch=self._backbone, wd=1e-3, loss_func=feat_loss, callback_fns=LossMetrics, blur=True, norm_type=NormType.Weight)
     self.learn.model = self.learn.model.to(self._device)
     if pretrained_path is not None:
         self.load(pretrained_path)
     
     self._code = super_resolution
Beispiel #5
0
    def __init__(self, data, backbone=None, pretrained_path=None):

        super().__init__(data, backbone)

        self._code = image_classifier_prf

        backbone_cut = None
        backbone_split = None

        _backbone = self._backbone
        if hasattr(self, '_backbone_'):
            _backbone = self._backbone_

        if not (self._check_backbone_support(_backbone)):
            raise Exception(
                f"Enter only compatible backbones from {', '.join(self.supported_backbones)}"
            )

        if hasattr(self, '_backbone_'):
            _backbone_meta = cnn_config(self._backbone_)
            backbone_cut = _backbone_meta['cut']
            backbone_split = _backbone_meta['split']

        acc_metric = partial(accuracy,
                             void_code=0,
                             class_mapping=data.class_mapping)
        self.learn = unet_learner(data,
                                  arch=self._backbone,
                                  metrics=acc_metric,
                                  wd=1e-2,
                                  bottle=True,
                                  last_cross=True,
                                  cut=backbone_cut,
                                  split_on=backbone_split)
        self._arcgis_init_callback()  # make first conv weights learnable
        self.learn.callbacks.append(LabelCallback(
            self.learn))  #appending label callback

        self.learn.model = self.learn.model.to(self._device)

        # _set_multigpu_callback(self) # MultiGPU doesn't work for U-Net. (Fastai-Forums)
        if pretrained_path is not None:
            self.load(pretrained_path)
Beispiel #6
0
def get_segmentation_learner(dls,
                             number_classes,
                             segmentation_type,
                             architecture_name,
                             backbone_name,
                             loss_func=None,
                             opt_func=Adam,
                             lr=defaults.lr,
                             splitter=trainable_params,
                             cbs=None,
                             pretrained=True,
                             normalize=True,
                             image_size=None,
                             metrics=None,
                             path=None,
                             model_dir='models',
                             wd=None,
                             wd_bn_bias=False,
                             train_bn=True,
                             moms=(0.95, 0.85, 0.95)):
    """This function return a learner for the provided architecture and backbone

    Parameters:
    dls (DataLoader): the dataloader to use with the learner
    number_classes (int): the number of clases in the project. It should be >=2
    segmentation_type (str): just `Semantic Segmentation` accepted for now 
    architecture_name (str): name of the architecture. The following ones are supported: `unet`, `deeplabv3+`, `hrnet`, `maskrcnn` and `u2^net`
    backbone_name (str): name of the backbone
    loss_func (): loss function.
    opt_func (): opt function.
    lr (): learning rates
    splitter (): splitter function for freazing the learner
    cbs (List[cb]): list of callbacks
    pretrained (bool): it defines if a trained backbone is needed
    normalize (bool): 
    image_size (int): REQUIRED for MaskRCNN. It indicates the desired size of the image.
    metrics (List[metric]): list of metrics
    path (): path parameter
    model_dir (str): the path in which save models
    wd (float): wieght decay
    wd_bn_bias (bool):
    train_bn (bool):
    moms (Tuple(float)): tuple of different momentuns
                    

    Returns:
    learner: value containing the learner object

    """

    number_classes_name = ""
    if number_classes == 2:
        number_classes_name = "binary"
    elif number_classes > 2:
        number_classes_name = "multiple"
    else:
        raise Exception("The number of classes must be >=2")

    check_architecture_configuration(number_classes=number_classes_name,
                                     segmentation_type=segmentation_type,
                                     architecture_name=architecture_name,
                                     backbone_name=backbone_name)

    learner = None

    if architecture_name == "unet":

        # TODO -> Revisar arch
        learner = unet_learner(dls=dls,
                               arch=unet_backbone_name[backbone_name],
                               metrics=metrics,
                               wd=wd,
                               loss_func=loss_func,
                               opt_func=opt_func,
                               lr=lr,
                               splitter=splitter,
                               cbs=cbs,
                               path=path,
                               model_dir=model_dir,
                               wd_bn_bias=wd_bn_bias,
                               train_bn=train_bn,
                               pretrained=pretrained,
                               normalize=normalize,
                               moms=moms)

    elif architecture_name == "deeplabv3+":

        model = DeepLabV3Plus(backbone_name=backbone_name,
                              nclass=number_classes,
                              pretrained=pretrained)
        learner = Learner(dls=dls,
                          model=model,
                          loss_func=loss_func,
                          opt_func=opt_func,
                          lr=lr,
                          splitter=splitter,
                          cbs=cbs,
                          metrics=metrics,
                          path=path,
                          model_dir=model_dir,
                          wd=wd,
                          wd_bn_bias=wd_bn_bias,
                          train_bn=train_bn)

    elif architecture_name == "hrnet":

        model = HRNet(nclass=number_classes,
                      backbone_name=backbone_name,
                      pretrained=pretrained)
        learner = Learner(dls=dls,
                          model=model,
                          loss_func=loss_func,
                          opt_func=opt_func,
                          lr=lr,
                          splitter=splitter,
                          cbs=cbs,
                          metrics=metrics,
                          path=path,
                          model_dir=model_dir,
                          wd=wd,
                          wd_bn_bias=wd_bn_bias,
                          train_bn=train_bn)

    elif architecture_name == "maskrcnn":
        if image_size is None:
            raise Exception(
                "MaskRCNN need to define image_size. This values are for reescaling the image"
            )

        model = maskrcnn_resnet50_fpn(num_classes=number_classes,
                                      min_size=image_size,
                                      max_size=image_size)
        learner = mask_rcnn.MaskRCNNLearner(dls=dls,
                                            model=model,
                                            loss_func=loss_func,
                                            opt_func=opt_func,
                                            lr=lr,
                                            splitter=splitter,
                                            cbs=cbs,
                                            metrics=metrics,
                                            path=path,
                                            model_dir=model_dir,
                                            wd=wd,
                                            wd_bn_bias=wd_bn_bias,
                                            train_bn=train_bn)

    elif architecture_name == "u2^net":
        model = None
        if backbone_name == "small":
            model = u2net.U2NETP(3, 1)
        elif backbone_name == "normal":
            model = u2net.U2NET(3, 1)

        learner = u2net.USquaredNetLearner(dls=dls,
                                           model=model,
                                           opt_func=opt_func,
                                           lr=lr,
                                           splitter=splitter,
                                           cbs=cbs,
                                           metrics=metrics,
                                           path=path,
                                           model_dir=model_dir,
                                           wd=wd,
                                           wd_bn_bias=wd_bn_bias,
                                           train_bn=train_bn)

    return learner
Beispiel #7
0
def run():
    models = {
        'resnet34': mod.resnet34,
        'resnet50': mod.resnet50,
        'resnet101': mod.resnet101,
        'resnet152': mod.resnet152
    }

    save_name = f'seg_{cfg.MODEL}_{cfg.TRAIN_SIZE}'
    save_name = f'{save_name}_{getNextFilePath(cfg.MODELS_PATH, save_name)}'

    test_list = (SegmentationItemList.from_folder(cfg.TEST_PATH,
                                                  extensions=['.dcm']))
    best = 0

    pred_path = cfg.PRED_PATH / save_name
    if not pred_path.is_dir():
        pred_path.mkdir()

    project = neptune.init('schwobr/SIIM-Pneumothorax')

    for k, db in enumerate(
            load_data_kfold(cfg.LABELS,
                            bs=cfg.BATCH_SIZE,
                            seed=cfg.SEED,
                            train_size=cfg.TRAIN_SIZE,
                            xtra_tfms=[gaussian_noise()])):
        print(f'fold {k}')

        learner = unet_learner(db,
                               models[cfg.MODEL],
                               pretrained=cfg.PRETRAINED,
                               wd=cfg.WD,
                               model_dir=cfg.MODELS_PATH,
                               metrics=[dice],
                               loss_func=URLoss(CrossEntropyLoss(),
                                                reduction='sum',
                                                do_spatial_reduc=True))

        fold_name = f'fold{k}_' + save_name
        set_BN_momentum(learner.model, momentum=0.01)
        # replace_bn(learner, learner.model)

        learner.fit_one_cycle(
            cfg.EPOCHS,
            slice(cfg.LR),
            callbacks=[
                SaveModelCallback(learner, monitor='dice', name=fold_name),
                AccumulateScheduler(learner, min(8, 64 // cfg.BATCH_SIZE)),
                # LookAhead(learner, k=max(6, 64 // cfg.BATCH_SIZE)),
                NeptuneCallback(learner,
                                project,
                                name=fold_name,
                                params={
                                    'lr': cfg.LR,
                                    'wd': cfg.WD,
                                    'size': cfg.TRAIN_SIZE
                                })
            ])

        met = max([met[0] for met in learner.recorder.metrics])

        if met > best:
            learner.save(save_name)
            best = met
            print(f'New best fold {k} with dice {best}')

        # learner.neptune_callback.send_artifact(
        #    cfg.MODELS_PATH/(fold_name+'.pth'))
        learner.neptune_callback.stop()

        learner.unfreeze()
        fold_name = 'uf_' + fold_name

        learner.fit_one_cycle(cfg.UNFROZE_EPOCHS,
                              slice(cfg.UF_LR / 100, cfg.UF_LR),
                              callbacks=[
                                  SaveModelCallback(learner,
                                                    monitor='dice',
                                                    name=fold_name),
                                  AccumulateScheduler(learner,
                                                      64 // cfg.BATCH_SIZE),
                                  NeptuneCallback(learner,
                                                  project,
                                                  name=fold_name,
                                                  params={
                                                      'lr': cfg.LR,
                                                      'wd': cfg.WD,
                                                      'size': cfg.TRAIN_SIZE
                                                  })
                              ])

        met = max([met[0] for met in learner.recorder.metrics])

        if met > best:
            learner.save(save_name)
            best = met
            print(f'New best fold {k} with dice {best}')

        # learner.neptune_callback.send_artifact(
        #    cfg.MODELS_PATH/(fold_name+'.pth'))
        learner.neptune_callback.stop()

        learner.data.add_test(test_list,
                              label=[test_list.items[0], '-1'],
                              tfms=(),
                              tfm_y=True)

        save_preds(learner, pred_path / str(k))

    exp = project.create_experiment(name=save_name,
                                    description='k-fold mtl training',
                                    params={
                                        'lr': cfg.LR,
                                        'wd': cfg.WD,
                                        'size': cfg.TRAIN_SIZE
                                    })

    # exp.send_artifact(cfg.MODELS_PATH/(save_name+'.pth'))

    learner.load(save_name)
    learner.data.add_test(test_list,
                          label=[test_list.items[0], '-1'],
                          tfms=(),
                          tfm_y=True)

    thr = get_best_thr(learner,
                       plot=False,
                       test_size=cfg.TEST_SIZE,
                       exp=None,
                       fig_path=cfg.FIG_PATH / (save_name + '.png'))

    create_submission_kfold(learner,
                            cfg.SUB_PATH / (save_name + '.csv'),
                            pred_path,
                            test_size=cfg.TEST_SIZE,
                            thr=thr)

    exp.send_artifact(cfg.SUB_PATH / (save_name + '.csv'))
    exp.stop()
    def __init__(self,
                 data,
                 backbone=None,
                 pretrained_path=None,
                 backend='pytorch',
                 *args,
                 **kwargs):

        self._backend = backend
        if self._backend == 'tensorflow':
            super().__init__(data, None)
            self._intialize_tensorflow(data, backbone, pretrained_path, kwargs)
        else:
            super().__init__(data, backbone)

            # import pdb; pdb.set_trace();
            self._ignore_classes = kwargs.get('ignore_classes', [])
            if self._ignore_classes != [] and len(data.classes) <= 3:
                raise Exception(
                    f"`ignore_classes` parameter can only be used when the dataset has more than 2 classes."
                )

            data_classes = list(self._data.class_mapping.keys())
            if 0 not in list(data.class_mapping.values()):
                self._ignore_mapped_class = [
                    data_classes.index(k) + 1 for k in self._ignore_classes
                    if k != 0
                ]
            else:
                self._ignore_mapped_class = [
                    data_classes.index(k) + 1 for k in self._ignore_classes
                ]
            if self._ignore_classes != []:
                if 0 not in self._ignore_mapped_class:
                    self._ignore_mapped_class.insert(0, 0)
                global accuracy
                accuracy = partial(
                    accuracy, ignore_mapped_class=self._ignore_mapped_class)

            self.mixup = kwargs.get('mixup', False)
            self.class_balancing = kwargs.get('class_balancing', False)
            self.focal_loss = kwargs.get('focal_loss', False)

            self._code = image_classifier_prf

            backbone_cut = None
            backbone_split = None

            _backbone = self._backbone
            if hasattr(self, '_orig_backbone'):
                _backbone = self._orig_backbone

            if not (self._check_backbone_support(_backbone)):
                raise Exception(
                    f"Enter only compatible backbones from {', '.join(self.supported_backbones)}"
                )

            if hasattr(self, '_orig_backbone'):
                _backbone_meta = cnn_config(self._orig_backbone)
                backbone_cut = _backbone_meta['cut']
                backbone_split = _backbone_meta['split']

            if not _isnotebook() and arcgis_os.name == 'posix':
                _set_ddp_multigpu(self)
                if self._multigpu_training:
                    self.learn = unet_learner(
                        data,
                        arch=self._backbone,
                        metrics=accuracy,
                        wd=1e-2,
                        bottle=True,
                        last_cross=True,
                        cut=backbone_cut,
                        split_on=backbone_split).to_distributed(
                            self._rank_distributed)
                else:
                    self.learn = unet_learner(data,
                                              arch=self._backbone,
                                              metrics=accuracy,
                                              wd=1e-2,
                                              bottle=True,
                                              last_cross=True,
                                              cut=backbone_cut,
                                              split_on=backbone_split)
            else:
                self.learn = unet_learner(data,
                                          arch=self._backbone,
                                          metrics=accuracy,
                                          wd=1e-2,
                                          bottle=True,
                                          last_cross=True,
                                          cut=backbone_cut,
                                          split_on=backbone_split)

            if self.class_balancing:
                if data.class_weight is not None:
                    class_weight = torch.tensor(
                        [data.class_weight.mean()] +
                        data.class_weight.tolist()).float().to(self._device)
                else:
                    if getattr(data, 'overflow_encountered', False):
                        logger.warning(
                            "Overflow Encountered. Ignoring `class_balancing` parameter."
                        )
                        class_weight = [1] * len(data.classes)
                    else:
                        logger.warning(
                            "Could not find 'NumPixelsPerClass' in 'esri_accumulated_stats.json'. Ignoring `class_balancing` parameter."
                        )

            if self._ignore_classes != []:
                if not self.class_balancing:
                    class_weight = torch.tensor([1] * data.c).float().to(
                        self._device)
                class_weight[self._ignore_mapped_class] = 0.
            else:
                class_weight = None

            self.learn.loss_func = CrossEntropyFlat(class_weight, axis=1)

            if self.focal_loss:
                self.learn.loss_func = FocalLoss(self.learn.loss_func)
            if self.mixup:
                self.learn.callbacks.append(MixUpCallback(self.learn))

            self._arcgis_init_callback()  # make first conv weights learnable
            self.learn.callbacks.append(LabelCallback(
                self.learn))  #appending label callback

            self.learn.model = self.learn.model.to(self._device)
            # _set_multigpu_callback(self) # MultiGPU doesn't work for U-Net. (Fastai-Forums)
            if pretrained_path is not None:
                self.load(pretrained_path)