【问题标题】:MLR resampling creates oneclass problems for multilabel classificationMLR 重采样为多标签分类创建了一类问题
【发布时间】:2019-10-13 22:05:19
【问题描述】:

我正在尝试使用交叉验证来衡量一些 MLR 分类器的多标签分类性能

我尝试使用 MLR resample 方法或传递我自己的子集,但是在这两种情况下都会引发错误(据我发现,当用于训练的子集仅包含某个标签的单个值时会发生这种情况)

以下是出现此问题的一个小示例:

learner = mlr::makeLearner("classif.logreg")

learner = makeMultilabelClassifierChainsWrapper(learner)

data = data.frame(
    attr1 = c(1, 2, 2, 1, 2, 1, 2),
    attr2 = c(2, 1, 2, 2, 1, 2, 1),
    lab1 = c(FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE),
    lab2 = c(FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE))

task = mlr::makeMultilabelTask(data=data, target=c('lab1', 'lab2'))

这里有两种出错的方式:

1.

rDesc = makeResampleDesc("CV", iters = 3)

resample(learner, task, rDesc)

2.

model = mlr::train(learner, task, subset=c(TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE))

错误信息:

checkLearnerBeforeTrain(task, learner, weights) 中的错误:任务“lab1”是一类问题,但学习者“classif.logreg”不支持!

【问题讨论】:

  • 好吧,您要么必须使用支持单类分类的学习器,要么以一种不会在分区中得到单个类的方式拆分数据。

标签: r cross-validation multilabel-classification mlr


【解决方案1】:

由于 MLR 中没有支持一类 (https://mlr.mlr-org.com/articles/tutorial/integrated_learners.html) 分类的学习器,并且拆分数据可能需要太多麻烦(尤其是对于像 reutersk500 这样的数据集),我已经为二类学习器创建了一个包装器,如果给定具有单个目标类的任务,将始终仅返回该类的值,并且对于更多类将使用包装的学习器:

(此代码将成为存储库https://github.com/lychanl/ChainsOfClassification 的一部分)

makeOneClassWrapper = function(learner) {
    learner = checkLearner(learner, type='classif')
    id = paste("classif.oneClassWrapper", getLearnerId(learner), sep = ".")
    packs = getLearnerPackages(learner)
    type = getLearnerType(learner)
    x = mlr::makeBaseWrapper(id, type, learner, packs, makeParamSet(),
        learner.subclass = c("OneClassWrapper"),
        model.subclass = c("OneClassWrapperModel"))
    x$type = "classif"
    x$properties = c(learner$properties, 'oneclass')
    return(x)
}

trainLearner.OneClassWrapper = function(.learner, .task, .subset = NULL, .weights = NULL, ...) {
    if (length(getTaskDesc(.task)$class.levels) <= 1) {
        x = list(oneclass=TRUE, value=.task$task.desc$positive)
        class(x) = "OneClassWrapperModel"
        return(makeChainModel(next.model = x, cl = c(.learner$model.subclass)))
    }

    model = train(.learner$next.learner, .task, .subset, .weights)

    x = list(oneclass=FALSE, model=model)
    class(x) = "OneClassWrapperModel"
    return(makeChainModel(next.model = x, cl = c(.learner$model.subclass)))
}

predictLearner.OneClassWrapper = function(.learner, .model, .newdata, ...) {
    .model = mlr::getLearnerModel(.model, more.unwrap = FALSE)

    if (.model$oneclass) {
        out = as.logical(rep(.model$value, nrow(.newdata)))
    }
    else {
        pred = predict(.model$model, newdata=.newdata)

        if (.learner$predict.type == "response") {
            out = getPredictionResponse(pred)
        } else {
            out = getPredictionProbabilities(pred, cl="TRUE")
        }
    }

    return(as.factor(out))
}

getLearnerProperties.OneClassWrapper = function(.learner) {
    return(.learner$properties)
}

isFailureModel.OneClassWrapperModel = function(model) {
    model = mlr::getLearnerModel(model, more.unwrap = FALSE)

  return(!model$oneclass && isFailureModel(model$model))
}

getFailureModelMsg.OneClassWrapperModel = function(model) {
    model = mlr::getLearnerModel(model, more.unwrap = FALSE)
  if (model$oneclass)
      return("")
  return(getFailureModelMsg(model$model))
}

getFailureModelDump.OneClassWrapperModel = function(model) {
    model = mlr::getLearnerModel(model, more.unwrap = FALSE)
  if (model$oneclass)
      return("")
  return(getFailureModelDump(model$model))
}

registerS3method("trainLearner", "<OneClassWrapper>", 
  trainLearner.OneClassWrapper)
registerS3method("getLearnerProperties", "<OneClassWrapper>", 
  getLearnerProperties.OneClassWrapper)
registerS3method("isFailureModel", "<OneClassWrapperModel>", 
  isFailureModel.OneClassWrapperModel)
registerS3method("getFailureModelMsg", "<OneClassWrapperModel>", 
  getFailureModelMsg.OneClassWrapperModel)
registerS3method("getFailureModelDump", "<OneClassWrapperModel>", 
  getFailureModelDump.OneClassWrapperModel)

【讨论】:

  • 看起来很棒!您愿意将其作为拉取请求贡献给 mlr 吗?
  • 很有可能,什么时候我会找到时间这样做
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-07
  • 2023-01-29
  • 2017-11-08
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 2021-12-06
相关资源
最近更新 更多