关于使用 mlr3-pipelines,我有一些问题。实际上,我的目标是创建一个结合三个图的管道:
1 – 处理分类变量的图:级别插补 => 标准化
imp_cat = po("imputenewlvl", param_vals =list(affect_columns = selector_name(my_cat_variables)))encode = po("encode", param_vals =list(affect_columns = selector_name(my_cat_variables)))cat = imp_cat %>>% encode
2 – 处理一部分数值变量的图:均值插补 => 标准化
imp_mean = po("imputemean", param_vals = list(affect_columns =selector_name(my_first_set_of_numeric_variables)))scale = po("scale", param_vals = list(affect_columns = selector_name(my_first_set_of_numeric_variables)))num_mean = imp_mean %>>% scale
第三个图处理另一部分数值变量:中位数插补 => 最小最大值缩放
imp_median = po("imputemedian", param_vals = list(affect_columns =selector_name(my_second_set_of_numeric_variables)))min_max = po("scalerange", param_vals = list(affect_columns = selector_name(my_second_set_of_numeric_variables)))num_median = imp_median %>>% min_max
通过featureUnion Ops结合这些图:
graph = po("copy", 3) %>>% gunion(list(cat, num_mean, num_median )) %>>% po("featureunion")
最后在 GraphLearner 中添加学习器:
g1 = GraphLearner$new(graph %>>% po(lrn("classif.ranger")))
我的数据中有一些缺失值,因此在每个图中使用了插补器,我有一个二元分类任务。
my_task = TaskClassif$new(id="classif", backend = data, target = "my_target")
理论上,当我开始学习时,不应该有缺失值错误。
g1$train(my_task)
但是根据我选择的学习器,我遇到了几个错误。例如,如果我使用 ranger 作为学习器,我会遇到这个错误
Error: Missing data in columns: ....
如果我使用 svm、glmnet 或 xgvoost:我会遇到由于分类变量存在的问题。Error : has the following unsupported feature types: factor...
使用我的管道,我不应该有分类变量,也不应该有缺失值。所以我不明白如何克服这个问题。
1 – 我已经在每个图中使用了插补器,为什么有些算法仍然告诉我有缺失值?
2 – 如何在编码后移除分类变量?有些算法不支持这种类型的变量
更新
我认为在管道中进行的所有修改都没有被保存。换句话说,算法(svm, ranger, …)是在原始任务上进行训练,而不是在管道更新后的任务上
回答:
第一个问题的回答
我将尝试解释为什么在您的工作流程中总是有缺失值。
让我们加载一堆包
library(mlr3) library(mlr3pipelines)library(mlr3learners)library(mlr3tuning)library(paradox)
让我们选择带有缺失值的任务 pima
task <- tsk("pima")task$missings()diabetes age glucose insulin mass pedigree pregnant pressure triceps 0 0 5 374 11 0 0 35 227
由于没有分类列,我将把 triceps 转换为一个:
hb <- po("histbin", param_vals =list(affect_columns = selector_name("triceps")))
现在进行新级别插补和编码:
imp_cat <- po("imputenewlvl", param_vals =list(affect_columns = selector_name("triceps")))encode <- po("encode", param_vals = list( affect_columns = selector_name("triceps")))cat <- hb %>>% imp_cat %>>% encode
当您在task
上使用cat
时:
cat$train(task)[[1]]$data()#big output
不仅返回您选择转换的列,还返回所有其他列
这也适用于num_median
和num_mean
。
让我们创建它们
imp_mean <- po("imputemean", param_vals = list(affect_columns = selector_name(c("glucose", "mass"))))scale <- po("scale", param_vals = list(affect_columns = selector_name(c("glucose", "mass"))))num_mean <- imp_mean %>>% scaleimp_median <- po("imputemedian", param_vals = list(affect_columns = selector_name(c("insulin", "pressure"))))min_max <- po("scalerange", param_vals = list(affect_columns = selector_name(c("insulin", "pressure"))))num_median <- imp_median %>>% min_max
检查num_median
做了什么
num_median$train(task)[[1]]$data()#output diabetes insulin pressure age glucose mass pedigree pregnant triceps 1: pos 0.13341346 0.4897959 50 148 33.6 0.627 6 35 2: neg 0.13341346 0.4285714 31 85 26.6 0.351 1 29 3: pos 0.13341346 0.4081633 32 183 23.3 0.672 8 NA 4: neg 0.09615385 0.4285714 21 89 28.1 0.167 1 23 5: pos 0.18509615 0.1632653 33 137 43.1 2.288 0 35 --- 764: neg 0.19951923 0.5306122 63 101 32.9 0.171 10 48765: neg 0.13341346 0.4693878 27 122 36.8 0.340 2 27766: neg 0.11778846 0.4897959 30 121 26.2 0.245 5 23767: pos 0.13341346 0.3673469 47 126 30.1 0.349 1 NA768: neg 0.13341346 0.4693878 23 93 30.4 0.315 1 31
所以它在“insulin”和“pressure”列上做了它应该做的,但也返回了其他列未更改。
通过三次复制数据并在每个步骤中应用这三个预处理器,您返回了转换的列,但也返回了所有其他列 – 三次。
您应该做的是:
graph <- cat %>>% num_mean %>>% num_median
cat
转换选定的列并返回所有列,然后num_mean
转换选定的列并返回所有列…
graph$train(task)[[1]]$data()
在我看来看起来不错
更重要的是
g1 <- GraphLearner$new(graph %>>% po(lrn("classif.ranger")))g1$train(task)
有效
2 – 第二个问题的答案是使用选择器函数,具体来说,在您的情况下
selector_type()
:
selector_invert(selector_type("factor"))
如果在进入学习器之前调用,应该可以解决问题。