R/caret.train.model.list.default.R

#' Can take x and y values as the defaults.
#' @param x passed directly to train {caret}; an object where samples are in rows and features are in columns. This could be a simple matrix, data frame or other type (e.g. sparse matrix)
#' @param y passed directly to train {caret}; a numeric or factor vector containing the outcome for each sample.
#' @param trControl passed directly to train {caret}; a list of values that define how this function acts. Default value if each item doesn't have its own trControl. See trainControl and http://topepo.github.io/caret/training.html#custom. (NOTE: If given, this argument must be named.)
#' @param training.list; a list describing a list of train {caret} values to run. Should be a list of objects generated by get.caret.model.spec. Each should contain exactly two values, to be passed to train {caret}: method and tuning. If tuning is an integer, it will be passed to tuneLength. If tuning is a data frame, it will be passed to tuneGrid. If it is null, train's default values for tuneLength will apply. Otherwise an error is generated.
#' @export
#' @examples
#' obs <- 500
#' x.vars <-100
#' y.vals <- sample(c(1,2),obs,replace = TRUE)
#' x.vals <- as.data.frame(matrix(rnorm(obs*x.vars,0,1),nrow=obs,ncol=x.vars))
#' x.vals <- apply(x.vals, 2, function(x.col){return(x.col+y.vals)})
#' trControl <- trainControl(method="repeatedcv", number=10, repeats=3)
#'   caret.train.model.list(x.vals
#'   ,y.vals
#'   ,trControl
#'   ,list(
#'    get.caret.model.spec("svmLinear")
#'    ,get.caret.model.spec("knn")
#'  )
#'  )
#' 
caret.train.model.list.default <- function(x,y,trControl,training.list,...){
  #so...
  #x and y could be actual x and y values, or they could be a formula and dataframe, respectively.
  
  #print(caret.train.model.listtestfunc(5))
  #print(class(x))
  print(class(y))
  caret.model.list = list()
  for(i in 1:length(training.list)){
    caret.model.spec <- training.list[[i]]
    gcmc.formals <- names(formals(get.caret.model.spec))[1:(length(names(formals(get.caret.model.spec)))-1)]
    spec.values <- names(caret.model.spec)[1:(length(names(caret.model.spec))-1)]
    #make sure we've got all the right paramaters in each gcmc
    if(all(spec.values %in% c(gcmc.formals,"params")
       && gcmc.formals %in% spec.values)){
      print(paste0("Running model ",as.character(i), " of ",
                   as.character(length(training.list)),
                   " for method ", caret.model.spec$method))
      #depends on the type of tuning we want to do.
      list.entry.name <- paste0(as.character(i),caret.model.spec$method)
      
      #pass params to train, which will then get passed on to the specific method being run.
      if("params"  %in% names(caret.model.spec)){
        #print("params is in the names; sending a valid params.ul")
        params.ul <- caret.model.spec$params #unlist(caret.model.spec$params)
        #unlist is giving us problems even when recursive is turned off. Let's seet if we can pass in a list without using it.
        #I suspect it'll be problematic though :S
      }else
      {
        params.ul <- list()
        #print("no params detected. namescaretmodelspec is ")
        print(names(caret.model.spec))
      }
      if (("trControl" %in% names(params.ul))==F){
        #add the default trControl to the params.ul list.
        params.ul <- append(params.ul, list("trControl"=trControl))
      }
      #add the appropriate tuning parameter to the parameter list.
      if(is.null(caret.model.spec$tuning)){
        #in this case, we don't need to add a tuning parameter
      }else if (class(caret.model.spec$tuning)=="numeric"){
        #add the tuneLength parameter
        params.ul <- append(params.ul, list("tuneLength" = caret.model.spec$tuning))
      }else if (class(caret.model.spec$tuning)=="data.frame"){
        #add the tuneGrid parameter
        params.ul <- append(params.ul, list("tuneGrid" = caret.model.spec$tuning))
      }else{
        stop("Unrecognized tuning method passed to train.caret.model.list")
      }
    
#           do.call(train,
#                   c(list(reduced.voxels.ds$x, reduced.voxels.ds$y,
#                          method = train.list.svm.nnet[[1]]$method,
#                          preProcess = train.list.svm.nnet[[1]]$preProcess,
#                          trControl = control,
#                          tuneGrid = train.list.svm.nnet[[1]]$tuning),
#                     params.ul)
      #neuralnet is quite particular about the format it needs data in.
      #we're going to write code here to automatically handle two needed transformations:

      #taking x and y values, if x isn't a formula, and put them into a single data frame
      #if y is a factor, the formula will be in the form of values.
      #should also generate a warning
      #AND this should only be done if neuralnet is the method specified.
      train.args <- c(list(x, y,
                           method = caret.model.spec$method,
                           #                    trControl = trControl,
                           preProcess = caret.model.spec$preProcess),
                      params.ul)
      #print(train.args)
      caret.model.list[[list.entry.name]] <- do.call(train, train.args)
#           train(x, y,
#                 method = caret.model.spec$method,
#                 trControl = trControl,
#                 preProcess = caret.model.spec$preProcess,
#                 params.ul
    }else
    {
      print(names(caret.model.spec))
      print(names(formals(get.caret.model.spec)))
      stop("One or more items passed to train.caret.model.list in the training.list does not appear to be a canonical caret model spec list.")
      
    }
    
  }
  return(caret.model.list)
}
bjsmith/r-mvpa documentation built on May 30, 2019, 11:53 a.m.