I have been trying to do the hyperparameter tuning of the caret models by using some libraries such as rBayesianOptimization. I started off with some simple models (such as svmLinear or glmnet) and it worked perfectly. When I wanted to try out some models with more hyperparameters (such as xgbTree or mlpWeightDecayML), the tuning process started causing exceptions after around 10 rounds.
I have been following the tutorial from this website on how to combine these two packages.
The basic code:
# Function used in BayesianOptimization
eval_function_mlpWeightDecayML <- function(layer1, layer2, layer3, decay) {
message("Running the eval 'mlpWeightDecayML' function...")
dataFrame = caretTrainObject$trainingData
index = caret::createDataPartition(dataFrame[, ncol(dataFrame)], p = 0.8, list = FALSE)
trainData = dataFrame[index, ]
testData = dataFrame[-index, ]
model <- suppressWarnings(caret::train(
x = trainData[, -ncol(dataFrame)],
y = trainData[, ncol(dataFrame)],
metric = caretTrainObject$metric,
method = "mlpWeightDecayML",
trControl = caret::trainControl(method = "none"),
verbose = FALSE,
tuneGrid = expand.grid(
layer1 = layer1,
layer2 = layer2,
layer3 = layer3,
decay = decay
)
))
message("Finished this evaluation! Getting the results ready..")
return(list(Score = calculate_specific_metric(model, testData, caretTrainObject$metric), Pred = 0))
}
calculate_specific_metric <- function(model, testData, metricName){
predictions = stats::predict(model, newdata = testData)
actual = testData[, ncol(testData)]
if(is_classification_model(model)){
matrix = caret::confusionMatrix(predictions, actual)
metrics = matrix$overall
} else {
# Negative because MAE, Rsquared and RMSE all are errors and should be minimized
metrics = -caret::postResample(pred = predictions, obs = actual)
}
if(metricName %in% names(metrics)){
return(metrics[metricName])
} else {
stop("Metric not found or not applicable for this model.")
}
}
tune.bayesian_optimization <- function(caretTrainObject){
dataFrame = caretTrainObject$trainingData
func = eval_function_mlpWeightDecayML
bounds = list(
layer1 = c(0L, 20L),
layer2 = c(0L, 20L),
layer3 = c(0L, 20L),
decay = c(0.0001, 0.9)
)
bayesianModel = rBayesianOptimization::BayesianOptimization(
func,
bounds = bounds,
n_iter = 5,
init_points = 10,
verbose = TRUE
)
bestPar = bayesianModel$Best_Par
}
caretTrainObject <- suppressWarnings(caret::train(
x = iris[, -ncol(iris)],
y = iris[, ncol(iris)],
method = "mlpWeightDecayML",
trControl = caret::trainControl(method = "cv"),
verbose = FALSE,
tuneGrid = expand.grid( # Grid not relevant
layer1 = c(3, 4),
layer2 = c(3, 4),
layer3 = c(3, 4),
decay = c(0.3, 0.4)
)
))
a = tune.bayesian_optimization(caretTrainObject)
The exception, after 10 rounds is:
... elapsed = 0.20 Round = 9 layer1 = 15.0000 layer2 = 0.0000 layer3 = 0.0000 decay = 0.2070436 Value = 0.4452055 Running the eval 'mlpWeightDecayML' function... Finished this evaluation! Getting the results ready.. elapsed = 0.16 Round = 10 layer1 = 7.0000 layer2 = 0.0000 layer3 = 0.0000 decay = 0.2733959 Value = 0.5547945 Error in if ((min(X) < 0) | (max(X) > 1) | ((max(X) - min(X)) <= 0.5)) { : missing value where TRUE/FALSE needed
I have tried with different datasets, still the same issue. The interesting part that this exact code, when run with caret models such as glmnet, runs perfectly fine. I debugged a bit and found out that the line number 168 in the rBayesianOptimization package causes an issue.
The same error is caused by both mlpWeightDecayML and xgbTree models (from what I tested).