Ejemplo n.º 1
0
 def __init__(self, config):
     super(LesionModel, self).__init__()
     if config["A"] == "unet":
         self.model = smp.Unet(
             encoder_name=config[
                 "EN"],  # choose encoder, e.g. mobilenet_v2 or efficientnet-b7
             encoder_weights=config["encoder_weights"],
             # use `imagenet` pre-trained weights for encoder initialization
             in_channels=
             3,  # model input channels (1 for gray-scale images, 3 for RGB, etc.)
             classes=config[
                 "OC"],  # model output channels (number of classes in your dataset)
         )
     elif config["A"] == "DeepLabV3Plus":
         self.model = smp.DeepLabV3Plus(
             encoder_name=config[
                 "EN"],  # choose encoder, e.g. mobilenet_v2 or efficientnet-b7
             encoder_weights=config["encoder_weights"],
             # use `imagenet` pre-trained weights for encoder initialization
             in_channels=
             3,  # model input channels (1 for gray-scale images, 3 for RGB, etc.)
             classes=config[
                 "OC"],  # model output channels (number of classes in your dataset)
         )
     self.model_cfg = config
     self.loss_function = DiceLoss()
     self.save_hyperparameters()
     self.iou_function = IOU()
     self.checkpoint_path = ""
Ejemplo n.º 2
0
def train(img_path, ori_seg_path, label_path, ckpt_path, xls_path):
    wb = xlwt.Workbook()
    ws = wb.add_sheet('dice loss')

    model = UNet(channels_in=4, channels_out=1)
    model.apply(init_weight)

    train_set = Dataset4Layers(img_path, ori_seg_path, label_path, 'train')
    train_loader = DataLoader(train_set, batch_size=3, shuffle=True)
    val_set = Dataset4Layers(img_path, ori_seg_path, label_path, 'val')
    val_loader = DataLoader(val_set, batch_size=3, shuffle=False)

    opt = Adam(model.parameters(), lr=1e-4, betas=(0.9, 0.999))
    sch = StepLR(opt, step_size=20, gamma=0.7)
    loss = DiceLoss()

    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    model = model.float().to(device)

    max_epoch = 151
    cnt = 0
    stop_count = 15
    min_dice_loss = 1.
    stop_flag = False
    for i in range(max_epoch):
        dice_loss_train = epoch_step(train_loader, model, opt, loss, 'train',
                                     device)
        dice_loss_val = epoch_step(val_loader, model, opt, loss, 'val', device)
        loss_list = [dice_loss_train, dice_loss_val]
        for j in range(len(loss_list)):
            ws.write(i, j, loss_list[j])

        print(
            f'in epoch{i}: train dice loss is {dice_loss_train}, val dice loss is {dice_loss_val}'
        )

        if dice_loss_val < min_dice_loss:
            min_dice_loss = dice_loss_val
            save_ckpt(ckpt_path, i, model.state_dict())
            cnt = 0
        else:
            cnt = cnt + 1
        if cnt == stop_count:
            stop_flag = True
            break
        sch.step()

    if not stop_flag:
        save_ckpt(ckpt_path, max_epoch - 1, model.state_dict())

    if not os.path.exists(xls_path):
        os.mkdir(xls_path)
    wb.save(os.path.join(xls_path, 'seg_of_rectum_unet.xls'))
Ejemplo n.º 3
0
def train(img_path, label_path, ckpt_path, xls_path, ws, model, model_name,
          Dataset, vgg_tag):
    train_set = Dataset(img_path, label_path, 'train')
    train_loader = DataLoader(train_set, batch_size=3, shuffle=True)
    val_set = Dataset(img_path, label_path, 'val')
    val_loader = DataLoader(val_set, batch_size=3, shuffle=False)

    opt = Adam(model.parameters(), 1e-4, betas=(0.9, 0.999))
    sch = StepLR(opt, step_size=30, gamma=0.8)
    loss = DiceLoss()
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    model = model.float().to(device)

    max_epoch = 151
    # max_epoch = 2
    cnt = 0
    stop_count = 15
    min_dice_loss = 1.
    stop_flag = False
    for i in range(max_epoch):
        dice_loss_train = epoch_step(train_loader, model, opt, vgg_tag, loss,
                                     'train', device)
        # dice_loss_train = epoch_step(val_loader, model, opt, vgg_tag, loss, 'train', device)
        dice_loss_val = epoch_step(val_loader, model, opt, vgg_tag, loss,
                                   'val', device)
        loss_list = [dice_loss_train, dice_loss_val]
        for j in range(len(loss_list)):
            ws.write(i, j, loss_list[j])

        print(
            f'in epoch{i}: train dice loss is {dice_loss_train}, val dice loss is {dice_loss_val}'
        )

        if dice_loss_val < min_dice_loss:
            min_dice_loss = dice_loss_val
            save_ckpt(ckpt_path, model_name, i, model.state_dict())
            cnt = 0
        else:
            cnt = cnt + 1
        if cnt == stop_count:
            stop_flag = True
            break
        sch.step()

    if not stop_flag:
        save_ckpt(ckpt_path, model_name, max_epoch - 1, model.state_dict())
    return ws
Ejemplo n.º 4
0
 def train(self):
     model = Net_design(self.used_model_list)
     device = torch.cuda.current_device()
     dataset = trainSampler(self.data_path)
     train_loader = DataLoader(dataset,
                               batch_size=self.batch_size,
                               shuffle=True,
                               num_workers=8,
                               pin_memory=True)
     if self.opreater == 'Adam':
         optimizer = optim.Adam(model.parameters(), lr=self.learning_rate)
     elif self.opreater == 'SGD':
         optimizer = optim.SGD(model.parameters(), lr=self.learning_rate)
     else:
         optimizer = optim.SGD(model.parameters(),
                               lr=self.learning_rate,
                               momentum=0.9)
     if self.loss_func == 'CE':
         criterion = nn.CrossEntropyLoss()
     else:
         criterion = DiceLoss()
     with open(os.path.join(self.save_dir, 'train_log.txt'), 'a') as f:
         for ep in range(self.epoch):
             model.train()
             epoch_loss = 0.0
             for batch in train_loader:
                 imgs = batch['image']
                 true_masks = batch['mask']
                 imgs = imgs.to(device=device, dtype=torch.float32)
                 true_masks = true_masks.to(device=device,
                                            dtype=torch.float32)
                 masks_pred = model(imgs)
                 loss = criterion(masks_pred, true_masks)
                 f.write("epoch is {}:loss is {}" % {(ep + 1), loss.item()})
                 logging.info("epoch is {epoch + 1}:loss is {loss.item()}")
                 epoch_loss += loss.item()
                 optimizer.zero_grad()
                 loss.backward()
                 optimizer.step()
             if ep % 5000 == 0:
                 torch.save(model.state_dict(),
                            self.save_dir + f'CP_epoch{ep + 1}.pth')
    def _set_threshold(pred, target, optimize_for: str = "dice"):
        # set threshold which minimizes hausdorff distance, handles outliers
        possible_values = np.arange(0.20, 1, 0.05)
        threshold = False
        best = 10000000000000
        for t in possible_values:
            tmp_pred = deepcopy(pred)
            tmp_pred[tmp_pred >= t] = 1  # doesnt matter for hausdorff as all non zeros count
            tmp_pred[tmp_pred < t] = 0

            if optimize_for == "dice":
                metric = DiceLoss.dice_loss(tmp_pred, target, return_loss=True)  # to conform with less is better of hausdorff
            elif optimize_for == "hausdorff":
                metric = hausdorff_distance(tmp_pred, target)

            if metric < best:
                best = metric
                threshold = t
        del tmp_pred
        return threshold
Ejemplo n.º 6
0
    def _set_threshold(pred, target, optimize_for: str = "dice"):
        # set threshold which minimizes hausdorff distance, handles outliers
        if pred.shape[1] == 2:
            # 2 sturctures use argmax
            return [None, False
                    ]  # doesnt matter isnt used but needs same len of channels
        possible_values = np.arange(0.20, 1, 0.05)
        threshold = [False for _ in range(pred.shape[1])]
        for channel_idx in range(pred.shape[1]):
            best = 10000000000000
            for t in possible_values:
                tmp_pred = deepcopy(
                    torch.unsqueeze(pred[:, channel_idx],
                                    dim=0))  # (1,1,x,y,z)
                tmp_target = deepcopy(
                    torch.unsqueeze(target[:, channel_idx],
                                    dim=0))  # (1,1,x,y,z)

                tmp_pred[
                    tmp_pred >=
                    t] = 1  # doesnt matter for hausdorff as all non zeros count
                tmp_pred[tmp_pred < t] = 0

                if optimize_for == "dice":
                    metric = DiceLoss.dice_loss(
                        tmp_pred, tmp_target, return_loss=True
                    )  # to conform with "less is better" of hausdorff
                elif optimize_for == "hausdorff":
                    metric = hausdorff_distance(
                        np.array(tmp_pred[0, 0].cpu()),
                        np.array(tmp_target[0, 0].cpu()))  # (x,y,z)

                if metric < best:
                    best = metric
                    threshold[channel_idx] = t
        return threshold
Ejemplo n.º 7
0
def train_unit():
    #model = SeTr(image_size=50, patch_size=10, dim=32, depth=4, heads=8, mlp_dim=400, channels=4).to(device)
    model = UNIT().to(device)
    #model = UNet(4).to(device)
    parameter_count = count_parameters(model)
    print('model parameter count: ' + str(parameter_count))

    #criterion = nn.CrossEntropyLoss()
    criterion = DiceLoss()

    optimizer = optim.Adam(model.parameters(), lr=0.003)
    
    scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer)

    epoch = 0
    while epoch != 10000:
        #if(epoch == 500):
        #    criterion = DiceLoss()
        batch_size = 2
        current_batch_index = (int(epoch/1) % (int(340/batch_size)))
        lower_index = (current_batch_index * batch_size) + 11
        upper_index = ((1+current_batch_index) * batch_size) + 11
        
        if epoch < 100:
            lower_index = 12
            upper_index = 14

        if epoch == 80:
            optimizer = optim.Adam(model.parameters(), lr=0.00003)

        if epoch == 400:
            optimizer = optim.Adam(model.parameters(), lr=0.000003)

        #print('lower_index:' + str(lower_index))
        #print('upper_index:' + str(upper_index))
        chunked_images, chunked_segmented_images = load_data(lower_index, upper_index, chunk_x, chunk_y)

        for batch_epoch in range(0, 1):

            running_loss = 0.0
        

            total_size = chunked_images.shape[0]
            subbatch_size = int(total_size / 1)
            current_subbatch_index = 0#epoch % 1
        
 
            model_input = np.copy(chunked_images[current_subbatch_index*subbatch_size:((1 + current_subbatch_index)*subbatch_size)])
            model_output = chunked_segmented_images[current_subbatch_index*subbatch_size:((1 + current_subbatch_index)*subbatch_size)]
        
            model_input= np.copy(chunked_images)
            model_output = np.copy(chunked_segmented_images)

            model_input = model_input.transpose((0, 3, 1, 2))
            model_input = torch.from_numpy(model_input).to(device)

            model_output = model_output.transpose((0, 1, 2))
            model_output = torch.LongTensor(model_output).to(device)

            outputs = model(model_input)
            
            optimizer.zero_grad()
            loss = criterion(outputs, model_output)
            loss.backward()
            optimizer.step()
            scheduler.step(loss)

            running_loss += loss.item()

            print('[%d] loss: %.3f' % (epoch + 1, running_loss))

            if (epoch%500 == 3):
                evaluate(model, True)
                model.train()
            elif(epoch % 30 == 2):
                evaluate(model, False)
                model.train()
            elif (epoch%500 == 4):
                evaluate_train(model, True)
                model.train()
            elif (epoch%30 == 5):
                evaluate_train(model, False)
                model.train()

            
            epoch = epoch + 1 

            del model_input
            del model_output
            del outputs
            del loss
            torch.cuda.empty_cache()
        
        del chunked_images
        del chunked_segmented_images
        torch.cuda.empty_cache()

    return model
Ejemplo n.º 8
0
def train_net(net,
              device,
              output_dir,
              train_date='',
              epochs=20,
              iters=900,
              bs=4,
              lr=0.01,
              save_cp=True,
              only_lastandbest=False,
              eval_freq=5,
              fold_idx=None,
              site='A',
              eval_site=None,
              gpus=None,
              save_folder='',
              aug=False,
              zoom=False,
              whitening=True,
              nonlinear='relu',
              norm_type='BN',
              pretrained=False,
              loaded_model_file_name='model_best',
              spade_seg_mode='soft',
              spade_inferred_mode='mask',
              spade_aux_blocks='',
              freeze_except=None,
              ce_weighted=False,
              spade_reduction=2,
              excluded_classes=None,
              dataset_name=None):
    net.apply(weights_init)
    logging.info('Model Parameters Reset!')
    net.to(device=device)

    if pretrained:
        pretrained_model_dir = pretrained + f'/Fold_{fold_idx}/{loaded_model_file_name}.pth'
        pretrained_dict_load = torch.load(pretrained_model_dir)
        model_dict = net.state_dict()

        pretrained_dict = {}
        for k, v in pretrained_dict_load.items():
            if (k in model_dict) and (model_dict[k].shape
                                      == pretrained_dict_load[k].shape):
                pretrained_dict[k] = v

        model_dict.update(pretrained_dict)
        net.load_state_dict(model_dict)

        print('Freeze Excluded Keywords:', freeze_except)
        if freeze_except is not None:
            for k, v in net.named_parameters():
                v.requires_grad = False
                for except_key in freeze_except:
                    if except_key in k:
                        v.requires_grad = True
                        print(k, ' requires grad')
                        break
        logging.info(f'Model loaded from {pretrained_model_dir}')

    pretrain_suffix = ''
    if pretrained:
        pretrain_suffix = f'_Pretrained'

    block_names = [
        'inc', 'down1', 'down2', 'down3', 'down4', 'mid', 'up1', 'up2', 'up3',
        'up4'
    ]

    spade_blocks_suffix = ''
    if spade_aux_blocks != '':
        if spade_inferred_mode == 'mask':
            spade_blocks_suffix += f'_SPADE_R{spade_reduction}_{spade_seg_mode}_Aux_'
        else:
            spade_blocks_suffix += f'_SPADE_R{spade_reduction}_{spade_inferred_mode}_Aux_'

        for blockname in spade_aux_blocks:
            block_idx = block_names.index(blockname)
            spade_blocks_suffix += str(block_idx)

    excluded_classes_suffix = ''

    if excluded_classes is not None:
        excluded_classes_string = [str(c) for c in excluded_classes]
        excluded_classes_suffix = '_exclude' + ''.join(excluded_classes_string)

    dir_results = output_dir

    tensorboard_logdir = dir_results + 'logs/' + f'{save_folder}/' + f'{train_date}_Site_{site}_GPUs_{gpus}/' + \
                         f'BS_{bs}_Epochs_{epochs}_Aug_{aug}_Zoom_{zoom}_Nonlinear_{nonlinear}_Norm_{norm_type}' + \
                         excluded_classes_suffix + pretrain_suffix + spade_blocks_suffix + f'/Fold_{fold_idx}'
    writer = SummaryWriter(log_dir=tensorboard_logdir)

    dir_checkpoint = dir_results + 'checkpoints/' + f'{save_folder}/' + \
                     f'{train_date}_Site_{site}_GPUs_{gpus}/' + f'Epochs_{epochs}_Aug_{aug}_Zoom_{zoom}_Nonlinear_{nonlinear}_Norm_{norm_type}' + \
                       excluded_classes_suffix + pretrain_suffix + spade_blocks_suffix + f'/Fold_{fold_idx}' + '/'
    print(tensorboard_logdir)
    dir_eval_csv = dir_results + 'eval_csv/' + f'{save_folder}/' + \
                   f'{train_date}_Site_{site}_GPUs_{gpus}/' + f'Epochs_{epochs}_Aug_{aug}_Zoom_{zoom}_Nonlinear_{nonlinear}_Norm_{norm_type}' + \
                   excluded_classes_suffix + pretrain_suffix + spade_blocks_suffix + '/'
    csv_files_prefix = f'{train_date}_Site_{site}_GPUs_{gpus}_'
    print(dir_eval_csv)
    if not os.path.exists(dir_eval_csv):
        os.makedirs(dir_eval_csv)
    train_list = {}
    val_list = {}
    test_list = {}

    train_list['Overall'] = []
    val_list['Overall'] = []
    test_list['Overall'] = []

    if eval_site is None:
        sites_inferred = list(site)
    else:
        sites_inferred = list(set(site + eval_site))
    sites_inferred.sort()
    print(sites_inferred)
    for site_idx in sites_inferred:
        train_list[site_idx] = all_list[site_idx][split_list[site_idx]
                                                  [fold_idx][0]].tolist()
        val_list[site_idx] = all_list[site_idx][split_list[site_idx][fold_idx]
                                                [1]].tolist()
        test_list[site_idx] = all_list[site_idx][split_list[site_idx][fold_idx]
                                                 [1]].tolist()
        if site_idx in site:
            train_list['Overall'].append(train_list[site_idx])
            val_list['Overall'].append(val_list[site_idx])
        test_list['Overall'].append(test_list[site_idx])

    print('-----------------------------------------')
    print('Dataset Info:')
    for site_key in train_list.keys():
        if site_key in ['Overall', 'ABC_mixed']:
            case_total_train = 0
            case_total_test = 0
            for site_list_train, site_list_test in zip(train_list[site_key],
                                                       test_list[site_key]):
                case_total_train += len(site_list_train)
                case_total_test += len(site_list_test)
            print(
                f'{site_key}: {len(train_list[site_key])} sites  '
                f'Train: {case_total_train} cases, Test: {case_total_test} cases'
            )
        else:
            print(
                f'Site {site_key} Train:  {len(train_list[site_key])} cases, Test:  {len(test_list[site_key])} cases'
            )
    print('-----------------------------------------')
    n_train = iters * bs
    if len(site) > 1:
        train_set = SiteSet(train_list['Overall'],
                            iters=n_train,
                            training=True,
                            augmentation=aug,
                            source="Overall",
                            zoom_crop=zoom,
                            whitening=whitening,
                            batchsize=bs // len(site),
                            site_num=len(site),
                            n_classes=net.n_classes,
                            excluded_classes=excluded_classes)
        val_set = SiteSet(val_list['Overall'],
                          iters=n_train,
                          training=True,
                          augmentation=False,
                          source="Overall",
                          zoom_crop=False,
                          whitening=whitening,
                          batchsize=bs // len(site),
                          site_num=len(site),
                          n_classes=net.n_classes,
                          excluded_classes=excluded_classes)
    else:
        train_set = SiteSet(train_list[site],
                            iters=n_train,
                            training=True,
                            augmentation=aug,
                            source=site,
                            zoom_crop=zoom,
                            whitening=whitening,
                            batchsize=bs // len(site),
                            site_num=len(site),
                            n_classes=net.n_classes,
                            excluded_classes=excluded_classes)
        val_set = SiteSet(val_list[site],
                          iters=n_train,
                          training=True,
                          augmentation=False,
                          source=site,
                          zoom_crop=False,
                          whitening=whitening,
                          batchsize=bs // len(site),
                          site_num=len(site),
                          n_classes=net.n_classes,
                          excluded_classes=excluded_classes)

    train_loader = DataLoader(train_set,
                              batch_size=bs,
                              shuffle=False,
                              num_workers=2,
                              pin_memory=True)
    val_loader = DataLoader(val_set,
                            batch_size=bs,
                            shuffle=False,
                            num_workers=2,
                            pin_memory=True)

    global_step = 0

    logging.info(f'''Starting training:
        Output Path:     {output_dir}
        Epochs:          {epochs}
        Iterations:      {iters}
        Batch size:      {bs}
        Learning rate:   {lr}
        Checkpoints:     {save_cp}
        Only_Last_Best:  {only_lastandbest}
        Eval_Frequency:  {eval_freq}
        Device:          {device.type}
        GPU ids:         {gpus}
        Site:            {site}
        Shift+Rotation:  {aug}
        Zoom+Crop:       {zoom}
        Whitening:       {whitening}
        Pretrain:        {pretrained}
        Classes:         {net.n_classes}
        Excluded Clases: {excluded_classes}
    ''')

    optimizer = optim.Adam(net.parameters(), lr=lr)

    scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer,
                                                     'min',
                                                     factor=0.5,
                                                     patience=5)

    criterion = DiceLoss()

    best_score = 0
    csv_header = True
    for epoch in range(epochs):

        losses = []
        losses_first_forward = []
        epoch_loss = 0
        with tqdm(total=iters,
                  desc=f'Epoch {epoch + 1}/{epochs}',
                  unit='batch') as pbar:
            # for batch in train_loader:
            time.sleep(2)
            for (train_batch, val_batch) in zip(train_loader, val_loader):
                net.train()
                imgs = train_batch[0]
                all_masks = train_batch[1]
                site_label = train_batch[2]

                assert imgs.shape[1] == net.n_channels, \
                    f'Network has been defined with {net.n_channels} input channels, ' \
                    f'but loaded images have {imgs.shape[1]} channels. Please check that ' \
                    'the images are loaded correctly.'

                imgs = imgs.to(device=device, dtype=torch.float32)
                mask_type = torch.float32 if net.n_classes == 1 else torch.long
                all_masks = all_masks.to(device=device, dtype=mask_type)

                masks_pred = net(imgs)
                if spade_aux_blocks == '':
                    loss, loss_hard = criterion(masks_pred,
                                                all_masks,
                                                num_classes=net.n_classes,
                                                return_hard_dice=True,
                                                softmax=True)
                    writer.add_scalar('Backwarded Loss/Dice_Loss', loss.item(),
                                      global_step)

                    if net.n_classes > 2:
                        loss_forward_weighted_ce = Weighted_Cross_Entropy_Loss(
                        )(masks_pred,
                          all_masks,
                          num_classes=net.n_classes,
                          weighted=ce_weighted,
                          softmax=True)
                        loss += loss_forward_weighted_ce
                        writer.add_scalar('Backwarded Loss/Weighted_CE_Loss',
                                          loss_forward_weighted_ce.item(),
                                          global_step)
                    train_loss = loss_hard.item()
                else:
                    # start first forward
                    loss_first_forward, loss_first_forward_hard = criterion(
                        masks_pred,
                        all_masks,
                        num_classes=net.n_classes,
                        return_hard_dice=True,
                        softmax=True)
                    referred_mask_loss = loss_first_forward_hard.item()
                    writer.add_scalar('Backwarded Loss/Dice_Loss_First',
                                      loss_first_forward.item(), global_step)
                    if net.n_classes > 2:
                        loss_first_forward_weighted_ce = Weighted_Cross_Entropy_Loss(
                        )(masks_pred,
                          all_masks,
                          num_classes=net.n_classes,
                          weighted=ce_weighted,
                          softmax=True)
                        loss_first_forward += loss_first_forward_weighted_ce
                        writer.add_scalar(
                            'Backwarded Loss/Weighted_CE_Loss_First',
                            loss_first_forward_weighted_ce.item(), global_step)
                    optimizer.zero_grad()
                    loss_first_forward.backward()
                    optimizer.step()

                    # start second forward
                    mask_pred_first_forward = masks_pred.detach()
                    mask_pred_first_forward = torch.softmax(
                        mask_pred_first_forward, dim=1)
                    masks_pred_second_forward = net(
                        imgs, seg=mask_pred_first_forward)
                    loss, loss_hard = criterion(masks_pred_second_forward,
                                                all_masks,
                                                num_classes=net.n_classes,
                                                return_hard_dice=True,
                                                softmax=True)

                    writer.add_scalar('Backwarded Loss/Dice_Loss_Second',
                                      loss.item(), global_step)
                    if net.n_classes > 2:
                        loss_second_forward_weighted_ce = Weighted_Cross_Entropy_Loss(
                        )(masks_pred_second_forward,
                          all_masks,
                          num_classes=net.n_classes,
                          weighted=ce_weighted,
                          softmax=True)
                        loss += loss_second_forward_weighted_ce
                        writer.add_scalar(
                            'Backwarded Loss/Weighted_CE_Loss_Second',
                            loss_second_forward_weighted_ce.item(),
                            global_step)
                    train_loss = loss_hard.item()

                epoch_loss += train_loss

                optimizer.zero_grad()
                loss.backward()
                nn.utils.clip_grad_value_(net.parameters(), 0.1)
                optimizer.step()

                pbar.set_postfix(**{'Dice': train_loss})
                pbar.update(1)
                global_step += 1

                net.eval()
                imgs = val_batch[0]
                all_masks = val_batch[1]
                site_label = val_batch[2]

                imgs = imgs.to(device=device, dtype=torch.float32)
                mask_type = torch.float32 if net.n_classes == 1 else torch.long
                all_masks = all_masks.to(device=device, dtype=mask_type)

                with torch.no_grad():
                    masks_pred = net(imgs)
                    # loss = criterion(masks_pred, all_masks)
                    # val_loss = loss.item()
                    if spade_aux_blocks == '':
                        loss, loss_hard = criterion(masks_pred,
                                                    all_masks,
                                                    num_classes=net.n_classes,
                                                    return_hard_dice=True,
                                                    softmax=True)
                        val_loss = loss_hard.item()
                    else:
                        mask_pred_first_forward = masks_pred.detach()

                        _, loss_hard_first_forward = criterion(
                            mask_pred_first_forward,
                            all_masks,
                            num_classes=net.n_classes,
                            return_hard_dice=True,
                            softmax=True)
                        mask_pred_first_forward = torch.softmax(
                            mask_pred_first_forward, dim=1)
                        masks_pred_second_forward = net(
                            imgs, seg=mask_pred_first_forward)
                        loss, loss_hard = criterion(masks_pred_second_forward,
                                                    all_masks,
                                                    num_classes=net.n_classes,
                                                    return_hard_dice=True,
                                                    softmax=True)
                        val_loss = loss_hard.item()
                        val_loss_first_forward = loss_hard_first_forward.item()

                if spade_aux_blocks == '':
                    writer.add_scalars('Loss/Dice_Loss', {
                        'train': train_loss,
                        'val': val_loss
                    }, global_step)
                else:
                    writer.add_scalars(
                        'Loss/Dice_Loss', {
                            'train': train_loss,
                            'val_first': val_loss_first_forward,
                            'val_second': val_loss
                        }, global_step)
                if global_step % (n_train // (eval_freq * bs)) == 0:
                    if net.n_classes == 2:
                        writer.add_images(
                            'masks/true',
                            (all_masks[:4, ...][:4, ...].cpu().unsqueeze(1)),
                            global_step)
                        writer.add_images(
                            'masks/pred',
                            torch.softmax(masks_pred[:4, ...],
                                          dim=1)[:, 1:2, :, :].cpu(),
                            global_step)

                    elif net.n_classes > 2:
                        writer.add_images(
                            'masks/true',
                            (all_masks[:4, ...].cpu().unsqueeze(1)),
                            global_step)
                        writer.add_images(
                            'masks/pred',
                            torch.argmax(torch.softmax(masks_pred[:4, ...],
                                                       dim=1),
                                         dim=1).unsqueeze(1).cpu(),
                            global_step)
                if spade_aux_blocks != '':
                    losses_first_forward.append(loss_first_forward.item())

                losses.append(train_loss)

                if global_step % 50 == 0 and optimizer.param_groups[0][
                        'lr'] > 1e-5:
                    scheduler.step(np.mean(losses[-50:]))
                if global_step % (n_train // (eval_freq * bs)) == 0:
                    for tag, value in net.named_parameters():
                        tag = tag.replace('.', '/')
                        writer.add_histogram('weights/' + tag,
                                             value.data.cpu().numpy(),
                                             global_step)
                    if eval_site is None:
                        eval_site = site
                    test_scores, test_asds = eval_net(
                        net,
                        test_list,
                        device,
                        fold_idx,
                        global_step,
                        dir_eval_csv,
                        csv_files_prefix=csv_files_prefix,
                        whitening=whitening,
                        eval_site=eval_site,
                        spade_aux=(spade_aux_blocks != ''),
                        excluded_classes=excluded_classes,
                        dataset_name=dataset_name)
                    writer.add_scalar('learning_rate',
                                      optimizer.param_groups[0]['lr'],
                                      global_step)
                    if epoch >= 0:
                        if len(site) == 1:
                            metric_site = site
                        else:
                            metric_site = 'Overall'
                        if net.n_classes == 2:
                            is_best = test_scores[metric_site] > best_score
                            best_score = max(test_scores[metric_site],
                                             best_score)
                            if is_best:
                                try:
                                    os.makedirs(dir_checkpoint)
                                    logging.info(
                                        'Created checkpoint directory')
                                except OSError:
                                    pass
                                torch.save(net.state_dict(),
                                           dir_checkpoint + f'model_best.pth')
                                logging.info(
                                    f'Best model saved ! ( Dice Score:{best_score}) on Site {metric_site})'
                                )

                        elif net.n_classes > 2:
                            scores_all_classes = 0
                            for c in test_scores.keys():
                                scores_all_classes += test_scores[c][
                                    metric_site]
                            scores_all_classes /= len(test_scores.keys())
                            is_best = scores_all_classes > best_score
                            best_score = max(scores_all_classes, best_score)
                            if is_best:
                                try:
                                    os.makedirs(dir_checkpoint)
                                    logging.info(
                                        'Created checkpoint directory')
                                except OSError:
                                    pass

                                torch.save(net.state_dict(),
                                           dir_checkpoint + f'model_best.pth')
                                logging.info(
                                    f'Best model saved ! ( Dice Score:{best_score} on Site {metric_site})'
                                )
                    if net.n_classes == 2:
                        if len(eval_site) > 1:
                            sites_print = list(eval_site) + ['Overall']
                        else:
                            sites_print = list(eval_site)

                        test_performance_dict = {}
                        test_performance_dict['fold'] = fold_idx
                        test_performance_dict['global_step'] = global_step
                        for st in sites_print:
                            print('\nSite: {}'.format(st))
                            print('\nTest Dice Coeff: {}'.format(
                                test_scores[st]))
                            print('\nTest ASD: {}'.format(test_asds[st]))
                        for st in sites_print:
                            test_performance_dict[f'Dice_{st}'] = [
                                format(test_scores[st], '.4f')
                            ]
                        for st in sites_print:
                            test_performance_dict[f'ASD_{st}'] = [
                                format(test_asds[st], '.2f')
                            ]
                        if spade_aux_blocks != '':
                            for st in sites_print:
                                test_performance_dict[
                                    f'Dice_{st}_first_forward'] = [
                                        format(
                                            test_scores[st + '_first_forward'],
                                            '.4f')
                                    ]
                            for st in sites_print:
                                test_performance_dict[
                                    f'ASD_{st}_first_forward'] = [
                                        format(
                                            test_asds[st + '_first_forward'],
                                            '.2f')
                                    ]
                        df = pd.DataFrame.from_dict(test_performance_dict)
                        df.to_csv(dir_eval_csv + csv_files_prefix +
                                  f'site_performance.csv',
                                  mode='a',
                                  header=csv_header,
                                  index=False)
                        csv_header = False
                        print('\n' + tensorboard_logdir)
                        # write with tensorboard
                        writer.add_scalars('Test/Dice_Score', test_scores,
                                           global_step)
                        writer.add_scalars('Test/ASD', test_asds, global_step)

                    elif net.n_classes > 2:
                        if dataset_name == 'ABD-8':
                            abdominal_organ_dict = {
                                1: 'spleen',
                                2: 'r_kidney',
                                3: 'l_kidney',
                                4: 'gallbladder',
                                5: 'pancreas',
                                6: 'liver',
                                7: 'stomach',
                                8: 'aorta'
                            }
                            if excluded_classes is None:
                                organ_dict = abdominal_organ_dict
                            else:
                                print('Original Organ dict')
                                print(abdominal_organ_dict)
                                post_mapping_dict = {}
                                original_classes = list(
                                    range(net.n_classes +
                                          len(excluded_classes)))
                                remain_classes = [
                                    item for item in original_classes
                                    if item not in excluded_classes
                                ]
                                for new_value, value in enumerate(
                                        remain_classes):
                                    post_mapping_dict[value] = new_value
                                organ_dict = {}
                                for c in remain_classes:
                                    if c == 0:
                                        continue
                                    organ_dict[post_mapping_dict[
                                        c]] = abdominal_organ_dict[c]
                                print('Current Organ dict')
                                print(organ_dict)
                        elif dataset_name == 'ABD-6':
                            abdominal_organ_dict = {
                                1: 'spleen',
                                2: 'l_kidney',
                                3: 'gallbladder',
                                4: 'liver',
                                5: 'stomach',
                                6: 'pancreas'
                            }
                            if excluded_classes is None:
                                organ_dict = abdominal_organ_dict
                            else:
                                print('Original Organ dict')
                                print(abdominal_organ_dict)
                                post_mapping_dict = {}
                                original_classes = list(
                                    range(net.n_classes +
                                          len(excluded_classes)))
                                remain_classes = [
                                    item for item in original_classes
                                    if item not in excluded_classes
                                ]
                                for new_value, value in enumerate(
                                        remain_classes):
                                    post_mapping_dict[value] = new_value
                                organ_dict = {}
                                for c in remain_classes:
                                    if c == 0:
                                        continue
                                    organ_dict[post_mapping_dict[
                                        c]] = abdominal_organ_dict[c]
                                print('Current Organ dict')
                                print(organ_dict)
                        print(f'Organ Dict:{organ_dict}')
                        test_performance_dict = {}
                        test_performance_dict['fold'] = fold_idx
                        test_performance_dict['global_step'] = global_step

                        for organ_class in range(1, net.n_classes):
                            if len(eval_site) > 1:
                                sites_print = list(eval_site) + ['Overall']
                            else:
                                sites_print = list(eval_site)

                            for st in sites_print:
                                test_performance_dict[
                                    f'{organ_dict[organ_class]}_Dice_{st}'] = [
                                        format(test_scores[organ_class][st],
                                               '.4f')
                                    ]
                            for st in sites_print:
                                test_performance_dict[
                                    f'{organ_dict[organ_class]}_ASD_{st}'] = [
                                        format(test_asds[organ_class][st],
                                               '.2f')
                                    ]

                            writer.add_scalars(
                                f'Test/Dice_Score_{organ_dict[organ_class]}',
                                test_scores[organ_class], global_step)
                            writer.add_scalars(
                                f'Test/ASD_{organ_dict[organ_class]}',
                                test_asds[organ_class], global_step)

                        test_scores['AVG'] = {}
                        test_asds['AVG'] = {}
                        for st in sites_print:
                            scores_all_classes_avg = 0
                            asds_all_classes_avg = 0
                            for c in range(1, net.n_classes):
                                scores_all_classes_avg += test_scores[c][st]
                                asds_all_classes_avg += test_asds[c][st]
                            scores_all_classes_avg /= (net.n_classes - 1)
                            asds_all_classes_avg /= (net.n_classes - 1)
                            test_scores['AVG'][st] = scores_all_classes_avg
                            test_asds['AVG'][st] = asds_all_classes_avg
                            print(f'\nSite:{st}')
                            print(f'Average:')
                            print('Test Dice Coeff: {}'.format(
                                test_scores['AVG'][st]))
                            print('Test ASD: {}'.format(test_asds['AVG'][st]))
                        for st in sites_print:
                            test_performance_dict[f'Average_Dice_{st}'] = [
                                format(test_scores['AVG'][st], '.4f')
                            ]
                        for st in sites_print:
                            test_performance_dict[f'Average_ASD_{st}'] = [
                                format(test_asds['AVG'][st], '.2f')
                            ]
                        writer.add_scalars(f'Test/Dice_Score_Average',
                                           test_scores['AVG'], global_step)
                        writer.add_scalars(f'Test/ASD_Average',
                                           test_asds['AVG'], global_step)

                        if spade_aux_blocks != '':
                            for organ_class in range(1, net.n_classes):
                                for st in sites_print:
                                    test_performance_dict[
                                        f'{organ_dict[organ_class]}_Dice_{st}_first_forward'] = [
                                            format(
                                                test_scores[organ_class]
                                                [st + '_first_forward'], '.4f')
                                        ]
                                for st in sites_print:
                                    test_performance_dict[
                                        f'{organ_dict[organ_class]}_ASD_{st}_first_forward'] = [
                                            format(
                                                test_asds[organ_class]
                                                [st + '_first_forward'], '.2f')
                                        ]
                        df = pd.DataFrame.from_dict(test_performance_dict)
                        df.to_csv(dir_eval_csv + csv_files_prefix +
                                  f'site_performance.csv',
                                  mode='a',
                                  header=csv_header,
                                  index=False)
                        csv_header = False
                        print('\n' + tensorboard_logdir)

        if save_cp:
            try:
                os.makedirs(dir_checkpoint)
                logging.info('Created checkpoint directory')
            except OSError:
                pass
            if (epoch + 1) < epochs:
                torch.save(net.state_dict(),
                           dir_checkpoint + f'CP_epoch{epoch + 1}.pth')

            else:
                torch.save(net.state_dict(),
                           dir_checkpoint + f'model_last.pth')

            if only_lastandbest:
                if os.path.exists(dir_checkpoint + f'CP_epoch{epoch}.pth'):
                    os.remove(dir_checkpoint + f'CP_epoch{epoch}.pth')
            print(dir_checkpoint)
            logging.info(f'Checkpoint {epoch + 1} saved !')

    writer.close()
    print("GPU is available")
    device = torch.device("cuda")
else:
    print("GPU is not available")
    device = torch.device("cpu")

nets = [
    UNet(1, 1, final_activation=nn.Sigmoid()),
    UNet_BatchNorm(1, 1, final_activation=nn.Sigmoid()),
    UNet_ELU(1, 1, final_activation=nn.Sigmoid()),
    UNet_Five_Layers(1, 1, final_activation=nn.Sigmoid())
]

n_epochs = 15
for net in nets:
    for loss_fn in [torch.nn.MSELoss(), DiceLoss(), DiceCoefficient()]:
        name = net.__class__.__name__
        loss_name = loss_fn.__class__.__name__
        print(f"\n\nTraining network {name} with loss {loss_name}")
        logger = SummaryWriter(f'runs/log_{name}_{loss_name}')
        net.to(device)

        loss_function = loss_fn
        loss_function.to(device)

        # use adam optimizer
        optimizer = torch.optim.Adam(net.parameters(), lr=1.e-3)

        # build the dice coefficient metric
        metric = DiceCoefficient()
        # train for 25 epochs
Ejemplo n.º 10
0
def dice_loss(input, target):
    dice = DiceLoss()
    loss = dice(input, target)
    return loss
def evaluate(config, model, data_iter, test=False):
    model.eval()
    loss_total = 0
    predict_all = np.array([], dtype=int)  # 预测小税号
    gather_predict_all = np.array([], dtype=int)  # 预测大税号
    labels_all = np.array([], dtype=int)
    gather_labels_all = np.array([], dtype=int)
    focalLoss = FocalLoss(config.num_classes)
    diceloss = DiceLoss(config.num_classes)  # dice loss
    with torch.no_grad():
        for texts, labels, gather_labels in data_iter:
            outputs, gather_outputs = model(texts)
            loss = F.cross_entropy(outputs, labels)
            # loss = focalLoss(outputs, labels)  # dic loss
            # loss = diceloss(outputs, labels)  # dice loss
            loss_total += loss

            labels = labels.data.cpu().numpy()  # label
            gather_labels = gather_labels.data.cpu().numpy()  # 大分类税号

            predic = torch.max(outputs.data, 1)[1].cpu().numpy()  # predic
            gather_predic = torch.max(gather_outputs.data,
                                      1)[1].cpu().numpy()  # predic_gather

            labels_all = np.append(labels_all, labels)
            gather_labels_all = np.append(gather_labels_all, gather_labels)
            predict_all = np.append(predict_all, predic)
            gather_predict_all = np.append(gather_predict_all, gather_predic)

    haiguan_labels_all = [config.class_list[x] for x in labels_all]
    haiguan_predic_all = [config.class_list[x] for x in predict_all]
    haiguan_gather_labels_all = [
        config.gather_class_list[x] for x in gather_labels_all
    ]
    haiguan_gather_predict_labels_all = [
        config.gather_class_list[x] for x in gather_predict_all
    ]
    acc = metrics.accuracy_score(labels_all, predict_all)
    if test:
        # report = metrics.classification_report(labels_all, predict_all, target_names=config.class_list, digits=4)
        report = metrics.classification_report(labels_all,
                                               predict_all,
                                               digits=4)
        # confusion = metrics.confusion_matrix(labels_all, predict_all)
        # class_map = {}  # 大小税号映射表
        wrong_number = 0  # 小税号预测错误条数
        # '''
        # class_map_list = [x.strip().split('\t') for x in open(config.class_map_path, encoding='utf-8').readlines()]
        # for lin in class_map_list:
        #     class_map[lin[0]] = lin[1]
        list1, list2, list3, list4, index_list = [], [], [], [], []  # 装结果的5列表
        for i, (pre, lab, galab, pre_galab) in enumerate(
                zip(haiguan_predic_all, haiguan_labels_all,
                    haiguan_gather_labels_all,
                    haiguan_gather_predict_labels_all)):
            if pre_galab == galab and pre == lab:  # 全对
                list1.append((pre, lab, pre_galab, galab))
            elif pre_galab == galab and pre != lab:  # 大对小不对
                index_list.append([str(i), pre, lab, galab])
                list2.append((pre, lab, pre_galab, galab))
            elif pre_galab != galab and pre == lab:  # 大不对小对
                list3.append((pre, lab, pre_galab, galab))
            elif pre_galab != galab and pre != lab:  # 大不对小不对
                index_list.append([str(i), pre, lab, galab])
                list4.append((pre, lab, pre_galab, galab))
        print('全对有{}条'.format(len(list1)))
        print('大对小不对有{}条'.format(len(list2)))
        print('大不对小对有{}条'.format(len(list3)))
        print('大不对小不对有{}条'.format(len(list4)))
        """
        with open('./84-85-90/base_wrong.txt', 'w', encoding='utf-8')as f:
            f.write('index, prelab, lab, galab')
            f.write('\n')
            for line in index_list:
                line = '\t'.join(line)
                f.write(line)
                f.write('\n')
        print('index_finish')
        """
        wrong_list = list2 + list4  # 小税号预测错误汇总
        test_number = 0
        for line in wrong_list:
            if line[3] not in line[0]:  # 预测的小税号不在正确的大税号下
                test_number += 1
        print('预测小税号错误中,小税号不在正确大税号属性下有{}条'.format(test_number))
        print('\n')
        print('\n')
        print('\n')
        # '''
        wrong_rate1 = test_number / len(wrong_list)
        # return acc, loss_total / len(data_iter), report, confusion, wrong_list, wrong_number, wrong_rate1
        return acc, loss_total / len(
            data_iter), wrong_list, wrong_number, wrong_rate1, report
    return acc, loss_total / len(data_iter)
Ejemplo n.º 12
0
    def _test_dataset(self, dataset, same_batch_size=False, unused=False):
        # mini cubes settting

        trainer = Trainer(config=self.config, dataset=self.dataset
                          )  # instanciating trainer to load and access model
        trainer.load_model(
            from_path=True,
            path=os.path.join(self.config.model_path_save, "weights_sup.pt"),
            phase="sup",
            ensure_sup_is_completed=False,  # one or two timed out at 24h
        )
        self.dataset.reset()
        dataset.reset()

        self.model = trainer.model

        batch_size = 1 if same_batch_size is False else self.config.batch_size_sup
        print("USING BATCH SIZE {} FOR TESTING".format(batch_size))

        dataset_dict = dict()
        dataset_dict.setdefault("good_metrics", {})
        nr_target_classes_map = {
            "heart": 2,
            "brain": 4,
            "lidc_resampled": 2,
            "hippo": 3
        }
        thresholds = []
        jaccard = []

        num_target_classes = None
        for dataset_name, n_target_classes in nr_target_classes_map.items():
            if dataset_name.lower() == self.dataset_name.lower():
                num_target_classes = n_target_classes
        assert num_target_classes is not None

        # per class and global
        dice_binary = [[] for _ in range(num_target_classes + 1)]
        dice_logits = [[] for _ in range(num_target_classes + 1)]
        hausdorff = [[] for _ in range(num_target_classes + 1)]

        print("LEN CONTAINERS", len(dice_binary))

        OCCURENCE_COUNT = 0
        break_on_next = False
        with torch.no_grad():
            self.model.eval()
            count = 0
            while True:
                # print(count)
                # batch size > 1 plus random shuffle of indexes in Dataset results in no having the exact same
                # testins result each time as batches are flattened and act "as one"
                # so you would be giving the metrics different tensors to work with

                try:
                    x, y = dataset.get_test(batch_size=1, return_tensor=True)
                except AttributeError:
                    return
                if x is None:
                    break

                x, y = x.float().to(self.device), y.float().to(self.device)
                # if self.config.model.lower() in ("vnet_mg", "unet_3d", "unet_acs", "unet_acs_axis_aware_decoder", "unet_acs_with_cls"):
                #    x, pad_tuple = pad_if_necessary_one_array(x, return_pad_tuple=True)

                # pred = self.model(x)

                # pred = FullCubeSegmentator._unpad_3d_array(pred, pad_tuple)

                if "fcn_resnet18" in self.config.model.lower():
                    x = torch.cat((x, x, x), dim=1)
                    if 86 in x.shape:
                        continue
                    pred = self.model(x)

                else:
                    pred = self.model(x)  # (B,C,x,y,z)

                if "unet_acs_with_cls" in self.config.model.lower():
                    pred_, x_cls, targets_cls = pred
                    # x_cls, targets_cls = x_cls.to(self.device), targets_cls.to(self.device)
                    pred = pred_  # for segmentation

                if "fcn_resnet18" not in self.config.model.lower():
                    y = make_1_hot_mask_for_dice(y)
                    assert ((y == 0) | (y == 1)).all()
                    tmp = DiceLoss.dice_loss(pred,
                                             y,
                                             return_loss=False,
                                             per_class=True)

                    for idx, dice_score in enumerate(tmp):
                        dice_logits[idx].append(float(dice_score))

                else:
                    # match 2 channel output of network
                    y_one_hot = categorical_to_one_hot(y,
                                                       dim=1,
                                                       expand_dim=False)
                    # (B,C,x,y,z)
                    dice_logits.append(
                        float(
                            DiceLoss.dice_loss(pred,
                                               y_one_hot,
                                               return_loss=False,
                                               skip_zero_sum=True)))

                if "fcn_resnet18" in self.config.model.lower():
                    pred = self._make_pred_mask_from_pred(pred,
                                                          threshold=False)
                else:
                    # print("SHAPE PRE MAKE MASK", pred.shape)
                    # threshold = self._set_threshold(pred, y)
                    # thresholds.append(threshold)
                    pred = self._make_pred_mask_from_pred(pred)
                    # print("SHAPE POST MAKE MASK", pred.shape)

                if pred.shape != y.shape:
                    OCCURENCE_COUNT += 1
                    print(
                        "SHAPE MISMATCH TEST DATA {}".format(OCCURENCE_COUNT))
                    continue

                tmp = DiceLoss.dice_loss(pred,
                                         y,
                                         return_loss=False,
                                         per_class=True)
                for idx, dice_score in enumerate(tmp):
                    dice_binary[idx].append(float(dice_score))

                h_dist = self.get_hausdorff_distance(pred, y)
                for idx, hd in enumerate(h_dist):
                    hausdorff[idx].append(hd)

                if pred.shape[1] == 1:
                    # pred is binary here
                    x_flat = pred[:, 0].contiguous().view(-1)
                    y_flat = y[:, 0].contiguous().view(-1)
                    x_flat = x_flat.cpu()
                    y_flat = y_flat.cpu()
                    jaccard.append(jaccard_score(y_flat, x_flat))

                else:
                    # multi channel jaccard scenario
                    temp_jac = 0
                    for channel_idx in range(x.shape[1]):
                        x_flat = pred[:, channel_idx].contiguous().view(-1)
                        y_flat = y[:, channel_idx].contiguous().view(-1)
                        x_flat = x_flat.cpu()
                        y_flat = y_flat.cpu()
                        temp_jac += jaccard_score(y_flat, x_flat)
                    jaccard.append(temp_jac / x.shape[1])
            count += 1
            dataset.reset()

        zero_len = False
        for i in dice_binary:
            if len(i) == 0:
                zero_len = True
        if zero_len is True:
            avg_jaccard = 0
            avg_hausdorff = 0  # sum(hausdorff) / len(hausdorff)
            avg_dice_binary = 0  # sum(dice_binary) / len(dice_binary)
        else:
            avg_jaccard = sum(jaccard) / len(jaccard)
            avg_hausdorff = self.average_metric(
                hausdorff)  # sum(hausdorff) / len(hausdorff)
            avg_dice_binary = self.average_metric(
                dice_binary)  # sum(dice_binary) / len(dice_binary)

        avg_dice_soft = self.average_metric(
            dice_logits)  # sum(dice_logits) / len(dice_l#ogits)

        print("HAUSDORFF INF: {} / {}".format(len(hausdorff[0]),
                                              len(dice_logits[0])))

        dataset_dict["good_metrics"]["jaccard_test"] = avg_jaccard
        dataset_dict["good_metrics"]["hausdorff_test"] = avg_hausdorff
        dataset_dict["good_metrics"]["dice_test_soft"] = avg_dice_soft
        dataset_dict["good_metrics"]["dice_test_binary"] = avg_dice_binary

        #############################

        jaccard = []
        # if hasattr(self.dataset, "nr_target_classes") and isinstance(self.dataset.nr_target_classes, int):
        dice_binary = [[] for _ in range(num_target_classes + 1)]
        dice_logits = [[] for _ in range(num_target_classes + 1)]
        hausdorff = [[] for _ in range(num_target_classes + 1)]
        # else:
        #    dice_binary = [[]]
        #    dice_logits = [[]]
        #    hausdorff = [[]]

        # OCCURENCE_COUNT = 0
        # with torch.no_grad():
        #    self.model.eval()
        #    while True:
        ##        x, y = dataset.get_train(batch_size=1, return_tensor=True)
        ##        if x is None:
        ##            break
        ##        x, y = x.float().to(self.device), y.float().to(self.device)
        ##        # if self.config.model.lower() in ("vnet_mg", "unet_3d", "unet_acs", "unet_acs_axis_aware_decoder", "unet_acs_with_cls"):
        ##        #    x, pad_tuple = pad_if_necessary_one_array(x, return_pad_tuple=True)
        ##        #    pred = self.model(x)
        ##        #    pred = FullCubeSegmentator._unpad_3d_array(pred, pad_tuple)#

        ##                if "fcn_resnet18" in self.config.model.lower():
        ##            x = torch.cat((x, x, x), dim=1)
        ##            if 86 in x.shape:
        ##                continue
        ##            pred = self.model(x)
        ##        else:
        ##            pred = self.model(x)

        #        if "fcn_resnet18" not in self.config.model.lower():
        #            y = make_1_hot_mask_for_dice(y)
        #            assert ((y == 0) | (y == 1)).all()
        #            # dice_logits.append(float(DiceLoss.dice_loss(pred, y, return_loss=False, per_class=True)))
        #            tmp = DiceLoss.dice_loss(pred, y, return_loss=False, per_class=True)
        #            for idx, dice_score in enumerate(tmp):
        #                dice_logits[idx].append(float(dice_score))#
        #        else:
        #            # match 2 channel output of network
        #            y_one_hot = categorical_to_one_hot(y, dim=1, expand_dim=False)
        #            dice_logits.append(float(DiceLoss.dice_loss(pred, y_one_hot, return_loss=False, skip_zero_sum=True)))

        #        if "fcn_resnet18" in self.config.model.lower():
        #            pred = self._make_pred_mask_from_pred(pred, threshold=False)
        #        else:
        #            # threshold = self._set_threshold(pred, y)
        #            # thresholds.append(threshold)
        #            pred = self._make_pred_mask_from_pred(pred)

        #        if pred.shape != y.shape:
        #            OCCURENCE_COUNT += 1
        #            print("SHAPE MISMATCH TRAIN DATA {}".format(OCCURENCE_COUNT))
        #            continue

        #        tmp = DiceLoss.dice_loss(pred, y, return_loss=False, per_class=True)
        #        for idx, dice_score in enumerate(tmp):
        #            dice_binary[idx].append(float(dice_score))
        #        h_dist = self.get_hausdorff_distance(pred, y)

        #        for idx, hd in enumerate(h_dist):
        #            hausdorff[idx].append(hd)

        #        if pred.shape[1] == 1:
        #            x_flat = pred[:, 0].contiguous().view(-1)
        #            y_flat = y[:, 0].contiguous().view(-1)
        #            x_flat = x_flat.cpu()
        #            y_flat = y_flat.cpu()
        #            jaccard.append(jaccard_score(y_flat, x_flat))

        #        else:
        #            # multi channel jaccard scenario
        #            temp_jac = 0
        #            for channel_idx in range(x.shape[1]):
        #                x_flat = pred[:, channel_idx].contiguous().view(-1)
        #                y_flat = y[:, channel_idx].contiguous().view(-1)
        #                x_flat = x_flat.cpu()
        #                y_flat = y_flat.cpu()
        #                temp_jac += jaccard_score(y_flat, x_flat)
        #            jaccard.append(temp_jac / x.shape[1])

        #    dataset.reset()

        # avg_jaccard = sum(jaccard) / len(jaccard)
        # avg_hausdorff = self.average_metric(hausdorff)  # sum(hausdorff) / len(hausdorff)
        # avg_dice_soft = self.average_metric(dice_logits)  # sum(dice_logits) / len(dice_l#ogits)
        # avg_dice_binary = self.average_metric(dice_binary)  # sum(dice_binary) / len(dice_binary) """

        # print("HAUSDORFF INF: {} / {}".format(len(hausdorff[0]), len(dice_logits[0])))

        dataset_dict["good_metrics"]["jaccard_train"] = avg_jaccard
        dataset_dict["good_metrics"]["hausdorff_train"] = avg_hausdorff
        dataset_dict["good_metrics"]["dice_train_soft"] = avg_dice_soft
        dataset_dict["good_metrics"]["dice_train_binary"] = avg_dice_binary
        dataset.reset()
        with open(os.path.join(self.test_results_dir, "thresholds.json"),
                  "w") as f:
            json.dump(thresholds, f)

        if unused is False:
            self.metric_dict[self.dataset_name] = dataset_dict
        else:
            raise ValueError
            self.metric_dict_unused[self.dataset_name] = dataset_dict
    def save_segmentation_examples(self, nr_cubes=3, inference_full_image=True):

        # deal with recursion when defaulting to patchign

        if "lidc" in self.dataset_name:
            return

        torch.cuda.ipc_collect()
        torch.cuda.empty_cache()
        dump_tensors()

        if hasattr(self.trainer, "model"):
            del self.trainer.model
            del self.trainer
            sleep(15)
            self.trainer = Trainer(config=self.config, dataset=None)
            dump_tensors()
            torch.cuda.ipc_collect()
            torch.cuda.empty_cache()
            dump_tensors()
            sleep(5)
        if inference_full_image is False:
            print("PATCHING Will be Done")

        dump_tensors()
        torch.cuda.ipc_collect()
        torch.cuda.empty_cache()
        dump_tensors()

        self.trainer.load_model(from_path=True, path=self.model_path, phase="sup", ensure_sup_is_completed=True)

        cubes_to_use = []
        cubes_to_use.extend(self.sample_k_full_cubes_which_were_used_for_testing(nr_cubes))
        cubes_to_use.extend(self.sample_k_full_cubes_which_were_used_for_training(nr_cubes))

        cubes_to_use_path = [os.path.join(self.dataset_dir, i) for i in cubes_to_use]
        label_cubes_of_cubes_to_use_path = [os.path.join(self.dataset_labels_dir, i) for i in cubes_to_use]

        for cube_idx, cube_path in enumerate(cubes_to_use_path):
            np_array = self._load_cube_to_np_array(cube_path)  # (x,y,z)
            self.original_cube_dimensions = np_array.shape
            if sum([i for i in np_array.shape]) > 550 and self.two_dim is False:
                inference_full_image = False

            if self.dataset_name.lower() in ("task04_sup", "task01_sup", "cellari_heart_sup_10_192", "cellari_heart_sup"):
                if self.tried is False:
                    inference_full_image = True
                else:
                    inference_full_image = False

            if inference_full_image is False:
                print("CUBE TOO BIG, PATCHING")
                patcher = Patcher(np_array, two_dim=self.two_dim)

                with torch.no_grad():
                    self.trainer.model.eval()
                    for idx, patch in patcher:

                        patch = torch.unsqueeze(patch, 0)  # (1,C,H,W or 1) -> (1,1,C,H,W or 1)
                        if self.config.model.lower() in (
                            "vnet_mg",
                            "unet_3d",
                            "unet_acs",
                            "unet_acs_axis_aware_decoder",
                            "unet_acs_with_cls",
                        ):
                            patch, pad_tuple = pad_if_necessary_one_array(patch, return_pad_tuple=True)

                        pred = self.trainer.model(patch)
                        assert pred.shape == patch.shape, "{} vs {}".format(pred.shape, patch.shape)
                        # need to then unpad to reconstruct
                        if self.two_dim is True:
                            raise RuntimeError("SHOULD  NOT BE USED HERE")

                        pred = self._unpad_3d_array(pred, pad_tuple)
                        pred = torch.squeeze(pred, dim=0)  # (1, 1, C,H,W) -> (1,C,H,W)
                        pred_mask = pred  # self._make_pred_mask_from_pred(pred)
                        del pred

                        patcher.predicitons_to_reconstruct_from[
                            :, idx
                        ] = pred_mask  # update array in patcher that will construct full cube predicted mask

                        dump_tensors()
                        torch.cuda.ipc_collect()
                        torch.cuda.empty_cache()
                        dump_tensors()

                pred_mask_full_cube = patcher.get_pred_mask_full_cube()
                # segmentations.append(patcher.get_pred_mask_full_cube())
            else:

                full_cube_tensor = torch.Tensor(np_array)
                full_cube_tensor = torch.unsqueeze(full_cube_tensor, 0)  # (C,H,W) -> (1,C,H,W)
                full_cube_tensor = torch.unsqueeze(full_cube_tensor, 0)  # (1,C,H,W) -> (1,1,C,H,W)

                with torch.no_grad():
                    self.trainer.model.eval()
                    if self.two_dim is False:
                        if self.config.model.lower() in (
                            "vnet_mg",
                            "unet_3d",
                            "unet_acs",
                            "unet_acs_axis_aware_decoder",
                            "unet_acs_with_cls",
                        ):
                            full_cube_tensor, pad_tuple = pad_if_necessary_one_array(full_cube_tensor, return_pad_tuple=True)
                            try:
                                p = self.trainer.model(full_cube_tensor)
                                p.to("cpu")
                                pred = p
                                del p
                                dump_tensors()
                                torch.cuda.ipc_collect()
                                torch.cuda.empty_cache()
                                dump_tensors()
                                torch.cuda.empty_cache()
                                pred = self._unpad_3d_array(pred, pad_tuple)
                                pred = torch.squeeze(pred, dim=0)  # (1, 1, C,H,W) -> (1,C,H,W)
                                pred = torch.squeeze(pred, dim=0)
                                pred_mask_full_cube = pred  # self._make_pred_mask_from_pred(pred)
                                torch.cuda.ipc_collect()
                                torch.cuda.empty_cache()
                                del pred

                            except RuntimeError as e:
                                if "out of memory" in str(e) or "cuDNN error: CUDNN_STATUS_NOT_SUPPORTED" in str(e):
                                    print("TOO BIG FOR MEMORY, DEFAULTING TO PATCHING")
                                    # exit(0)
                                    dump_tensors()
                                    torch.cuda.ipc_collect()
                                    torch.cuda.empty_cache()
                                    dump_tensors()
                                    self.tried = True
                                    self.save_segmentation_examples(inference_full_image=False)
                                    return

                            # segmentations.append(pred_mask_full_cube)
                    else:
                        pred_mask_full_cube = torch.zeros(self.original_cube_dimensions)
                        for z_idx in range(full_cube_tensor.size()[-1]):
                            tensor_slice = full_cube_tensor[..., z_idx]  # SLICE : (1,1,C,H,W) -> (1,1,C,H)
                            assert tensor_slice.shape == (1, 1, self.original_cube_dimensions[0], self.original_cube_dimensions[1])
                            pred = self.trainer.model(tensor_slice)
                            pred = torch.squeeze(pred, dim=0)  # (1, 1, C,H) -> (1,C,H)
                            pred = torch.squeeze(pred, dim=0)  # (1,C,H) -> (C,H)
                            pred_mask_slice = pred  # self._make_pred_mask_from_pred(pred)
                            pred_mask_full_cube[..., z_idx] = pred_mask_slice

                        # segmentations.append(pred_mask_full_cube)

            # for idx, pred_mask_full_cube in enumerate(segmentations):

            print(cube_idx)

            if cube_idx < nr_cubes:
                if inference_full_image is True:
                    save_dir = os.path.join(self.save_dir, self.dataset_name, "testing_examples_full/", cubes_to_use[cube_idx][:-4])
                else:
                    save_dir = os.path.join(
                        self.save_dir, self.dataset_name, "testing_examples_full/", cubes_to_use[cube_idx][:-4] + "_with_patcher"
                    )
            else:
                if inference_full_image is True:
                    save_dir = os.path.join(self.save_dir, self.dataset_name, "training_examples_full/", cubes_to_use[cube_idx][:-4])
                else:
                    save_dir = os.path.join(
                        self.save_dir, self.dataset_name, "training_examples_full/", cubes_to_use[cube_idx][:-4] + "_with_patcher"
                    )

            make_dir(save_dir)

            # save nii of segmentation
            pred_mask_full_cube = pred_mask_full_cube.cpu()  # logits mask
            pred_mask_full_cube_binary = self._make_pred_mask_from_pred(pred_mask_full_cube)  # binary mask

            nifty_img = nibabel.Nifti1Image(np.array(pred_mask_full_cube).astype(np.float32), np.eye(4))
            nibabel.save(nifty_img, os.path.join(save_dir, cubes_to_use[cube_idx][:-4] + "_logits_mask.nii.gz"))

            nifty_img = nibabel.Nifti1Image(np.array(pred_mask_full_cube_binary).astype(np.float32), np.eye(4))
            nibabel.save(nifty_img, os.path.join(save_dir, cubes_to_use[cube_idx][:-4] + "_binary_mask.nii.gz"))

            # save .nii.gz of cube if is npy original full cube file
            if ".npy" in cube_path:
                nifty_img = nibabel.Nifti1Image(np_array.astype(np.float32), np.eye(4))
                nibabel.save(nifty_img, os.path.join(save_dir, cubes_to_use[cube_idx][:-4] + "_cube.nii.gz"))

            # self.save_3d_plot(np.array(pred_mask_full_cube), os.path.join(save_dir, "{}_plt3d.png".format(cubes_to_use[idx])))

            label_tensor_of_cube = torch.Tensor(self._load_cube_to_np_array(label_cubes_of_cubes_to_use_path[cube_idx]))
            label_tensor_of_cube = self.adjust_label_cube_acording_to_dataset(label_tensor_of_cube)
            label_tensor_of_cube_masked = np.array(label_tensor_of_cube)
            label_tensor_of_cube_masked = np.ma.masked_where(
                label_tensor_of_cube_masked < 0.5, label_tensor_of_cube_masked
            )  # it's binary anyway

            pred_mask_full_cube_binary_masked = np.array(pred_mask_full_cube_binary)
            pred_mask_full_cube_binary_masked = np.ma.masked_where(
                pred_mask_full_cube_binary_masked < 0.5, pred_mask_full_cube_binary_masked
            )  # it's binary anyway

            pred_mask_full_cube_logits_masked = np.array(pred_mask_full_cube)
            pred_mask_full_cube_logits_masked = np.ma.masked_where(
                pred_mask_full_cube_logits_masked < 0.3, pred_mask_full_cube_logits_masked
            )  # it's binary anyway

            make_dir(os.path.join(save_dir, "slices/"))

            for z_idx in range(pred_mask_full_cube.shape[-1]):

                # binary
                fig = plt.figure(figsize=(10, 5))
                plt.imshow(np_array[:, :, z_idx], cmap=cm.Greys_r)
                plt.imshow(pred_mask_full_cube_binary_masked[:, :, z_idx], cmap="Accent")
                plt.axis("off")
                fig.savefig(
                    os.path.join(save_dir, "slices/", "slice_{}_binary.jpg".format(z_idx + 1)),
                    bbox_inches="tight",
                    dpi=150,
                )
                plt.close(fig=fig)

                # logits
                fig = plt.figure(figsize=(10, 5))
                plt.imshow(np_array[:, :, z_idx], cmap=cm.Greys_r)
                plt.imshow(pred_mask_full_cube_logits_masked[:, :, z_idx], cmap="Blues", alpha=0.5)
                plt.axis("off")
                fig.savefig(
                    os.path.join(save_dir, "slices/", "slice_{}_logits.jpg".format(z_idx + 1)),
                    bbox_inches="tight",
                    dpi=150,
                )
                plt.close(fig=fig)

                # dist of logits histogram
                distribution_logits = np.array(pred_mask_full_cube[:, :, z_idx].contiguous().view(-1))
                fig = plt.figure(figsize=(10, 5))
                plt.hist(distribution_logits, bins=np.arange(min(distribution_logits), max(distribution_logits) + 0.05, 0.05))
                fig.savefig(
                    os.path.join(save_dir, "slices/", "slice_{}_logits_histogram.jpg".format(z_idx + 1)),
                    bbox_inches="tight",
                    dpi=150,
                )
                plt.close(fig=fig)

                # save ground truth as wel, overlayed on original
                fig = plt.figure(figsize=(10, 5))
                plt.imshow(np_array[:, :, z_idx], cmap=cm.Greys_r)
                plt.imshow(label_tensor_of_cube_masked[:, :, z_idx], cmap="jet")
                plt.axis("off")
                fig.savefig(
                    os.path.join(save_dir, "slices/", "slice_{}_gt.jpg".format(z_idx + 1)),
                    bbox_inches="tight",
                    dpi=150,
                )
                plt.close(fig=fig)

            dice_score_soft = float(DiceLoss.dice_loss(pred_mask_full_cube, label_tensor_of_cube, return_loss=False))
            dice_score_binary = float(DiceLoss.dice_loss(pred_mask_full_cube_binary, label_tensor_of_cube, return_loss=False))
            x_flat = pred_mask_full_cube_binary.contiguous().view(-1)
            y_flat = pred_mask_full_cube_binary.contiguous().view(-1)
            x_flat = x_flat.cpu()
            y_flat = y_flat.cpu()
            jaccard_scr = jaccard_score(y_flat, x_flat)
            metrics = {"dice_logits": dice_score_soft, "dice_binary": dice_score_binary, "jaccard": jaccard_scr}
            # print(dice)
            with open(os.path.join(save_dir, "dice.json"), "w") as f:
                json.dump(metrics, f)

            dump_tensors()
            torch.cuda.ipc_collect()
            torch.cuda.empty_cache()
            dump_tensors()
            dump_tensors()
            torch.cuda.ipc_collect()
            torch.cuda.empty_cache()
            dump_tensors()
            sleep(10)
    def compute_metrics_for_all_cubes(self, inference_full_image=True):

        cubes_to_use = []

        dump_tensors()
        torch.cuda.ipc_collect()
        torch.cuda.empty_cache()
        torch.cuda.ipc_collect()
        torch.cuda.empty_cache()
        dump_tensors()
        torch.cuda.empty_cache()

        if "lidc" in self.dataset_name:
            return

        if hasattr(self.trainer, "model"):
            del self.trainer.model
            del self.trainer
            sleep(20)
            self.trainer = Trainer(config=self.config, dataset=None)
            dump_tensors()
            torch.cuda.ipc_collect()
            torch.cuda.empty_cache()
            dump_tensors()

        dump_tensors()
        torch.cuda.ipc_collect()
        torch.cuda.empty_cache()
        dump_tensors()

        self.trainer.load_model(from_path=True, path=self.model_path, phase="sup", ensure_sup_is_completed=True)

        if inference_full_image is False:
            print("PATCHING Will be Done")

        full_cubes_used_for_testing = self.get_all_cubes_which_were_used_for_testing()
        full_cubes_used_for_training = self.get_all_cubes_which_were_used_for_training()
        cubes_to_use.extend(full_cubes_used_for_testing)
        cubes_to_use.extend(full_cubes_used_for_training)

        cubes_to_use_path = [os.path.join(self.dataset_dir, i) for i in cubes_to_use]
        label_cubes_of_cubes_to_use_path = [os.path.join(self.dataset_labels_dir, i) for i in cubes_to_use]

        metric_dict = dict()

        (
            dice_logits_test,
            dice_logits_train,
            dice_binary_test,
            dice_binary_train,
            jaccard_test,
            jaccard_train,
            hausdorff_test,
            hausdorff_train,
        ) = ([], [], [], [], [], [], [], [])

        for idx, cube_path in enumerate(cubes_to_use_path):
            np_array = self._load_cube_to_np_array(cube_path)  # (x,y,z)
            self.original_cube_dimensions = np_array.shape
            if sum([i for i in np_array.shape]) > 550 and self.two_dim is False:
                inference_full_image = False

            if self.dataset_name.lower() in ("task04_sup", "task01_sup", "cellari_heart_sup_10_192", "cellari_heart_sup"):
                if self.tried is False:
                    inference_full_image = True
                else:
                    inference_full_image = False

            if inference_full_image is False:
                print("CUBE TOO BIG, PATCHING")

                patcher = Patcher(np_array, two_dim=self.two_dim)

                with torch.no_grad():
                    self.trainer.model.eval()
                    for patch_idx, patch in patcher:

                        patch = torch.unsqueeze(patch, 0)  # (1,C,H,W or 1) -> (1,1,C,H,W or 1)
                        if self.config.model.lower() in (
                            "vnet_mg",
                            "unet_3d",
                            "unet_acs",
                            "unet_acs_axis_aware_decoder",
                            "unet_acs_with_cls",
                        ):
                            patch, pad_tuple = pad_if_necessary_one_array(patch, return_pad_tuple=True)

                        pred = self.trainer.model(patch)
                        assert pred.shape == patch.shape, "{} vs {}".format(pred.shape, patch.shape)
                        # need to then unpad to reconstruct
                        if self.two_dim is True:
                            raise RuntimeError("SHOULD  NOT BE USED HERE")

                        pred = self._unpad_3d_array(pred, pad_tuple)
                        pred = torch.squeeze(pred, dim=0)  # (1, 1, C,H,W) -> (1,C,H,W)
                        # pred_mask = self._make_pred_mask_from_pred(pred)
                        patcher.predicitons_to_reconstruct_from[
                            :, patch_idx
                        ] = pred  # update array in patcher that will construct full cube predicted mask
                        del pred
                        dump_tensors()
                        torch.cuda.ipc_collect()
                        torch.cuda.empty_cache()
                        dump_tensors()

                pred_mask_full_cube = patcher.get_pred_mask_full_cube()

            else:

                full_cube_tensor = torch.Tensor(np_array)
                full_cube_tensor = torch.unsqueeze(full_cube_tensor, 0)  # (C,H,W) -> (1,C,H,W)
                full_cube_tensor = torch.unsqueeze(full_cube_tensor, 0)  # (1,C,H,W) -> (1,1,C,H,W)

                with torch.no_grad():
                    self.trainer.model.eval()
                    if self.two_dim is False:
                        if self.config.model.lower() in (
                            "vnet_mg",
                            "unet_3d",
                            "unet_acs",
                            "unet_acs_axis_aware_decoder",
                            "unet_acs_with_cls",
                        ):
                            full_cube_tensor, pad_tuple = pad_if_necessary_one_array(full_cube_tensor, return_pad_tuple=True)
                            try:
                                p = self.trainer.model(full_cube_tensor)
                                p.to("cpu")
                                pred = p
                                del p
                                dump_tensors()
                                torch.cuda.ipc_collect()
                                torch.cuda.empty_cache()
                                dump_tensors()
                                torch.cuda.empty_cache()
                                pred = self._unpad_3d_array(pred, pad_tuple)
                                pred = torch.squeeze(pred, dim=0)  # (1, 1, C,H,W) -> (1,C,H,W)
                                pred = torch.squeeze(pred, dim=0)
                                pred_mask_full_cube = pred  # self._make_pred_mask_from_pred(pred)
                                torch.cuda.ipc_collect()
                                torch.cuda.empty_cache()
                                del pred

                            except RuntimeError as e:
                                if "out of memory" in str(e) or "cuDNN error: CUDNN_STATUS_NOT_SUPPORTED" in str(e):
                                    print("TOO BIG FOR MEMORY, DEFAULTING TO PATCHING")
                                    # exit(0)
                                    dump_tensors()
                                    torch.cuda.ipc_collect()
                                    torch.cuda.empty_cache()
                                    dump_tensors()
                                    self.tried = True
                                    res = self.compute_metrics_for_all_cubes(inference_full_image=False)
                                    return res

                    else:
                        pred_mask_full_cube = torch.zeros(self.original_cube_dimensions)
                        for z_idx in range(full_cube_tensor.size()[-1]):
                            tensor_slice = full_cube_tensor[..., z_idx]  # SLICE : (1,1,C,H,W) -> (1,1,C,H)
                            assert tensor_slice.shape == (1, 1, self.original_cube_dimensions[0], self.original_cube_dimensions[1])
                            pred = self.trainer.model(tensor_slice)
                            pred = torch.squeeze(pred, dim=0)  # (1, 1, C,H) -> (1,C,H)
                            pred = torch.squeeze(pred, dim=0)  # (1,C,H) -> (C,H)
                            pred_mask_slice = pred  # self._make_pred_mask_from_pred(pred)
                            pred_mask_full_cube[..., z_idx] = pred_mask_slice

            full_cube_label_tensor = torch.Tensor(self._load_cube_to_np_array(label_cubes_of_cubes_to_use_path[idx]))
            full_cube_label_tensor = self.adjust_label_cube_acording_to_dataset(full_cube_label_tensor)

            pred_mask_full_cube = pred_mask_full_cube.to("cpu")
            threshold = self._set_threshold(pred_mask_full_cube, full_cube_label_tensor)
            pred_mask_full_cube_binary = self._make_pred_mask_from_pred(pred_mask_full_cube, threshold=threshold)

            dice_score_soft = float(DiceLoss.dice_loss(pred_mask_full_cube, full_cube_label_tensor, return_loss=False))
            dice_score_binary = float(DiceLoss.dice_loss(pred_mask_full_cube_binary, full_cube_label_tensor, return_loss=False))
            hausdorff = hausdorff_distance(np.array(pred_mask_full_cube_binary), np.array(full_cube_label_tensor))
            x_flat = pred_mask_full_cube_binary.contiguous().view(-1)
            y_flat = full_cube_label_tensor.contiguous().view(-1)
            x_flat = x_flat.cpu()
            y_flat = y_flat.cpu()
            jac_score = jaccard_score(y_flat, x_flat)

            if idx < len(full_cubes_used_for_testing):
                dice_logits_test.append(dice_score_soft)
                dice_binary_test.append(dice_score_binary)
                jaccard_test.append(jac_score)
                hausdorff_test.append(hausdorff)
            else:
                dice_logits_train.append(dice_score_soft)
                dice_binary_train.append(dice_score_binary)
                jaccard_train.append(jac_score)
                hausdorff_train.append(hausdorff)

            dump_tensors()
            torch.cuda.ipc_collect()
            torch.cuda.empty_cache()
            dump_tensors()
            sleep(10)
            print(idx)

        avg_jaccard_test = sum(jaccard_test) / len(jaccard_test)
        avg_jaccard_train = sum(jaccard_train) / len(jaccard_train)

        avg_dice_test_soft = sum(dice_logits_test) / len(dice_logits_test)
        avg_dice_test_binary = sum(dice_binary_test) / len(dice_binary_test)

        avg_dice_train_soft = sum(dice_logits_train) / len(dice_logits_train)
        avg_dice_train_binary = sum(dice_binary_train) / len(dice_binary_train)

        avg_hausdorff_train = sum(hausdorff_train) / len(hausdorff_train)
        avg_hausdorff_test = sum(hausdorff_test) / len(hausdorff_test)

        metric_dict["dice_test_soft"] = avg_dice_test_soft
        metric_dict["dice_test_binary"] = avg_dice_test_binary
        metric_dict["dice_train_soft"] = avg_dice_train_soft
        metric_dict["dice_train_binary"] = avg_dice_train_binary
        metric_dict["jaccard_test"] = avg_jaccard_test
        metric_dict["jaccard_train"] = avg_jaccard_train
        metric_dict["hausdorff_test"] = avg_hausdorff_test
        metric_dict["hausdorff_train"] = avg_hausdorff_train

        return metric_dict
Ejemplo n.º 15
0
    # Model
    if lossf == 'contour':
        model = CleanU_Net(in_channels=1, out_channels=1)
        wo_mask = False
    else:
        model = CleanU_Net(in_channels=1, out_channels=2)
        wo_mask = False
    if torch.cuda.is_available():
        model = torch.nn.DataParallel(
            model, device_ids=list(range(torch.cuda.device_count()))).cuda()

    # Loss function
    if lossf == 'crossentropy':
        criterion = nn.CrossEntropyLoss()
    elif lossf == 'dice':
        criterion = DiceLoss()
    elif lossf == 'contour':
        criterion = ContourLoss()
    else:
        raise ValueError('Undefined loss type')

    # Optimizerd
    if torch.cuda.is_available():
        if opt == 'rmsprop':
            optimizer = torch.optim.RMSprop(model.module.parameters(), lr=lr)
        if opt == 'adam':
            optimizer = torch.optim.Adam(model.module.parameters(), lr=lr)
    else:
        if opt == 'rmsprop':
            optimizer = torch.optim.RMSprop(model.parameters(), lr=lr)
        if opt == 'adam':