You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

R语言MLR包:如何阻止makeClassifTask删除测试集空因子水平

解决mlr中测试集空因子水平导致的任务创建问题

我之前也碰到过完全一样的场景,咱们先把问题的核心理清楚:mlr的makeClassifTask默认会自动清理空因子水平(也就是fixup.data="yes"的默认行为),但咱们需要保留这些水平来和训练集的特征对齐——毕竟模型是基于训练集所有因子水平训练的,测试集必须严格匹配特征结构才行。

问题拆解

你已经通过testdata$Var1 <- factor(testdata$Var1, levels = levels(traindata$Var1))给测试集Var1加上了空水平-1,但遇到了两难:

  • 用默认参数创建任务时,mlr会自动删掉这个空水平,抛出警告
  • 设置fixup.data="no"时,mlr又因为检测到空水平直接报错,不让任务创建

可行的解决方案

这里有两个靠谱的办法,你可以根据自己的习惯选:

方法1:临时添加空水平记录,创建任务后再移除

这个办法有点取巧但实用性拉满,核心是先让测试集每个因子水平都至少有一条数据,过了mlr的校验后再把临时数据删掉:

# 先复制一份测试集避免修改原数据
temp_test <- testdata
# 添加一条包含Var1=-1的临时记录(response填虚拟值即可)
temp_test <- rbind(temp_test, data.frame(ID = 999, Var1 = "-1", Var2 = 0, response = 0))
# 创建任务,此时不会有警告或错误
testtask <- makeClassifTask(data = temp_test, target = "response", positive = "1")
# 移除刚才添加的临时记录
testtask <- subsetTask(testtask, subset = temp_test$ID != 999)

这样创建出来的任务会完整保留Var1的所有水平,同时测试集还是你原本的真实数据。

方法2:直接修改任务的特征属性,强制保留所有水平

如果不想折腾临时数据,也可以先默认创建任务(接受空水平被删除),再手动把Var1的水平改回训练集的版本:

# 先默认创建任务(此时Var1的-1水平会被自动删除)
testtask <- makeClassifTask(data = testdata, target = "response", positive = "1")
# 获取任务的特征列表
feat_names <- getTaskFeatureNames(testtask)
# 定位Var1的位置
var1_pos <- which(feat_names == "Var1")
# 手动把任务描述里的Var1水平改回训练集的水平
testtask$task.desc$features[[var1_pos]]$levels <- levels(traindata$Var1)
# 同步更新任务数据里的Var1因子水平
testtask$env$data$Var1 <- factor(testtask$env$data$Var1, levels = levels(traindata$Var1))

这个方法直接修改任务的内部结构,需要注意mlr版本的兼容性,但绝大多数场景下都能正常工作。

补充说明

因为你测试集的response是虚拟值,这两个方法都不会影响后续的预测——毕竟预测时只需要特征和训练集对齐就行,response的虚拟值只是为了满足任务创建的格式要求。

内容的提问来源于stack exchange,提问作者mank

火山引擎 最新活动