R/cv_gdp.R

Defines functions cv_gdp

Documented in cv_gdp

#' Cross Validate Generalized Double Pareto Shrinkage Regression
#'
#' @param formula a model formula
#' @param data a training data set
#' @param cv.method preferably one of "boot632" (the default), "cv", or "repeatedcv".
#' @param nfolds the number of bootstrap or cross-validation folds to use. defaults to 5.
#' @param folds a vector of pre-set cross-validation or bootstrap folds from caret::createResample or
#' caret::createFolds.
#' @param nrep the number of repetitions for cv.method = "repeatedcv". defaults to 4.
#' @param tunlen the number of values for the unknown hyperparameter to test. defaults to 10.
#' @param crit the criterion by which to evaluate the model performance. must be one of "RobustMAE" (the default)
#' or "RobustMSE".
#'
#' @return
#' a train object
#' @export
#'
cv_gdp = function(formula, data, cv.method = "boot632", nfolds = 5, nrep = 4, folds = NULL, tunlen = 10, crit = c("MAE", "MSE")){

  if (!is.null(folds)) {
    nfolds = NULL
  }

  crit <- match.arg(crit)

  gdp <- list(type = "Regression",
                 library = "cvreg",
                 loop = NULL)

  gdp$parameters <- data.frame(parameter = c("alpha", "zeta"),
                                  class = rep("numeric", 2),
                                  label = c("alpha", "zeta"))

  gdpGrid <- function(x, y, len = NULL, search = "grid") {

    ## use grid search:
    if(search == "grid"){
      search = "grid"
    } else {
      search = "grid"
    }

    gdpzeta <- function(alpha) 2*sqrt(alpha+1)
    alpha = seq(1, 4, len = tunlen)
    grid <- lapply(alpha, function(a) expand.grid(a, seq(0.25*gdpzeta(a), gdpzeta(a), len = 4)))
    grid <- do.call(rbind, grid)
    colnames(grid) <- c("alpha", "zeta")
    out <- grid
    return(out)
  }

  gdp$grid <- gdpGrid

  gdpFit <- function(x, y, param, ...) {
    dat <- as.data.frame(x)
    dat$.outcome <- y
    cvreg::gdp(.outcome ~ ., data = dat, alpha = param$alpha, zeta = param$zeta)
  }

  gdp$fit <- gdpFit
  gdp$prob <- gdpFit

  gdpPred <- function(modelFit, newdata, preProc = NULL, submodels = NULL){
    newdata <- as.matrix(cbind(rep(1, nrow(newdata)), newdata))
    as.matrix(newdata %*% modelFit$coefficients)
  }

  gdp$predict <- gdpPred

  postRegResamp = function(pred, obs) {

    isNA <- is.na(pred)
    pred <- pred[!isNA]
    obs <- obs[!isNA]
    if (!is.factor(obs) && is.numeric(obs)) {
      if (length(obs) + length(pred) == 0) {
        out <- rep(NA, 2)
      }
      else {
        mse <- mean((pred - obs)^2)
        mae <- mean(abs(pred - obs))
        out <- c(mse, mae)
      }
      names(out) <- c("MSE", "MAE")
    }
    else {
      if (length(obs) + length(pred) == 0) {
        out <- rep(NA, 2)
      }
      else {
        pred <- factor(pred, levels = levels(obs))
        requireNamespaceQuietStop("e1071")
        out <- unlist(e1071::classAgreement(table(obs, pred)))[c("diag", "kappa")]
      }
      names(out) <- c("Accuracy", "Kappa")
    }
    if (any(is.nan(out)))
      out[is.nan(out)] <- NA
    out
  }

  robustSummary = function (data, lev = NULL, model = NULL)
  {
    if (is.character(data$obs))
      data$obs <- factor(data$obs, levels = lev)
    postRegResamp(data[, "pred"], data[, "obs"])
  }


  if (cv.method == "repeatedcv") {
    fitControl <- trainControl(method = cv.method,
                               number = nfolds,
                               repeats = nrep,
                               index = folds,
                               savePredictions = "all",
                               summaryFunction = robustSummary,
                               search = "grid")
  } else {

    fitControl <- trainControl(method = cv.method,
                               number = nfolds,
                               index = folds,
                               savePredictions = "all",
                               summaryFunction = robustSummary,
                               search = "grid")
  }


  fitted.models <- train(formula, data,
                         method = gdp,
                         metric = crit,
                         tuneLength = tunlen,
                         maximize = FALSE,
                         preProcess = c("center", "scale"),
                         trControl = fitControl)

  return(fitted.models)

}
abnormally-distributed/cvreg documentation built on May 3, 2020, 3:45 p.m.