当模型对象是 S4 对象时从模型对象访问 tuneValue - 插入符号,自定义模型
access tuneValue from the model object when it is a S4 object - caret, custom model
我在插入符中使用自定义模型,它基本上建立在普通 "cforest" 方法之上。
为了构建我的模型,我获取了 cforest 模型的模型信息:
newModel <- getModelInfo("cforest", regex=F)[[1]]
我需要实现自定义预测功能,所以我这样做:
out$predict = function(modelFit, newdata, submodels = NULL) {
# new predict function which needs the tuned parameters
best.params <- modelFit$tuneValue
# rest of the code using best params
}
新预测函数的内容本身是无关紧要的。关键是,我需要预测函数中的调整值。
虽然代码在其他模型上工作得很好,但这不适用于 cforest,因为在这种情况下,modelFit
是一个 "RandomForest" S4 对象,我无法访问 tuneValue
. (确切的错误是“Error in modelFit$tuneValue : $ operator not defined for this S4 class
”)
我探索了 "RandomForest" 对象,它似乎没有包含任何插槽中的调整值。
我的猜测是,由于它是一个 S4 对象,因此将调整后的值存储到 $tuneValue 中的插入符号代码在这种特殊情况下不起作用。
也许我可以在拟合过程中的某个时刻手动保存调谐值,但我不知道
1 - 我应该什么时候做(什么时候选择调整值?)
2 - 我应该将它们保存在哪里以便在预测期间访问它们
有人知道我该怎么做吗?
这是生成 RandomForest S4 对象的最小代码:
x <- matrix(rnorm(20*10), 20, 10)
y <- x %*% rnorm(10)
y <- factor(y<mean(y), levels=c(T,F), labels=c("high", "low"))
new_model <- getModelInfo("cforest", regex=F)[[1]]
fit <- train(x=x, y=y, method = new_model)
# this is a RandomForest S4 object
fit$finalModel
我花了一些时间才弄清楚,但实际上很简单。由于该模型是一个 S4 对象,我想在其中添加信息...我构建了自己的 S4 对象,继承自该模型!
为了做到这一点,我不得不更改 "fit" 函数。
# loading vanilla model
newModel <- getModelInfo("cforest", regex=F)[[1]]
# backing up old fit fun
newModel$old_fit <- out$fit
# editing fit function to wrap the S4 model into my custom S4 object
newModel$fit <- function(x, y, wts, param, lev, last, classProbs, ...) {
tmp <- newModel$old_fit(x, y, wts, param, lev, last, classProbs, ...)
if(isS4(tmp)) {
old_class <- as.character(class(tmp))
# creating custom class with the slots I need
setClass(".custom", slots=list(.threshold="numeric", .levels="character"), contains=old_class)
# instanciating the new class with values taken from the argument of fit()
tmp <- new(".custom", .threshold=param$threshold, .levels=lev, tmp)
}
tmp
}
现在,模型对象始终是 class“.custom”,所以我可以:
newModel$predict = function(modelFit, newdata, submodels = NULL) {
if(isS4(modelFit)){
if(class(modelFit)!=".custom")
error("predict() received a S4 object whose class was not '.custom'")
obsLevels <- modelFit@.levels
threshold <- modelFit@.threshold
} else {
obsLevels <- modelFit$obsLevels
threshold <- modelFit$tuneValue$threshold
}
# rest of the code
}
太棒了,现在我的自定义模型可以扩展任何插入符模型,无论它是否依赖于 S4 对象,如 cforest 或 svm!
我在插入符中使用自定义模型,它基本上建立在普通 "cforest" 方法之上。
为了构建我的模型,我获取了 cforest 模型的模型信息:
newModel <- getModelInfo("cforest", regex=F)[[1]]
我需要实现自定义预测功能,所以我这样做:
out$predict = function(modelFit, newdata, submodels = NULL) {
# new predict function which needs the tuned parameters
best.params <- modelFit$tuneValue
# rest of the code using best params
}
新预测函数的内容本身是无关紧要的。关键是,我需要预测函数中的调整值。
虽然代码在其他模型上工作得很好,但这不适用于 cforest,因为在这种情况下,modelFit
是一个 "RandomForest" S4 对象,我无法访问 tuneValue
. (确切的错误是“Error in modelFit$tuneValue : $ operator not defined for this S4 class
”)
我探索了 "RandomForest" 对象,它似乎没有包含任何插槽中的调整值。
我的猜测是,由于它是一个 S4 对象,因此将调整后的值存储到 $tuneValue 中的插入符号代码在这种特殊情况下不起作用。
也许我可以在拟合过程中的某个时刻手动保存调谐值,但我不知道
1 - 我应该什么时候做(什么时候选择调整值?)
2 - 我应该将它们保存在哪里以便在预测期间访问它们
有人知道我该怎么做吗?
这是生成 RandomForest S4 对象的最小代码:
x <- matrix(rnorm(20*10), 20, 10)
y <- x %*% rnorm(10)
y <- factor(y<mean(y), levels=c(T,F), labels=c("high", "low"))
new_model <- getModelInfo("cforest", regex=F)[[1]]
fit <- train(x=x, y=y, method = new_model)
# this is a RandomForest S4 object
fit$finalModel
我花了一些时间才弄清楚,但实际上很简单。由于该模型是一个 S4 对象,我想在其中添加信息...我构建了自己的 S4 对象,继承自该模型!
为了做到这一点,我不得不更改 "fit" 函数。
# loading vanilla model
newModel <- getModelInfo("cforest", regex=F)[[1]]
# backing up old fit fun
newModel$old_fit <- out$fit
# editing fit function to wrap the S4 model into my custom S4 object
newModel$fit <- function(x, y, wts, param, lev, last, classProbs, ...) {
tmp <- newModel$old_fit(x, y, wts, param, lev, last, classProbs, ...)
if(isS4(tmp)) {
old_class <- as.character(class(tmp))
# creating custom class with the slots I need
setClass(".custom", slots=list(.threshold="numeric", .levels="character"), contains=old_class)
# instanciating the new class with values taken from the argument of fit()
tmp <- new(".custom", .threshold=param$threshold, .levels=lev, tmp)
}
tmp
}
现在,模型对象始终是 class“.custom”,所以我可以:
newModel$predict = function(modelFit, newdata, submodels = NULL) {
if(isS4(modelFit)){
if(class(modelFit)!=".custom")
error("predict() received a S4 object whose class was not '.custom'")
obsLevels <- modelFit@.levels
threshold <- modelFit@.threshold
} else {
obsLevels <- modelFit$obsLevels
threshold <- modelFit$tuneValue$threshold
}
# rest of the code
}
太棒了,现在我的自定义模型可以扩展任何插入符模型,无论它是否依赖于 S4 对象,如 cforest 或 svm!