我在使用caret
包实现一个带有径向基函数核(’svmRadial’)的支持向量机。根据我对文档和源代码的理解,caret
使用一个分析公式来获取sigma的合理估计,并将其固定为该值(根据输出:调优参数’sigma’被固定在0.1028894的值)。此外,caret
对一组成本参数C(默认值=3)进行交叉验证。
然而,如果我现在想设置自己的成本参数网格(tuneGrid),我还必须指定sigma的值。否则会出现以下错误:
错误:调优参数网格应包含sigma和C列
如何基于分析公式固定Sigma,同时仍然实现我自己的成本参数C的网格?
这是一个最小工作示例(MWE):
library(caret)library(mlbench)data(BostonHousing)set.seed(1)index <- sample(nrow(BostonHousing),nrow(BostonHousing)*0.75)Boston.train <- BostonHousing[index,]Boston.test <- BostonHousing[-index,]# 没有tuneGridset.seed(1)svmR <- train(medv ~ ., data = Boston.train, method = "svmRadial", preProcess = c("center", "scale"), trControl = trainControl(method = "cv", number = 5))# 使用tuneGrid(会显示错误信息)set.seed(1)svmR <- train(medv ~ ., data = Boston.train, method = "svmRadial", preProcess = c("center", "scale"), tuneGrid = expand.grid(C = c(0.01, 0.1)), trControl = trainControl(method = "cv", number = 5))
回答:
如果你查看模型的信息,会显示如果你不提供,网格是如何生成的:
getModelInfo("svmRadial")$svmRadial$gridfunction(x, y, len = NULL, search = "grid") { sigmas <- kernlab::sigest(as.matrix(x), na.action = na.omit, scaled = TRUE) if(search == "grid") { out <- expand.grid(sigma = mean(as.vector(sigmas[-2])), C = 2 ^((1:len) - 3)) } else { rng <- extendrange(log(sigmas), f = .75) out <- data.frame(sigma = exp(runif(len, min = rng[1], max = rng[2])), C = 2^runif(len, min = -5, max = 10)) } out }
所以获取它的方法是使用kernlab::sigest
估计sigma。首先我们提取svmRadial的网格方法:
models <- getModelInfo("svmRadial", regex = FALSE)[[1]]
由于你提供了一个公式,设置输入x和y:
preProcValues = preProcess(Boston.train, method = c("center", "scale")) processData = predict(preProcValues,Boston.train)x = model.matrix(medv ~ .,data=processData)[,-1]y = processData$medv
我们使用这个模型的网格函数,你可以看到它与你的输出相同:
set.seed(1)models$grid(x,y,3) sigma C1 0.1028894 0.252 0.1028894 0.503 0.1028894 1.00svmR$results sigma C RMSE Rsquared MAE RMSESD RsquaredSD MAESD1 0.1028894 0.25 5.112750 0.7591398 2.982241 0.8569208 0.05387213 0.40323542 0.1028894 0.50 4.498887 0.8046234 2.594059 0.7823051 0.05357678 0.36444303 0.1028894 1.00 4.055564 0.8349416 2.402248 0.8403222 0.06825159 0.3732571
这就是底层发生的情况:
set.seed(1)sigmas = kernlab::sigest(as.matrix(x), na.action = na.omit, scaled = TRUE)# 从代码中可以看到,它取两个极端分位数的平均值mean(sigmas[-2])[1] 0.1028894