I am trying to use the hmeasure metric Hand,2009 as my custom metric for training SVMs in caret. As I am relatively new to using R, I tried adapt the twoClassSummary function. All I need is to pass the true class labels and predicted class probability from the model (an svm) to the HMeasure function from the hmeasure package instead of using ROC or other measures of classification performance in caret.
For example, a call to the HMeasure function in R - HMeasure(true.class,predictedProbs[,2])- results in calculation of the Hmeasure. Using an adaptation of twoClassSummary code below results in an error being returned: 'x' must be numeric.
Maybe that train function can't "see" the predicted probabilities to evaluate the HMeasure function. How can I fix this?
I ve read the documentation, and linked questions posed on SO dealing with regression. Thats got me some of the way. I would be grateful for any help or pointers towards a solution.
library(caret)
library(doMC)
library(hmeasure)
library(mlbench)
set.seed(825)
data(Sonar)
table(Sonar$Class)
inTraining <- createDataPartition(Sonar$Class, p = 0.75, list = FALSE)
training <- Sonar[inTraining, ]
testing <- Sonar[-inTraining, ]
# using caret
fitControl <- trainControl(method = "repeatedcv",number = 2,repeats=2,summaryFunction=twoClassSummary,classProbs=TRUE)
svmFit1 <- train(Class ~ ., data = training,method = "svmRadial",trControl = fitControl,preProc = c("center", "scale"),tuneLength = 8,metric = "ROC")
predictedProbs <- predict(svmFit1, newdata = testing , type = "prob")
true.class<-testing$Class
hmeas<- HMeasure(true.class,predictedProbs[,2]) # suppose its Rocks we're interested in predicting
hmeasure.probs<-hmeas$metrics[c('H')] # returns the H measure metric
hmeasureCaret<-function (data, lev = NULL, model = NULL,...)
{
# adaptation of twoClassSummary
require(hmeasure)
if (!all(levels(data[, "pred"]) == levels(data[, "obs"])))
stop("levels of observed and predicted data do not match")
#lev is a character string that has the outcome factor levels taken from the training data
hObject <- try(hmeasure::HMeasure(data$obs, data[, lev[1]]),silent=TRUE)
hmeasH <- if (class(hObject)[1] == "try-error") {
NA
} else {hObject$metrics[[1]] #hObject$metrics[c('H')] returns a dataframe, need to return a vector
}
out<-hmeasH
names(out) <- c("Hmeas")
#class(out)
}
environment(hmeasureCaret) <- asNamespace('caret')
Non working code below.
ctrl <- trainControl(method = "cv", summaryFunction = hmeasureCaret,classProbs=TRUE,allowParallel = TRUE,
verboseIter=TRUE,returnData=FALSE,savePredictions=FALSE)
set.seed(1)
svmTune <- train(Class.f ~ ., data = training,method = "svmRadial",trControl = ctrl,preProc = c("center", "scale"),tuneLength = 8,metric="Hmeas",
verbose = FALSE)