【问题标题】:How to handle errors in predict function of R?如何处理 R 的预测函数中的错误?
【发布时间】:2016-10-04 20:55:41
【问题描述】:

我有一个数据框 df,我正在构建一个机器学习模型(C5.0 决策树)来预测列的类别(loan_approved):

结构(非真实数据):

id occupation income  loan_approved
1  business   4214214 yes
2  business   32134   yes
3  business   43255   no
4  sailor     5642    yes
5  teacher    53335   no
6  teacher    6342    no

流程:

  • 我将数据帧随机拆分为test和train,在train上学习 数据集(第 1、2、3、5、6 行训练,第 4 行作为测试)
  • 为了在一个或多个列中考虑新的分类级别,我使用了 try 函数

功能:

    error_free_predict = function(x){
    output = tryCatch({
    predict(C50_model, newdata = test[x,], type = "class")
    }, error = function(e) {
    "no"
    })
    return(output)
    }

应用了预测功能:

test <- mutate(test, predicted_class = error_free_predict(1:NROW(test)))

问题:

id occupation income loan_approved predicted_class
1  business   4214214 yes          no
2  business   32134   yes          no
3  business   43255   no           no
4  sailor     5642    yes          no
5  teacher    53335   no           no
6  teacher    6342    no           no

问题:

我知道这是因为测试数据框有一个新级别,而火车数据中不存在,但我的函数不应该在除此之外的所有情况下都有效吗?

P.S: 没有用 sapply 因为太慢了

【问题讨论】:

  • 您的实际问题是什么?是不是只返回“不”? predict 调用返回的错误是什么?
  • 问题在于预测函数在“职业”列中遇到了新的因子水平,并且不仅针对这一行失败,而且将整个数据帧视为失败案例
  • 听起来您应该对拆分进行分层,以便每个拆分中每个类别的数量大致相同。
  • @Aaron: 我打算在生产中使用它,我可能会看到至少一个新职业/级别的记录

标签: r try-catch predict


【解决方案1】:

这个问题有两个部分。

  1. 问题的第一部分出现在模型训练期间,因为如果进行随机拆分,分类变量在训练和测试之间的分配不均等。在您的情况下,假设您只有一个职业“水手”的记录,那么当您进行随机拆分时,它可能最终会出现在测试集中。使用火车数据集构建的模型永远不会看到职业“水手”的影响,因此会引发错误。在更一般的情况下,其他一些分类变量级别可能会在随机拆分后完全进入测试集。

因此,您可以进行分层抽样,而不是在训练和测试之间随机划分数据。使用 data.table 进行 70:30 拆分的代码是:

ind <- total_data[, sample(.I, round(0.3*.N), FALSE),by="occupation"]$V1
train <- total_data[-ind,]
test <- total_data[ind,]

这可确保任何级别在训练和测试数据集中均等分配。因此,您不会在测试数据集中获得“新”分类级别;在随机分裂的情况下可能存在。

  1. 问题的第二部分出现在模型在生产中时,它遇到了一个全新的变量,该变量甚至在训练或测试集中都不存在。为了解决这个问题,可以使用以下方法维护所有类别变量的所有级别的列表 lvl_cat_var1 &lt;- unique(cat_var1)lvl_cat_var2 &lt;- unique(cat_var2) 等。然后在预测之前可以检查新级别并过滤:

    new_lvl_data <- total_data[!(var1 %in% lvl_cat_var1 & var2 %in% lvl_cat_var2)] 
    pred_data <- total_data[(var1 %in% lvl_cat_var1 & var2 %in% lvl_cat_var2)] 
    

那么对于默认预测执行:

new_lvl_data$predicted_class <- "no" 

以及对 pred_data 的全面预测。

【讨论】:

  • 您可以使用lvl_cat_var1 &lt;- unique(cat_var1) lvl_cat_var2 &lt;- unique(cat_var2) 维护所有类别变量的所有级别的列表,然后在预测之前检查新级别并过滤new_lvl_data &lt;- total_data[!(var1 %in% lvl_cat_var1 &amp; var2 %in% lvl_cat_var2)]pred_data &lt;- total_data[(var1 %in% lvl_cat_var1 &amp; var2 %in% lvl_cat_var2)] 然后执行@ 987654331@ 和pred_data 的全面预测
  • 将此作为您的答案,我很乐意接受!
  • @agenis:OP 希望新级别的记录被归类为默认类。我只是选择了“否”作为例子。没有更多的含义。
  • @abhiieor: ind &lt;- total_data[, sample(.I, round(0.3*.N), FALSE),by="occupation"]$V1 你能解释一下这个命令吗?,我收到一个错误。关于 .I 和 .N 等的更多信息。
  • 这就是data.table的采样语法。 .I 给出当前行号和 .N 总行数。
【解决方案2】:

我通常使用循环来执行此操作,其中火车之外的任何级别都会被此函数重新编码为 NA。这里的 train 是您用于训练模型的数据,而 test 是用于预测的数据。

for(i in 1:ncol(train)){
  if(is.factor(train[,i])){
    test[,i] <- factor(test[,i],levels=levels(train[,i]))
  }
}

Trycatch 是一种错误处理机制,即在遇到错误之后。除非您想在遇到错误后做一些不同的事情,否则它将不适用。但是你仍然想运行模型,然后这个循环会处理新的关卡。

【讨论】:

  • 感谢您的回答,但您不认为,for 循环或任何与此相关的循环都会非常慢。这是一个令人担忧的问题,因为我正在考虑使其成为生产级!
  • 这里的For循环只是为了去除因子水平。就性能而言,这根本不重要。
猜你喜欢
  • 1970-01-01
  • 2015-08-16
  • 2021-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-08
  • 2023-03-27
  • 1970-01-01
相关资源
最近更新 更多