Exemple #1
0
def test_item_to_mat_conversion():
    """ Test conversion mat > item > mat
    NOT testing item > mat > item, because comparing items more tedious (first need association!),
    """
    # get "original" mat
    params = {'model': {'factor_downsample': 4,
                        'input_height': 512,
                        'input_width': 1536,
                        },
              }
    dataset = data_loader.DataSet(path_csv='../data/train.csv',
                                  path_folder_images='../data/train_images',
                                  path_folder_masks='../data/train_masks',
                                  )
    list_ids = dataset.list_ids
    item_org = dataset.load_item(list_ids[0], flag_load_mask=False)
    dataset_torch = data_loader_torch.DataSetTorch(dataset, params)
    mat_org = dataset_torch.convert_item_to_mat(item_org)

    # convert back
    item = dataset_torch.convert_mat_to_item(mat_org)
    item.img = item_org.img  # need this for back conversion!
    mat = dataset_torch.convert_item_to_mat(item)

    assert np.allclose(mat, mat_org)
def evaluate(
    model,
    device,
    params,
):
    # define dataset
    dataset = data_loader.DataSet(
        path_csv=params['datasets']['valid']['path_csv'],
        path_folder_images=params['datasets']['valid']['path_folder_images'],
        path_folder_masks=params['datasets']['valid']['path_folder_masks'],
    )
    dataset_torch = data_loader_torch.DataSetTorch(dataset,
                                                   params,
                                                   flag_augment=False)
    dataset_loader = torch.utils.data.DataLoader(
        dataset=dataset_torch,
        batch_size=params['train']['batch_size_eval'],
        shuffle=False,
        num_workers=0,
    )

    # set model to eval (affects e.g. dropout layers) and disable unnecessary grad computation
    model.eval()
    torch.set_grad_enabled(False)
    torch.cuda.empty_cache()  # empty cuda cache to prevent memory errors
    gc.collect(
    )  # empty unreferenced objects at the end. Not sure whether better at the end?

    # calculate loss for whole dataset
    num_batches = len(dataset_loader)
    loss_per_name = dict()
    print("Evaluating")
    for img_batch, mask_batch, heatmap_batch, regr_batch in tqdm(
            dataset_loader):
        # concat img and mask and perform inference
        input = torch.cat([img_batch, mask_batch],
                          1)  # nbatch, nchannels, height, width
        output = model(input.to(device))

        # calculate loss
        batch_loss_per_name = calc_loss(
            output,
            heatmap_batch.to(device),
            regr_batch.to(device),
            params['train']['loss'],
        )
        for name, batch_loss in batch_loss_per_name.items():
            if name not in loss_per_name:
                loss_per_name[name] = 0
            loss_per_name[name] += batch_loss.data

    # calculate average
    for name, loss in loss_per_name.items():
        loss_per_name[name] = loss.cpu().numpy() / len(dataset_loader)
    len_dataset = len(dataset_loader.dataset)  # check difference
    len_dataset2 = len(dataset_loader)
    return loss_per_name
Exemple #3
0
    def calc_distance(xyz):
        # calculate fitting error
        x, y, z = xyz
        y_pred = 1.0392211185855782 + 0.05107277 * x + 0.16864302 * z  # from notebook
        dist_fit = (y_pred - y) ** 2

        # calculate u,v for reduced image
        IMG_SHAPE = (2710, 3384, 3)  # img.shape = h,w,c
        cam_K = np.array([[2304.5479, 0, 1686.2379],
                          [0, 2305.8757, 1354.9849],
                          [0, 0, 1]], dtype=np.float32)
        xyz = np.array([x, y, z])
        uv = data_loader.xyz2uv(xyz, cam_K)
        dataset_torch = data_loader_torch.DataSetTorch(None, params)
        uv_new = dataset_torch.convert_uv_to_uv_preprocessed(uv, IMG_SHAPE)
        u_new, v_new = uv_new[0], uv_new[1]
        dist_uv = (v_new - v_pred) ** 2 + (u_new - u_pred) ** 2

        # total
        dist_tot = max(0.2, dist_uv) + max(0.4, dist_fit)
        # dist_tot = dist_uv + dist_fit
        return dist_tot
Exemple #4
0
def predict(model,
            device,
            params,
            ):
    # Create data generators - they will produce batches
    dataset_test = data_loader.DataSet(
        path_csv=params['datasets']['test']['path_csv'],
        path_folder_images=params['datasets']['test']['path_folder_images'],
        path_folder_masks=params['datasets']['test']['path_folder_masks'],
    )
    dataset_torch_test = data_loader_torch.DataSetTorch(
        dataset_test, params,
        flag_load_label=False,
        flag_augment=False,
    )
    data_loader_test = torch.utils.data.DataLoader(
        dataset=dataset_torch_test,
        batch_size=params['predict']['batch_size'],
        shuffle=False,
        num_workers=4,
        pin_memory=True,  # see https://pytorch.org/docs/stable/data.html
    )

    # perform predictions
    predictions = []
    model.eval()
    idx_batch = -1
    for img, mask, _, _ in tqdm(data_loader_test):
        idx_batch += 1
        if idx_batch > params['predict']['num_batches_max']:
            print("Ending early because of param num_batches_max={}".format(params['predict']['num_batches_max']))
            break

        # perform prediction
        with torch.no_grad():
            # concat img and mask and perform inference
            input = torch.cat([img, mask], 1)  # nbatch, nchannels, height, width
            output = model(input.to(device))
        output = output.data.cpu().numpy()

        # extract cars as string from each element in batch
        num_elems_in_batch = output.shape[0]
        for idx_elem_in_batch in range(num_elems_in_batch):
            idx_id = idx_batch * params['predict']['batch_size'] + idx_elem_in_batch
            id = dataset_test.list_ids[idx_id]

            # get mat from output and plot
            mat = output[idx_elem_in_batch, ...]
            mat = np.rollaxis(mat, 0, 3)  # reverse rolling backwards
            if params['predict']['flag_plot_mat']:
                # convert image to numpy
                img_numpy = img.data.cpu().numpy()
                img_numpy = img_numpy[idx_elem_in_batch, ...]
                img_numpy = np.rollaxis(img_numpy, 0, 3)  # reverse rolling backwards
                img_numpy = img_numpy[:, :, ::-1]  # BGR to RGB

                fig, ax = plt.subplots(2, 1, figsize=(10, 10))
                ax[0].imshow(img_numpy)
                ax_mask = ax[1].imshow(mat[:, :, 0], cmap='PiYG', vmin=-1, vmax=+1)
                fig.colorbar(ax_mask, ax=ax[1])
                if False:  # only use in case of multiple axes, here x,y,z
                    ax[2].imshow(mat[:, :, 4])
                    ax[3].imshow(mat[:, :, 5])
                    ax[4].imshow(mat[:, :, 7])
                for axi, label in zip(ax, ['img', 'mask']):  # , 'x', 'y', 'z']):
                    axi.set_ylabel(label)
                fig.suptitle('ImageID={}'.format(id))

                # save
                path_out = os.path.join(params['path_folder_out'],
                                        'pred_mat',
                                        '{:05d}.png'.format(idx_id),
                                        )
                os.makedirs(os.path.dirname(path_out), exist_ok=True)
                fig.savefig(path_out)
                plt.close()

            # convert mat to item and plot.
            item = dataset_torch_test.convert_mat_to_item(mat)
            if params['predict']['flag_optimize']:
                for idx_car, car in enumerate(item.cars):
                    x_new, y_new, z_new, is_marked = optimize_xyz(car.v, car.u, car.x, car.y, car.z, params)
                    item.cars[idx_car].x = x_new
                    item.cars[idx_car].y = y_new
                    item.cars[idx_car].z = z_new
                    item.cars[idx_car].is_marked = is_marked

            if params['predict']['flag_plot_item']:
                item_org = dataset_test.load_item(id)
                item.img = item_org.img
                item.mask = np.zeros((1, 1))
                fig, ax = item.plot()
                fig.suptitle('ImageID={}'.format(id))

                if idx_batch == 2:
                    num_cars = len(item.cars)
                    plt.show()

                # save
                path_out = os.path.join(params['path_folder_out'],
                                        'pred_item',
                                        '{:05d}.png'.format(idx_id),
                                        )
                os.makedirs(os.path.dirname(path_out), exist_ok=True)
                fig.savefig(path_out)
                plt.close()

            # extract prediction string from item
            string = item.get_cars_as_string(flag_submission=True)
            predictions.append(string)

    # predictions to csv
    df_out = pd.DataFrame()
    df_out['ImageId'] = dataset_test.list_ids
    df_out.loc[0:len(predictions) - 1, 'PredictionString'] = predictions
    print(df_out.head())
    path_csv = os.path.join(params['path_folder_out'], 'predictions.csv')
    df_out.to_csv(path_csv, sep=',', index=False)

    return df_out
def train(
    model,
    device,
    params,
):
    # define training dataset
    dataset = data_loader.DataSet(
        path_csv=params['datasets']['train']['path_csv'],
        path_folder_images=params['datasets']['train']['path_folder_images'],
        path_folder_masks=params['datasets']['train']['path_folder_masks'],
    )
    dataset_torch = data_loader_torch.DataSetTorch(
        dataset,
        params,
        flag_load_label=True,
        flag_augment=params['train']['use_augmentation'],
    )
    dataset_loader = torch.utils.data.DataLoader(
        dataset=dataset_torch,
        batch_size=params['train']['batch_size'],
        shuffle=True,
        num_workers=4,
        pin_memory=True,  # see https://pytorch.org/docs/stable/data.html
    )

    # define optimizer and decrease learning rate by 0.1 every 3 epochs
    optimizer = torch.optim.AdamW(
        model.parameters(),
        lr=params['train']['learning_rate']['initial'],
    )
    lr_scheduler = torch.optim.lr_scheduler.StepLR(
        optimizer,
        step_size=params['train']['learning_rate']['num_epochs_const'],
        gamma=params['train']['learning_rate']['factor_decrease'],
    )

    # for each epoch...
    df_out = pd.DataFrame()
    for idx_epoch in range(params['train']['num_epochs']):
        print("Training epoch {}".format(idx_epoch))

        # set model to train (affects e.g. dropout layers) and disable unnecessary grad computation
        model.train()
        torch.set_grad_enabled(True)
        torch.cuda.empty_cache()  # empty cuda cache to prevent memory errors
        gc.collect(
        )  # empty unreferenced objects at the end. Not sure whether better at the end?

        # calculate loss for whole dataset
        num_batches = len(dataset_loader)
        loss_per_name = dict()
        dataset_tqdm = tqdm(dataset_loader)
        for img_batch, mask_batch, heatmap_batch, regr_batch in dataset_tqdm:

            # concat img and mask and perform inference
            input = torch.cat([img_batch, mask_batch],
                              1)  # nbatch, nchannels, height, width
            output = model(input.to(device))

            # calculate loss
            batch_loss_per_name = calc_loss(
                output,
                heatmap_batch.to(device),
                regr_batch.to(device),
                params['train']['loss'],
            )
            for name, batch_loss in batch_loss_per_name.items():
                if name not in loss_per_name:
                    loss_per_name[name] = 0
                loss_per_name[name] += batch_loss.data

            # change tqdm progress bar description
            description = "loss: "
            for name, batch_loss in batch_loss_per_name.items():
                description += "{}={:.3f} ".format(
                    name,
                    batch_loss.data.cpu().numpy())
            dataset_tqdm.set_description(description)

            # perform optimization
            batch_loss_per_name['tot'].backward(
            )  # computes x.grad += dloss/dx for all parameters x
            optimizer.step()  # updates values x += -lr * x.grad
            optimizer.zero_grad()  # set x.grad = 0, for next iteration

        # step learning rate after each epoch (not after each batch)
        lr_scheduler.step()

        # calculate average and store results
        for name in loss_per_name.keys():
            loss_per_name[name] = loss_per_name[name].cpu().numpy() / len(
                dataset_loader)
            df_out.loc[idx_epoch, 'loss_' + name] = loss_per_name[name]
        values_per_name = evaluate(model, device, params)
        for key, value in values_per_name.items():
            df_out.loc[idx_epoch, 'valid_' + key] = value

        # save history
        path_csv = os.path.join(
            params['path_folder_out'],
            'train_history_{}.csv'.format(idx_epoch),
        )
        os.makedirs(os.path.dirname(path_csv), exist_ok=True)
        df_out.to_csv(path_csv, sep=';')
        print(df_out)

        # save model weights
        path_weights = os.path.join(
            params['path_folder_out'],
            'model_{}.pth'.format(idx_epoch),
        )
        torch.save(model.state_dict(), path_weights)
    return df_out