我正在使用两种不同的方法来获取过滤器选择的特征。我希望这些方法返回相同的值,但它们没有这样做,我不明白为什么。使用第二种方法的原因是,我可以访问用于选择要素的分数,而不仅仅是所选要素的名称。
该筛选器是一个单变量模型分数筛选器,使用 Cox 模型来衡量性能,并选择前 5 个特征。我创建了一个重采样实例,以便两种方法在每个折叠中使用相同的样本。
第一种方法是通常的方法 - 使用 makeFilterWrapper 将过滤器包裹在套索模型周围,并通过重新采样的提取选项调用 getFilteredFeatures。我的理解是,getFilteredFeatures返回过滤器选择的特征,然后再传递给套索模型。
在第二种方法中,我使用 subsetTask 创建与 getFilteredFeatures 在每个 CV 折叠中使用的相同子任务,然后调用 generateFilterValuesData 来获取过滤器生成的值。每个折叠中此列表中的前 5 个值应与每个折叠中从 getFilteredFeatures 返回的值匹配,但它们不匹配。这是为什么呢?
library(survival)
#> Warning: package 'survival' was built under R version 3.5.3
library(mlr)
#> Loading required package: ParamHelpers
data(veteran)
task_id = "VET"
vet.task <- makeSurvTask(id = task_id, data = veteran, target = c("time", "status"))
vet.task <- createDummyFeatures(vet.task)
inner = makeResampleDesc("CV", iters=2, stratify=TRUE) # Tuning
outer = makeResampleDesc("CV", iters=2, stratify=TRUE) # Benchmarking
set.seed(24601)
resinst = makeResampleInstance(desc=outer, task=vet.task)
cox.lrn <- makeLearner(cl="surv.coxph", id = "coxph", predict.type="response")
lasso.lrn <- makeLearner(cl="surv.cvglmnet", id = "lasso", predict.type="response", alpha = 1, nfolds=5)
filt.uni.lrn =
makeFilterWrapper(
lasso.lrn,
fw.method="univariate.model.score",
perf.learner=cox.lrn,
fw.abs = 5
)
#Method 1
res = resample(learner=filt.uni.lrn, task=vet.task, resampling=resinst, measures=list(cindex), extract=getFilteredFeatures)
#> Resampling: cross-validation
#> Measures: cindex
#> [Resample] iter 1: 0.7458904
#> [Resample] iter 2: 0.6575813
#>
#> Aggregated Result: cindex.test.mean=0.7017359
#>
res$extract
#> [[1]]
#> [1] "karno" "diagtime" "celltype.squamous"
#> [4] "celltype.smallcell" "celltype.adeno"
#>
#> [[2]]
#> [1] "karno" "diagtime" "age"
#> [4] "celltype.smallcell" "celltype.large"
#Method 2
for (i in 1:2) {
subt = subsetTask(task=vet.task, subset = resinst$train.inds[[i]])
print(generateFilterValuesData(subt, method="univariate.model.score", perf.learner=cox.lrn))
}
#> FilterValues:
#> Task: VET
#> name type method value
#> 2 karno numeric univariate.model.score 0.6387665
#> 7 celltype.smallcell numeric univariate.model.score 0.6219512
#> 8 celltype.adeno numeric univariate.model.score 0.5700000
#> 5 prior numeric univariate.model.score 0.5456522
#> 6 celltype.squamous numeric univariate.model.score 0.5316206
#> 4 age numeric univariate.model.score 0.5104603
#> 1 trt numeric univariate.model.score 0.5063830
#> 3 diagtime numeric univariate.model.score 0.4760956
#> 9 celltype.large numeric univariate.model.score 0.3766520
#> FilterValues:
#> Task: VET
#> name type method value
#> 2 karno numeric univariate.model.score 0.6931330
#> 9 celltype.large numeric univariate.model.score 0.6264822
#> 7 celltype.smallcell numeric univariate.model.score 0.5269058
#> 6 celltype.squamous numeric univariate.model.score 0.5081967
#> 8 celltype.adeno numeric univariate.model.score 0.5064655
#> 4 age numeric univariate.model.score 0.4980237
#> 1 trt numeric univariate.model.score 0.4646018
#> 3 diagtime numeric univariate.model.score 0.4547619
#> 5 prior numeric univariate.model.score 0.4527897
创建于 2019-10-02 由 reprex 软件包 (v0.3.0(
你在这里混淆了两件事。
案例 1(嵌套重采样(
在嵌套重采样的外折中选择的特征是根据内重采样的最佳性能褶皱确定的。
- 折叠 1(内部(->使用过滤器计算前 5 个特征 ->计算模型性能
- 折叠 2(内部(->使用过滤器计算前 5 个特征 ->计算模型性能
- 检查哪个内褶皱具有最佳性能(假设折叠 1(->从该折叠中取出前 5 个特征作为模型拟合在外折叠中
因此,过滤器值实际上不会在外部折叠上计算,而只会在内部折叠上计算。您基本上是在问"根据来自内循环的过滤器给我前 5 个特征,并且只在外折叠中训练模型"。由于过滤器值不会在外折中再次重新计算,因此只能返回特征名称,而不会返回任何值。
案例2(直接计算滤波器值(
在这里,您可以直接在两个外部折叠上生成过滤器值。由于观测值与嵌套重采样中的内部褶皱不同(情况 1(,因此套索学习器将得出不同的过滤分数(模型拟合发生在不同的观测值中(,并且可能具有不同的排名。
IIUC 您的想法是,在嵌套重采样设置中为每个外部折叠再次生成过滤器值。事实并非如此,也不会有任何好处,因为在内部褶皱的优化过程中已经选择了适合模型的特征。
对于外部褶皱,仅使用内循环中建议的选定特征来训练模型。同样的逻辑也适用于调优:"给我内循环中所有折叠的最佳超参数(我会告诉你如何做到这一点(,然后使用这些设置在外折叠上拟合模型"。
也许将此逻辑转移到调优中会有所帮助:您也不会在每个外部折叠上独立调用tuneParams()
并假设您返回的超参数与内部嵌套重采样优化会提出的相同,不是吗?