Применение XGBoost в R к данным с неполными значениями категориальной переменной - PullRequest
0 голосов
/ 01 октября 2019

Как вы справляетесь с применением XGBoost в R? У меня проблема с этим, так как, когда столбец данных категориального типа не содержит всех своих возможных значений (которые учитывает модель), я получаю сообщение об ошибке: «Избранные имена, хранящиеся в object и newdata, отличаются».

Я знаю, как обойти эту проблему, подготавливая входные данные другим способом, то есть путем добавления достаточного количества фиктивных переменных, чтобы охватить все возможные значения категориальных переменных, которые я намерен учитывать. Например, если объект FI, который требуется использовать, принимает значения «a», «b» или «c», я создаю модель XGBoost, используя функции is_a, is_b и is_c. Затем, если в моих входных данных, к которым я хочу применить модель, функция F поставляется только со значениями 'b' или 'c', я все еще использую эти 3 функции, и is_c равен 0 при каждом наблюдении.

Но я не хочу этого делать, так как в целом это кажется довольно утомительным, и, кроме того, я не сталкиваюсь с подобными проблемами при использовании разных моделей, например, логистической регрессии с помощью функции glm ().

Итак, мой вопрос: возможно ли применить модель XGBoost к наблюдениям, содержащим категориальные (факторные) переменные с неполными значениями? Incomplete значение здесь: не все значения, которые учитывает модель.

Я подготовил пример для демонстрации этого случая на основе данных mtcars. Допустим, мы хотим иметь классификационную модель, предсказывающую тип коробки передач (автоматическая или ручная, столбец «am»). Одна из возможных функций - это вес (столбец «вес»), и мы хотим использовать данные о весе в качестве признака типа фактора, а не признака непрерывного типа.

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

1 Ответ

0 голосов
/ 01 октября 2019

Несмотря на то, что причина отсутствующего признака во входных данных является разумной (недоступные категориальные данные) для алгоритма, не имеет значения, пропущен ли признак, поскольку данные не содержат уровень фактора или данные действительно неполны(отсутствует функция).

Так что я могу только предложить вам более быстрый способ кодирования новых входных данных, чтобы всегда иметь нужные уровни функций:

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. Кодирование уровней факторов

Предоставляя аргумент уровней в преобразовании факторов, вы получите все соответствующие уровни. Помимо предоставления списка вручную, вы всегда сохраняете соответствующие уровни факторов в качестве переменной при создании исходной модели.

Используйте cbind и model.matrix () для манекенов

Вместо использования функции dummy.data.frame используйте model.matrix (), поскольку она будет автоматически кодировать 0 для отсутствующих уровней факторов.

...