【问题标题】:Create branches with different subsets of data with mlr3 PipeOps使用 mlr3 PipeOps 创建具有不同数据子集的分支
【发布时间】:2020-10-01 10:53:55
【问题描述】:

我想使用 mlr3 在不同的数据子集上训练模型,我想知道是否有办法在管道中的不同数据子集上训练模型。

我想要做的类似于R for Data Science - Chapter 25: Many models 中的示例。假设我们使用相同的数据集gapminder,该数据集包含世界各国的不同变量,例如 GDP 和预期寿命。如果我想为每个国家/地区的预期寿命训练模型,有没有一种简单的方法可以使用mlr3 创建这样的管道?

理想情况下,我想使用 mlr3pipelines 在图中为每个子集创建一个分支(例如,每个国家/地区的一个单独的分支),最后一个模型。因此,最终图将从单个节点开始,并在末端节点有n 训练有素的学习者,数据集中的每个组(即国家/地区)一个,或者聚合结果的最终节点。我还希望它适用于新数据,例如,如果我们在未来获得 2020 年的新数据,我希望它能够使用针对特定国家/地区训练的模型为每个国家/地区创建预测。

我发现的所有mlr3 示例似乎都处理了整个数据集的模型,或者使用训练集中的所有组训练了模型。

目前,我只是为每组数据手动创建一个单独的任务,但将数据子集步骤合并到建模管道中会很好。

【问题讨论】:

  • 将其放入 ml-terms 中。您有一个包含一个因子列的大数据集(在您的示例中为国家/地区)。对于所述列的每个因素,您想训练一个单独的模型?请注意,此集成将因新因素而失败,并且模型不会从其他县的数据中“学习”。
  • @jakob-r 是的,这是正确的。理想情况下,我想我会有一个单独的管道来处理训练数据中不存在的因素。或者,如果我真的想进行预测,也许我可以应用一些聚类来估计最佳匹配组,以临时估算因子以用于预测目的,直到有足够的数据来训练新因子的模型。

标签: r mlr3


【解决方案1】:

如果你有这两个包中的函数会有所帮助:dplyrtidyr。以下代码向您展示了如何按国家/地区训练多个模型:

library(dplyr)
library(tidyr)

df <- gapminder::gapminder

by_country <- 
  df %>% 
  nest(data = -c(continent, country)) %>% 
  mutate(model = lapply(data, learn))

请注意,learn 是一个将单个数据帧作为其输入的函数。稍后我将向您展示如何定义该函数。现在您需要知道从该管道返回的数据帧如下:

# A tibble: 142 x 4
   country     continent data              model     
   <fct>       <fct>     <list>            <list>    
 1 Afghanistan Asia      <tibble [12 x 4]> <LrnrRgrR>
 2 Albania     Europe    <tibble [12 x 4]> <LrnrRgrR>
 3 Algeria     Africa    <tibble [12 x 4]> <LrnrRgrR>
 4 Angola      Africa    <tibble [12 x 4]> <LrnrRgrR>
 5 Argentina   Americas  <tibble [12 x 4]> <LrnrRgrR>
 6 Australia   Oceania   <tibble [12 x 4]> <LrnrRgrR>
 7 Austria     Europe    <tibble [12 x 4]> <LrnrRgrR>
 8 Bahrain     Asia      <tibble [12 x 4]> <LrnrRgrR>
 9 Bangladesh  Asia      <tibble [12 x 4]> <LrnrRgrR>
10 Belgium     Europe    <tibble [12 x 4]> <LrnrRgrR>

要定义learn 函数,我按照mlr3 网站上提供的步骤进行操作。功能是

learn <- function(df) {
  # I create a regression task as the target `lifeExp` is a numeric variable.
  task <- mlr3::TaskRegr$new(id = "gapminder", backend = df, target = "lifeExp")
  # define the learner you want to use.
  learner <- mlr3::lrn("regr.rpart")
  # train your dataset and return the trained model as an output
  learner$train(task)
}

希望这能解决你的问题。

考虑以下步骤来训练您的模型并预测每个国家/地区的结果。

create_task <- function(id, df, ratio) {
  train <- sample(nrow(df), ratio * nrow(df))
  task <- mlr3::TaskRegr$new(id = as.character(id), backend = df, target = "lifeExp")
  list(task = task, train = train, test = seq_len(nrow(df))[-train])
}

model_task <- function(learner, task_list) {
  learner$train(task_list[["task"]], row_ids = task_list[["train"]])
}

predict_result <- function(learner, task_list) {
  learner$predict(task_list[["task"]], row_ids = task_list[["test"]])
}

by_country <- 
  df %>% 
  nest(data = -c(continent, country)) %>% 
  mutate(
    task_list = Map(create_task, country, data, 0.8), 
    learner = list(mlr3::lrn("regr.rpart"))
  ) %>% 
  within({
    Map(model_task, learner, task_list)
    prediction <- Map(predict_result, learner, task_list)
  })

【讨论】:

  • 谢谢,这与我目前正在做的类似,除了data.table。在此示例中,如何使用经过训练的模型进行预测?
  • 您需要额外的设置。请参阅我上面的新帖子。 @ialm
  • 谢谢,我猜当前的管道无法启用我想要的工作流程。我最终做了类似的事情,除了data.tables 而不是tibbles,因为我的数据已经在使用data.table 进行处理。
猜你喜欢
  • 2020-07-15
  • 2021-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-18
  • 2021-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多