使用 makeFeatSelWrapper (mlr) 的 bit.names 和 bits.to.features 参数对特征组执行包装器选择
Using bit.names and bits.to.features arguments to makeFeatSelWrapper (mlr) to perform wrapper selection over groups of features
我想使用 mlr 包通过包装方法对鸢尾花数据集执行特征选择,但是我只想查看与花瓣 and/or 萼片相关的特征组。因此,包装器例程不会查看不同组合中的 4 个功能,而是查看不同组合中的两组功能。
mlr 文档指出这可以使用两个参数 bit.names
和 bit.to.feature
执行:
bit.names [character] Names of bits encoding the solutions. Also
defines the total number of bits in the encoding. Per default these
are the feature names of the task.
bits.to.features [function(x, task)] Function which transforms an
integer-0-1 vector into a character vector of selected features. Per
default a value of 1 in the ith bit selects the ith feature to be in
the candidate solution.
我在 mlr 教程或其他地方找不到这两个参数的任何用法示例。
我将使用 ?mlr::selectFeatures
中提供的示例。
首先对所有特征进行操作
library(mlr)
rdesc <- makeResampleDesc("Holdout")
ctrl <- makeFeatSelControlSequential(method = "sfs",
maxit = NA)
res <- selectFeatures("classif.rpart",
iris.task,
rdesc,
control = ctrl)
analyzeFeatSelResult(res)
这按预期工作
为了 运行 在特征组上,我设计了一个 0/1 矩阵来将特征映射到组(我不确定这是否是要走的路,它看起来很合乎逻辑):
mati <- rbind(
c(0,0,1,1),
c(1,1,0,0))
rownames(mati) <- c("Petal", "Sepal")
colnames(mati) <- getTaskFeatureNames(iris.task)
矩阵看起来像:
Sepal.Length Sepal.Width Petal.Length Petal.Width
Petal 0 0 1 1
Sepal 1 1 0 0
现在我 运行:
res <- selectFeatures("classif.rpart",
iris.task,
rdesc,
control = ctrl,
bit.names = c("Petal", "Sepal"),
bits.to.features = function(x = mati, task) mlr:::binaryToFeatures(x, getTaskFeatureNames(task)))
analyzeFeatSelResult(res)
#output
Features : 1
Performance : mmce.test.mean=0.0200000
Sepal
Path to optimum:
- Features: 0 Init : Perf = 0.66 Diff: NA *
- Features: 1 Add : Sepal Perf = 0.02 Diff: 0.64 *
Stopped, because no improving feature was found.
这似乎执行了我需要的操作,但我不太确定我是否正确定义了 bits.to.features
参数。
但是当我尝试在包装器中使用相同的方法时:
outer <- makeResampleDesc("CV", iters = 2L)
inner <- makeResampleDesc("Holdout")
ctrl <- makeFeatSelControlSequential(method = "sfs",
maxit = NA)
lrn <- makeFeatSelWrapper("classif.rpart",
resampling = inner,
control = ctrl,
bit.names = c("Petal", "Sepal"),
bits.to.features = function(x = mati, task) mlr:::binaryToFeatures(x, getTaskFeatureNames(task)))
r <- resample(lrn, iris.task, outer, extract = getFeatSelResult)
我收到一个错误:
Resampling: cross-validation
Measures: mmce
[FeatSel] Started selecting features for learner 'classif.rpart'
With control class: FeatSelControlSequential
Imputation value: 1
[FeatSel-x] 1: 00 (0 bits)
[FeatSel-y] 1: mmce.test.mean=0.7200000; time: 0.0 min
[FeatSel-x] 2: 10 (1 bits)
[FeatSel-y] 2: mmce.test.mean=0.0800000; time: 0.0 min
[FeatSel-x] 2: 01 (1 bits)
[FeatSel-y] 2: mmce.test.mean=0.0000000; time: 0.0 min
[FeatSel-x] 3: 11 (2 bits)
[FeatSel-y] 3: mmce.test.mean=0.0800000; time: 0.0 min
[FeatSel] Result: Sepal (1 bits)
Error in `[.data.frame`(df, , j, drop = drop) :
undefined columns selected
我做错了什么,bit.names
和 bit.to.feature
参数的正确用法是什么?
谢谢
编辑:我在 mlr github 上发布了一个问题:https://github.com/mlr-org/mlr/issues/2468
我猜你发现了两个错误。
第一个是您的代码甚至 运行s,第二个是这不适用于嵌套重采样。
错误 1:您的代码不应该 运行
首先mati
没有任何作用,因为它会被bits.to.features
的每次内部调用覆盖。毕竟你刚刚定义了一个默认参数。
你定义的 bit.names
"Petal"
和 "Sepal"
你基本上只是告诉 mlr 使用两位。
所以特征 selection 将适用于向量 00、01、10、11。
不幸的是,R 现在自动将这些向量回收到 4 的长度,因此 10 变成 1010:
mlr:::binaryToFeatures(c(1,0), getTaskFeatureNames(iris.task))
# [1] "Sepal.Length" "Petal.Length"
这是我们的第一个错误,mlr 应该避免此处的矢量回收。
要使代码 运行 符合预期,您可以像这样定义函数 bits.to.features
:
bitnames = c("Sepal", "Petal")
btf = function(x, task) {
sets = list(
c("Sepal.Length", "Sepal.Width"),
c("Petal.Length", "Petal.Width")
)
res = unlist(sets[as.logical(x)])
if (is.null(res)) {
return(character(0L))
} else {
return(res)
}
}
res <- selectFeatures("classif.rpart", iris.task, rdesc,
control = ctrl, bits.to.features = btf, bit.names = bitnames)
bts
的解释
引用 selectFeatures
的帮助页面:
[function(x, task)]
Function which transforms an integer-0-1 vector into a character vector of selected features.
Per default a value of 1 in the ith bit selects the ith feature to be in the candidate solution.
所以 x
是一个包含 0 和 1 的向量(例如 c(0,0,1,0)
)。
如果您不更改该功能,它将 return 第三个功能的名称(例如 "Petal.Length"
用于 iris)。向量 x
将始终与定义的 bit.names
具有相同的长度。然而,生成的字符向量可以是任意长度。它只需要 return 任务的有效特征名称。
在示例中,我将功能名称硬编码到函数 bts
中。如果您想将该功能应用于许多不同的任务,这是不好的做法。
因此 mlr 使您可以访问 task
对象,因此也可以通过 getTaskFeatureNames(task)
访问特征名称,这样您就可以以编程方式生成特征名称,而不是硬编码。
错误 2:bit.names
必须是特征名称
特征选择 return 结果是位名称。然后 mlr 尝试 select 数据集中的这些位名称,但显然它们不存在,因为它们完全不相关(在您的情况下)。
此错误现已在 github 版本的 mlr 中得到解决。
我想使用 mlr 包通过包装方法对鸢尾花数据集执行特征选择,但是我只想查看与花瓣 and/or 萼片相关的特征组。因此,包装器例程不会查看不同组合中的 4 个功能,而是查看不同组合中的两组功能。
mlr 文档指出这可以使用两个参数 bit.names
和 bit.to.feature
执行:
bit.names [character] Names of bits encoding the solutions. Also defines the total number of bits in the encoding. Per default these are the feature names of the task.
bits.to.features [function(x, task)] Function which transforms an integer-0-1 vector into a character vector of selected features. Per default a value of 1 in the ith bit selects the ith feature to be in the candidate solution.
我在 mlr 教程或其他地方找不到这两个参数的任何用法示例。
我将使用 ?mlr::selectFeatures
中提供的示例。
首先对所有特征进行操作
library(mlr)
rdesc <- makeResampleDesc("Holdout")
ctrl <- makeFeatSelControlSequential(method = "sfs",
maxit = NA)
res <- selectFeatures("classif.rpart",
iris.task,
rdesc,
control = ctrl)
analyzeFeatSelResult(res)
这按预期工作
为了 运行 在特征组上,我设计了一个 0/1 矩阵来将特征映射到组(我不确定这是否是要走的路,它看起来很合乎逻辑):
mati <- rbind(
c(0,0,1,1),
c(1,1,0,0))
rownames(mati) <- c("Petal", "Sepal")
colnames(mati) <- getTaskFeatureNames(iris.task)
矩阵看起来像:
Sepal.Length Sepal.Width Petal.Length Petal.Width
Petal 0 0 1 1
Sepal 1 1 0 0
现在我 运行:
res <- selectFeatures("classif.rpart",
iris.task,
rdesc,
control = ctrl,
bit.names = c("Petal", "Sepal"),
bits.to.features = function(x = mati, task) mlr:::binaryToFeatures(x, getTaskFeatureNames(task)))
analyzeFeatSelResult(res)
#output
Features : 1
Performance : mmce.test.mean=0.0200000
Sepal
Path to optimum:
- Features: 0 Init : Perf = 0.66 Diff: NA *
- Features: 1 Add : Sepal Perf = 0.02 Diff: 0.64 *
Stopped, because no improving feature was found.
这似乎执行了我需要的操作,但我不太确定我是否正确定义了 bits.to.features
参数。
但是当我尝试在包装器中使用相同的方法时:
outer <- makeResampleDesc("CV", iters = 2L)
inner <- makeResampleDesc("Holdout")
ctrl <- makeFeatSelControlSequential(method = "sfs",
maxit = NA)
lrn <- makeFeatSelWrapper("classif.rpart",
resampling = inner,
control = ctrl,
bit.names = c("Petal", "Sepal"),
bits.to.features = function(x = mati, task) mlr:::binaryToFeatures(x, getTaskFeatureNames(task)))
r <- resample(lrn, iris.task, outer, extract = getFeatSelResult)
我收到一个错误:
Resampling: cross-validation
Measures: mmce
[FeatSel] Started selecting features for learner 'classif.rpart'
With control class: FeatSelControlSequential
Imputation value: 1
[FeatSel-x] 1: 00 (0 bits)
[FeatSel-y] 1: mmce.test.mean=0.7200000; time: 0.0 min
[FeatSel-x] 2: 10 (1 bits)
[FeatSel-y] 2: mmce.test.mean=0.0800000; time: 0.0 min
[FeatSel-x] 2: 01 (1 bits)
[FeatSel-y] 2: mmce.test.mean=0.0000000; time: 0.0 min
[FeatSel-x] 3: 11 (2 bits)
[FeatSel-y] 3: mmce.test.mean=0.0800000; time: 0.0 min
[FeatSel] Result: Sepal (1 bits)
Error in `[.data.frame`(df, , j, drop = drop) :
undefined columns selected
我做错了什么,bit.names
和 bit.to.feature
参数的正确用法是什么?
谢谢
编辑:我在 mlr github 上发布了一个问题:https://github.com/mlr-org/mlr/issues/2468
我猜你发现了两个错误。 第一个是您的代码甚至 运行s,第二个是这不适用于嵌套重采样。
错误 1:您的代码不应该 运行
首先mati
没有任何作用,因为它会被bits.to.features
的每次内部调用覆盖。毕竟你刚刚定义了一个默认参数。
你定义的 bit.names
"Petal"
和 "Sepal"
你基本上只是告诉 mlr 使用两位。
所以特征 selection 将适用于向量 00、01、10、11。
不幸的是,R 现在自动将这些向量回收到 4 的长度,因此 10 变成 1010:
mlr:::binaryToFeatures(c(1,0), getTaskFeatureNames(iris.task))
# [1] "Sepal.Length" "Petal.Length"
这是我们的第一个错误,mlr 应该避免此处的矢量回收。
要使代码 运行 符合预期,您可以像这样定义函数 bits.to.features
:
bitnames = c("Sepal", "Petal")
btf = function(x, task) {
sets = list(
c("Sepal.Length", "Sepal.Width"),
c("Petal.Length", "Petal.Width")
)
res = unlist(sets[as.logical(x)])
if (is.null(res)) {
return(character(0L))
} else {
return(res)
}
}
res <- selectFeatures("classif.rpart", iris.task, rdesc,
control = ctrl, bits.to.features = btf, bit.names = bitnames)
bts
的解释
引用 selectFeatures
的帮助页面:
[function(x, task)]
Function which transforms an integer-0-1 vector into a character vector of selected features. Per default a value of 1 in the ith bit selects the ith feature to be in the candidate solution.
所以 x
是一个包含 0 和 1 的向量(例如 c(0,0,1,0)
)。
如果您不更改该功能,它将 return 第三个功能的名称(例如 "Petal.Length"
用于 iris)。向量 x
将始终与定义的 bit.names
具有相同的长度。然而,生成的字符向量可以是任意长度。它只需要 return 任务的有效特征名称。
在示例中,我将功能名称硬编码到函数 bts
中。如果您想将该功能应用于许多不同的任务,这是不好的做法。
因此 mlr 使您可以访问 task
对象,因此也可以通过 getTaskFeatureNames(task)
访问特征名称,这样您就可以以编程方式生成特征名称,而不是硬编码。
错误 2:bit.names
必须是特征名称
特征选择 return 结果是位名称。然后 mlr 尝试 select 数据集中的这些位名称,但显然它们不存在,因为它们完全不相关(在您的情况下)。
此错误现已在 github 版本的 mlr 中得到解决。