Чтобы получить лучшее (и более существенное) понимание черных ящиков моделей, графики разбивки чрезвычайно полезны и интуитивно понятны. Пакет {фонарик} упрощает создание этих графиков, но у него есть один недостаток: не интуитивно понятно, как настроить метки ваших объектов (по крайней мере, я не нашел простого ответа). В этом посте показан обходной путь, который я использовал, и я надеюсь, что он поможет другим сэкономить время на поиске решения в Google.

Я буду использовать набор данных Палмера, чтобы показать свои шаги.

# Load the packages
library(flashlight)     # Shed Light on Black Box ML Models
library(palmerpenguins) # Palmer Archipelago Penguin Data
library(dplyr)          # A Grammar of Data Manipulation
library(magrittr)       # A Forward-Pipe Operator for R
library(ggplot2)        # Create Elegant Data Visualizations Using 
                        # the Grammar of Graphics
# Load the data
data("penguins")

Подробное описание работы {фонарика} и графики разбивки можно прочитать здесь. Я буду использовать аналогичный пример, представленный в руководстве. На первом этапе я покажу вам результат общего графика разбивки.

Код для создания графика разбивки

# Fit model
fit <- lm(bill_length_mm ~ ., data = penguins)
# Make flashlight
fl <-
  flashlight(
    model = fit,
    data = penguins,
    y = "bill_length_mm",
    label = "ols",
    metrics = list(rmse = MetricsWeighted::rmse, 
                   `R-squared` = MetricsWeighted::r_squared)
  )
# Plot the breakdown plot
plot(light_breakdown(fl, new_obs = penguins[3, ], digits = 2))

На графике показаны вклады отдельных переменных (или функций). Иными словами, он визуализирует, какой вклад в прогноз вносит каждая отдельная переменная. Он начинается со среднего значения зависимой переменной (или target) в данных. Значение 44 указывает на то, что средняя длина клюва пингвинов в данных составляет 44 мм. Красные столбцы показывают отрицательный вклад, а синие столбцы — положительный вклад (также обозначаемый знаком перед значением переменной). Это означает, что если пингвин относится к виду Адели, длина клюва короче, тогда как большая глубина клюва (здесь 18 мм) с большей вероятностью будет способствовать увеличению длины клюва. Порядок переменных отсортирован по размеру вклада. Это означает, что переменные с большим вкладом идут первыми, а переменные с меньшим вкладом — наименее.

Хотя эта цифра уже говорит о многом, она еще не готова к публикации. Чтобы сделать внешний вид визуально более привлекательным, мы хотели бы настроить метки так, чтобы они были легко читаемыми, и, возможно, также изменить некоторые другие эстетические аспекты.

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

Подробнее о выводе, произведенном light_breakdown

light_breakdown(fl, new_obs = penguins[3, ], digits = 2)
I am an object with class(es) light_breakdown, light, list
data.frames (maximum 6 rows shown):
data 
# A tibble: 6 x 6
   step variable          after before label description                   
  <int> <chr>             <dbl>  <dbl> <chr> <chr>                         
1     0 baseline           44.0   44.0 ols   average in data: 44           
2     1 species            39.7   44.0 ols   species = Adelie: -4.3        
3     2 sex                38.6   39.7 ols   sex = female: -1              
4     3 body_mass_g        37.5   38.6 ols   body_mass_g = 3250: -1.1      
5     4 flipper_length_mm  37.2   37.5 ols   flipper_length_mm = 195: -0.34
6     5 bill_depth_mm      37.5   37.2 ols   bill_depth_mm = 18: +0.28

Все, что хранится в description, позже будет нанесено на ваш график в виде меток.

Чтобы получить осмысленные метки, я перекодирую значения переменных (здесь для sex я хочу видеть «женщина» вместо «женщина») и имена переменных (например, переменная bill_length_mm неудобна для чтения, а Length of bill (in mm) — легко читается).

penguins %<>%
  # First adjust the labels
   dplyr::mutate(
    sex = case_when(sex == "female" ~ "Female",
                    sex == "male" ~ "Male")) %>% 
  dplyr::rename(
    `Penguin species` = species,
    `Island` = island,
    `Length of bill (in mm)` = bill_length_mm,
    `Depth of bill (in mm)` = bill_depth_mm,
    `Length of flipper (in mm)` = flipper_length_mm,
    `Body mass (in g)` = body_mass_g,
    `Sex` = sex,
    `Year` = year)

И все готово. Теперь снова подгоним модель и сгенерируем фонарик.

# Fit model
fit <- lm(`Length of bill (in mm)` ~ ., data = penguins)
# Make flashlight
fl <-
  flashlight(
    model = fit,
    data = penguins,
    y = "Length of bill (in mm)",
    label = "ols",
    metrics = list(rmse = MetricsWeighted::rmse, 
                   `R-squared` = MetricsWeighted::r_squared)
  )

Мы можем использовать объект фонарика fl и построить график разбивки.

plot(light_breakdown(fl, new_obs = penguins[3,], digits = 2)) +
  theme_classic() +
  theme(
    axis.text.y = element_blank(),
    axis.ticks.y = element_blank(),
    axis.title.y = element_blank()
  ) +
  scale_fill_grey()

theme(), theme_classic() и scale_fill_grey() являются дополнительными корректировками, чтобы рисунок можно было опубликовать в более поздней рукописи, но есть бесконечные возможности, и вы можете выбрать то, что лучше для вас.

Первоначально опубликовано на https://cosimameyer.rbind.io 18 апреля 2021 г.