srepho srepho - 1 month ago 46
R Question

User Defined Metric in Caret Package

I am looking to utilise the caret package with a metric that is not one of the default options. For the example below I use the Metrics package. I have read all of the relevant questions on StackOverflow as well as the guide on the caret website but still am receiving errors.

In the example below I wish to use Mean Absolute Error.

create a function:

maefunction<-function(data, lev=NULL, model=NULL){
require(Metrics)
MAE<-mae(data[, "obs"], data[, "pred"])
out<-c(MAE)
out
}


Now I insert the function into the trainControl

library(caret)
GBM<-train(train$result~., data=train, method="gbm", trControl=trainControl(summaryFunction=maefunction), metric=MAE)


I receive the following message

Error in list_to_dataframe(res, attr(.data, "split_labels"), .id, id_as_factor) :
Results must be all atomic, or all data frames
In addition: Warning messages:
1: In if (metric %in% c("Accuracy", "Kappa")) stop(paste("Metric", :
the condition has length > 1 and only the first element will be used
2: In if (metric == "ROC" & !ctrl$classProbs) stop("train()'s use of ROC codes requires class probabilities. See the classProbs option of trainControl()") :
the condition has length > 1 and only the first element will be used
3: In if (!(metric %in% perfNames)) { :
the condition has length > 1 and only the first element will be used
4: In train.default(x, y, weights = w, ...) :
The metric "4" was not in the result set. will be used instead.The metric "0.5" was not in the result set. will be used instead.

Answer

I think that you have to use a named vector (see the example below). I didn't explicitly say that in the documentation so I will update that section.

Max

library(mlbench)
data(BostonHousing)

maeSummary <- function (data,
                        lev = NULL,
                        model = NULL) {
   out <- mae(data$obs, data$pred)  
   names(out) <- "MAE"
   out
}

mControl <- trainControl(summaryFunction = maeSummary)
marsGrid <- expand.grid(degree = 1, nprune = (1:10) * 2)

set.seed(1)
earthFit <- train(medv ~ .,
                  data = BostonHousing, 
                  "earth",
                  tuneGrid = marsGrid,
                  metric = "MAE",
                  maximize = FALSE,
                  trControl = mControl)
Comments