Построение переменной важности из множества моделей с циклом for - PullRequest
0 голосов
/ 03 июня 2019

Я продолжаю сталкиваться с ошибкой при попытке построить значение переменной из ансамбля моделей.

У меня есть ансамбль моделей, которые я подогнал, и сейчас я пытаюсь создать несколько графиков значения переменной для каждого алгоритма Iприспособил.Я использую varImp() функцию из каретки, чтобы извлечь значение переменной, затем plot() это.Чтобы соответствовать ансамблю моделей, я использую пакет caretEnsemble.

Спасибо за любую помощь, см. Пример кода ниже.

# Caret ensemble is needed to produce list of models
library(caret)
library(caretEnsemble)

# Set algorithms I wish to fit
my_algorithms <- c("glmnet", "svmRadial", "rf", "nnet", "knn", "rpart")

# Define controls
my_controls <- trainControl(
  method = "cv",
  savePredictions = "final",
  number = 3
)

# Run the models all at once with caretEnsemble
my_list_of_models <- caretEnsemble::caretList(Species ~ .,
                                 data = iris,
                                 trControl = my_controls,
                                 methodList = my_algorithms)
# Subset models
list_of_algorithms <- my_list_of_models[my_algorithms]

# Create first for loop to extract variable importance via caret::varImp()
importance <- list()
for (algo in seq_along(list_of_algorithms)) {
  importance[[algo]] <- varImp(list_of_algorithms[[algo]])
}

# Create second loop to go over extracted importance and plot it using plot()
importance_plots <- list()
for (imp in seq_along(importance)) {
  importance_plots[[imp]] <- plot(importance[[imp]])
}

# Error occurs during the second for loop:
Error in data.frame(values = unlist(unname(x)), ind, stringsAsFactors = FALSE):arguments imply differing number of rows: 16, 

1 Ответ

1 голос
/ 06 июня 2019

Я пришел к решению проблемы выше и решил опубликовать его в качестве своего собственного ответа.Я написал небольшую функцию для отображения важности переменных, не полагаясь на вспомогательные функции caret для создания графиков.Я использовал dotplot и levelplot, потому что caret возвращает data.frame, который отличается в зависимости от предоставленного алгоритма.Он может не работать на разных алгоритмах и моделях, которые не подходят.

# Libraries ---------------------------------------------------------------
library(caret) # To train ML algorithms
library(dplyr) # Required for %>% operators in custom function below
library(caretEnsemble) # To train multiple caret models
library(lattice) # Required for plotting, should be loaded alongside caret
library(gridExtra) # Required for plotting multiple plots

# Custom function ---------------------------------------------------------
# The function requires list of models as input and is used in for loop 
plot_importance <- function(importance_list, imp, algo_names) {
  importance <- importance_list[[imp]]$importance
  model_title <- algo_names[[imp]]
  if (ncol(importance) < 2) { # Plot dotplot if dim is ncol < 2
    importance %>%
      as.matrix() %>%
      dotplot(main = model_title)
  } else { # Plot heatmap if ncol > 2
    importance %>%
      as.matrix() %>%
      levelplot(xlab = NULL, ylab = NULL, main = model_title, scales = list(x = list(rot = 45)))
  }
}

# Tuning parameters -------------------------------------------------------
# Set algorithms I wish to fit
# Rather than using methodList as provided above, I've switched to tuneList because I need to control tuning parameters of random forest algorithm.

my_algorithms <- list(
  glmnet = caretModelSpec(method = "glmnet"),
  rpart = caretModelSpec(method = "rpart"),
  svmRadial = caretModelSpec(method = "svmRadial"),
  rf = caretModelSpec(method = "rf", importance = TRUE), # Importance is not computed for "rf" by default
  nnet = caretModelSpec(method = "nnet"),
  knn = caretModelSpec(method = "knn")
)

# Define controls
my_controls <- trainControl(
  method = "cv",
  savePredictions = "final",
  number = 3
)

# Run the models all at once with caretEnsemble
my_list_of_models <- caretList(Species ~ .,
  data = iris,
  tuneList = my_algorithms,
  trControl = my_controls
)

# Extract variable importance ---------------------------------------------
importance <- lapply(my_list_of_models, varImp)

# Plotting variable immportance -------------------------------------------
# Create second loop to go over extracted importance and plot it using plot()
importance_plots <- list()
for (imp in seq_along(importance)) {
  # importance_plots[[imp]] <- plot(importance[[imp]])
  importance_plots[[imp]] <- plot_importance(importance_list = importance, imp = imp, algo_names = names(my_list_of_models))
}

# Multiple plots at once
do.call("grid.arrange", c(importance_plots))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...