library(dplyr)
library(tidymodels)


data("credit_data")

summary(credit_data)

# Fit model with parsnip --------------------------------------------------

# specify random forest model
model <- rand_forest(trees = 1000, mtry = 4, min_n = 5) %>%
  set_mode("classification") %>%
  set_engine("ranger")

# train model
trained_model <- model %>%
  fit(Status ~ ., data = credit_data)

# get predictions
predict(trained_model, new_data = credit_data, type = "class")
predict(trained_model, new_data = credit_data, type = "prob")



# Data pre-processing using recipes ------------------------------------------------

# create a "recipe" for pre-processing data
rec <- recipe(Status ~ ., data = credit_data) %>%
  step_impute_knn(Home, Marital, Job, Income, Assets, Debt, neighbors = 3) %>%
  step_normalize(all_numeric_predictors())


# train preprocessing steps
trained_rec <- prep(rec, training = credit_data)

# transform data
bake(trained_rec, new_data = credit_data)



# Train-test split --------------------------------------------------------

# create train-test split (80% training, 20% test)
split <- initial_split(credit_data, prop = 0.8)
split

credit_train <- training(split)    # training set
credit_test <- testing(split)      # test set



# Create pipeline using workflows -----------------------------------------

# combine preprocessing recipe and random forest model into a modeling pipeline
pipeline <- workflow() %>%
  add_recipe(rec) %>%
  add_model(model)

# train pipeline using training data
trained_pipe <- pipeline %>%
  fit(credit_train)

# get predictions for testing set
credit_pred <- predict(trained_pipe, new_data = credit_test, type = "prob") %>%
  bind_cols(credit_test)

# calculate performance (AUC) on test set
credit_pred %>% roc_auc(truth = Status, .pred_bad)



# Cross-validation --------------------------------------------------------

# create cross-validation folds
folds <- vfold_cv(credit_train, v = 5)
folds

# run cross-validation
cv_results <- pipeline %>% 
  fit_resamples(folds)

# get average performance metrics across folds
cv_results %>% collect_metrics()



# Hyperparameter tuning ------------------------------------------------------------

# specify model - indicate that mtry and min_n parameters will be tuned
mod <- rand_forest(trees = 200, mtry = tune(), min_n = tune()) %>%
  set_mode("classification") %>% 
  set_engine("ranger")

# create pipeline
pipeline <- workflow() %>%
  add_recipe(rec) %>%
  add_model(mod)

# create grid of hyperparameter values
grid <- expand.grid(
  mtry = c(2,4,8), 
  min_n = c(5, 10, 20)
)

# tune model
tune_results <- pipeline %>%
  tune_grid(resamples = folds, 
            grid = grid)

# view tuning results
tune_results %>% collect_metrics()
tune_results %>% show_best(metric = "roc_auc")

# extract top performing tuning parameters 
best_tune <- tune_results %>% select_best(metric = "roc_auc")  

# update pipeline to use best tuning parameters and refit using entire training set
final_model <- pipeline %>%
  finalize_workflow(best_tune) %>%
  fit(credit_train)

# evaluate performance of final model on test set
final_model %>%
  predict(new_data = credit_test, type = "prob") %>%
  bind_cols(credit_test) %>%
  roc_auc(truth = Status, .pred_bad)
