## Keras baseline with resnet50
### >90% validation accuracy after 5 epochs
```{r, eval=FALSE}
library(keras)

# Class labels
labels <- data.table::fread("input/train_labels.csv")
labels$cancer <- factor(labels$label, 
                        levels = c(0, 1),
                        labels = c("non_cancer", "cancer"))


if (!dir.exists("input/val")) {
    dir.create("input/val")
    lapply(as.character(unique(labels$cancer)), 
           function(x) dir.create(path = paste0("./input/train/", x)))
    lapply(as.character(unique(labels$cancer)), 
           function(x) dir.create(path = paste0("./input/val/", x)))
}


old_names <- paste0("input/train/", labels$id, ".tif")
new_names <- paste0("input/train/", labels$cancer, "/", labels$id, ".tif")
# 5% for validation
val_ind <- sample(1:nrow(labels), nrow(labels) * 0.05)
new_names[val_ind] <- sub("train", "val", new_names[val_ind])
Map(function(x, y) file.rename(from = x, to = y), old_names, new_names)

# Parameters
dim_size <- 96
batch_size <- 32
epochs <- 30

base_model <- application_xception(input_shape = c(dim_size, dim_size, 3),
                                   weights = "imagenet",
                                   include_top = FALSE,
                                   pooling = "avg")

predictions <- base_model$output %>% 
    layer_dense(units = 1, activation = "sigmoid")
model <- keras_model(inputs = base_model$input, outputs = predictions)

model %>% compile(
    loss = "binary_crossentropy",
    optimizer = optimizer_adam(lr = 0.002),
    metrics = "accuracy"
)

if (!dir.exists("models")) {
    dir.create("models")
}

if (!dir.exists("logs")) {
    dir.create("logs")
}

callbacks_list <- list(
    callback_csv_logger(
        filename = "logs/resnet.csv"),
    callback_early_stopping(
        monitor = "val_loss",
        min_delta = 1e-4,
        patience = 8,
        verbose = 1,
        mode = "min"
    ),
    callback_reduce_lr_on_plateau(
        monitor = "val_loss",
        factor = 0.5,
        patience = 4,
        verbose = 1,
        min_delta = 1e-4,
        mode = "min"
    ),
    callback_model_checkpoint(
        filepath = "models/resnet_{epoch:02d}_{val_loss:.2f}h.h5",
        monitor = "val_loss",
        save_best_only = FALSE,
        save_weights_only = FALSE,
        mode = "min"
    )
)

model %>% fit_generator(
    generator = flow_images_from_directory(directory = "data/train",
                                           batch_size = batch_size,
                                           target_size = c(dim_size, dim_size),
                                           shuffle = TRUE,
                                           image_data_generator(rescale = 1/255),
                                           class_mode = "binary"),
    validation_data = flow_images_from_directory(directory = "data/val",
                                                 batch_size = batch_size,
                                                 target_size = c(dim_size, dim_size),
                                                 shuffle = TRUE,
                                                 image_data_generator(rescale = 1/255),
                                                 class_mode = "binary"),
    steps_per_epoch = 1000, 
    validation_steps = 100,
    epochs = epochs,
    callbacks = callbacks_list 
)
```