【问题标题】:Application of XGBoost in R to data with incomplete values of a categorical variable将 XGBoost 在 R 中应用于分类变量值不完整的数据
【发布时间】:2020-01-30 17:08:03
【问题描述】:

您如何应对 XGBoost 在 R 中的应用?我有一个问题,因为当一个分类类型的数据列不包含其所有可能的值(模型考虑)时,我收到一个错误:“存储在objectnewdata 中的特色名称不同” .

我知道如何通过以不同方式准备输入数据来解决该问题,即通过添加足够数量的虚拟变量来覆盖我打算考虑的分类变量的所有可能值。例如。如果我想使用的特征 F 取值“a”、“b”或“c”,我会使用特征 is_a、is_b 和 is_c 创建一个 XGBoost 模型。然后,如果在我想要应用模型的输入数据中,特征 F 仅带有“b”或“c”值,我仍在使用这 3 个特征,每次观察时 is_c 等于 0。

但这不是我想要做的,因为总的来说它似乎很乏味,而且我在使用不同的模型时不会遇到类似的问题,例如通过 glm() 函数进行逻辑回归。

所以我的问题是:是否可以将 XGBoost 模型应用于包含不完整值的分类(因子)变量的观察? Incomplete 此处的含义:并非模型考虑的所有值。

我已经根据 mtcars 数据准备了一个示例来展示这种情况。假设我们想要一个预测变速箱类型(自动或手动,“am”列)的分类模型。可能的特征之一是权重(“wt”列),我们希望将权重数据用作因子类型特征,而不是连续类型的特征。

library(xgboost)
library(dplyr)
library(dummies)

##### Example 0: wt as a continuous variable (no errors on data with incomplete values) #####
# Train:
data_train <- mtcars
model_matrix_train <- model.matrix(am ~ ., data = data_train)
xgb_data_train <- xgb.DMatrix(model_matrix_train, label = data_train$am)
param <- list(max_depth = 2, eta = 1, objective = "binary:logistic")
model_xgb <- xgb.train(param, xgb_data_train, nrounds = 100)

# Test on data with incomplete wt values:
data_test <- mtcars %>% 
  filter(wt < 4)
model_matrix_test <- model.matrix(am ~ ., data = data_test)
xgb_data_test <- xgb.DMatrix(model_matrix_test, label = data_test$am)
predict(model_xgb, newdata = xgb_data_test, type="prob")


##### Example 1: wt as a factor (error on data with incomplete values) #####
# Train:
data_train <- mtcars %>% 
  mutate(wt = factor(
    case_when(
      wt < 2 ~ "1_2",
      wt < 3 ~ "2_3",
      wt < 4 ~ "3_4",
      wt < 5 ~ "4_5",
      TRUE ~ "5_6"
    ))
  )
model_matrix_train <- model.matrix(am ~ ., data = data_train)
xgb_data_train <- xgb.DMatrix(model_matrix_train, label = data_train$am)
param <- list(max_depth = 2, eta = 1, objective = "binary:logistic")
model_xgb <- xgb.train(param, xgb_data_train, nrounds = 100)

# Test on data with incomplete wt values:
data_test <- mtcars %>% 
  filter(wt < 4) %>% 
  mutate(wt = factor(
    case_when(
      wt < 2 ~ "1_2",
      wt < 3 ~ "2_3",
      wt < 4 ~ "3_4",
      wt < 5 ~ "4_5",
      TRUE ~ "5_6"
    ))
  )
model_matrix_test <- model.matrix(am ~ ., data = data_test)
xgb_data_test <- xgb.DMatrix(model_matrix_test, label = data_test$am)
predict(model_xgb, newdata = xgb_data_test, type="prob") # ERROR

我还尝试对 wt 的所有相关案例使用虚拟变量(而不是将 wt 转换为因子变量)。结果和上面的例子1类似:

##### Example 2: wt as a dummy variable (error on data with incomplete values) #####
# Train:
data_train <- mtcars %>% 
  mutate(wt = factor(
    case_when(
      wt < 2 ~ "1_2",
      wt < 3 ~ "2_3",
      wt < 4 ~ "3_4",
      wt < 5 ~ "4_5",
      TRUE ~ "5_6"
    ))
  )
data_train <- dummy.data.frame(data_train, "wt", sep = "_")
model_matrix_train <- model.matrix(am ~ ., data = data_train)
xgb_data_train <- xgb.DMatrix(model_matrix_train, label = data_train$am)
param <- list(max_depth = 2, eta = 1, objective = "binary:logistic")
model_xgb <- xgb.train(param, xgb_data_train, nrounds = 100)

# Test on data with incomplete wt values:
data_test <- mtcars %>% 
  filter(wt < 4) %>% 
  mutate(wt = factor(
    case_when(
      wt < 2 ~ "1_2",
      wt < 3 ~ "2_3",
      wt < 4 ~ "3_4",
      wt < 5 ~ "4_5",
      TRUE ~ "5_6"
    ))
  )
data_test <- dummy.data.frame(data_test, "wt", sep = "_")
model_matrix_test <- model.matrix(am ~ ., data = data_test)
xgb_data_test <- xgb.DMatrix(model_matrix_test, label = data_test$am)
predict(model_xgb, newdata = xgb_data_test, type="prob") # ERROR

【问题讨论】:

    标签: r machine-learning xgboost


    【解决方案1】:

    虽然输入数据中缺失特征的原因对于算法来说是合理的(不是可用的分类数据),但特征缺失是因为数据不包含因子水平还是因为数据确实不完整没有区别(缺少一项功能)。

    所以我只能为您提供一种更快的方法来编码新的输入数据以始终具有正确的特征级别:

    data_test <- mtcars %>% 
      filter(wt < 4) %>% 
      mutate(wt = factor(
        case_when(
          wt < 2 ~ "1_2",
          wt < 3 ~ "2_3",
          wt < 4 ~ "3_4",
          wt < 5 ~ "4_5",
          TRUE ~ "5_6"
        ), levels = c("1_2","2_3","3_4","4_5","5_6")) #instead of c(...) this could be variable with the stored factor levels from model creation
      )
    
    data_test <- (data_test %>% cbind(model.matrix(~ wt-1, data = .) %>% data.frame())
    

    这做了两件重要的事情:

    1. 编码因子级别

    通过在因子转换中提供级别参数,您将拥有所有相关级别。除了提供手动列表外,您始终在创建原始模型时将适当的因子水平保存为变量。

    1. 对假人使用 cbind 和 model.matrix()

    不要使用 dummy.data.frame 函数,而是使用 model.matrix(),因为它会自动编码 0 缺失因子水平。

    【讨论】:

    • 它似乎运作良好,谢谢!需要根据真实数据进行检查。
    • 它工作正常。原因是我在重新定义变量wt 时省略了level 参数。再次感谢@Fnguyen。
    • 很高兴听到它有帮助!
    猜你喜欢
    • 2020-06-17
    • 1970-01-01
    • 2016-04-24
    • 1970-01-01
    • 1970-01-01
    • 2018-03-08
    • 2021-08-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多