Введение в пакет

Соавтором этого сообщения является Шимон Максимюк.

В течение нескольких месяцев мы работали над пакетом R treeshap - быстрым методом вычисления значений SHAP для моделей ансамбля деревьев. Пакет еще не полностью разработан, но он уже может вычислять объяснения для ряда моделей, включая XGBoost, LightGBM, gbm, ranger и _6 _, (_ 7_ в планах на ближайшее будущее) и представлять результаты с различными функциями построения графиков. Недавно мы добавили возможность расчета значений взаимодействия SHAP. Поскольку мы думаем, что пакет может выйти из ранней стадии разработки, мы хотим представить нашу работу более широкой аудитории.

Что такое значения SHAP?

SHAP расшифровывается как Shapley Additive Explanations - метод объяснения предсказаний модели, основанных на значениях Шепли из теории игр.
Мы рассматриваем функции как игроков в кооперативной игре (игроки формируют коалиции, которые затем могут получить некоторую выплату в зависимости от «силы» команды), где прогноз является выплатой. Мы стараемся справедливо разделить выплату между игроками. Доказано, что ценности Шепли - единственное справедливое распределение, где справедливое означает, что оно удовлетворяет некоторым важным аксиомам.

Таким образом, с помощью SHAP мы объясняем, насколько каждая функция влияет на ценность одного прогноза. Чтобы быть более точным, мы объясняем, насколько это способствует отклонению от среднего прогноза выбранного набора справочных данных. Далее в блоге вы увидите пример такого объяснения.

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

Если вы хотите узнать больше о значениях SHAP, мы рекомендуем прочитать посвященную им главу в одной из этих книг: Анализ объяснительной модели или Интерпретируемое машинное обучение.

Основным преимуществом значений SHAP по сравнению с другими методами является стоящая за ними солидная теория.
Мы можем вычислить значения SHAP для любой модели с нулевым знанием структуры модели, и в таком общем случае вычислительная сложность будет экспоненциальной. Таким образом, время вычислений, безусловно, было бы самым большим недостатком, но есть TreeSHAP ...

Как работает TreeSHAP?

TreeSHAP - это алгоритм для вычисления значений SHAP для моделей ансамбля деревьев, таких как деревья решений, случайные леса и деревья с градиентным усилением, за полиномиальное время, предложенный Lundberg et. al (2018) ¹.

Алгоритм позволяет снизить сложность с O(TL2^M) до O(TLD^2) (T = количество деревьев в модели, L = максимальное количество листьев в дереве, D = максимальная глубина дерева, M = количество объясненных функций). Мы можем сделать это благодаря структуре моделей на основе деревьев и свойствам значений Шепли, в основном аддитивности (это означает, что значение SHAP для модели, являющейся лесом, представляет собой сумму значений SHAP для всех ее деревьев).
Чтобы еще больше гарантировать быструю работу нашего метода, пакет R treeshap интегрирует реализацию алгоритма на C ++.

TreeSHAP изначально был реализован как часть пакета Python shap (ссылка на GitHub).
В прошлом, MI2DataLab, мы разработали оболочку R для этой библиотеки - shapper, но это менее стабильное и удобное решение, чем отдельный пакет.

treeshap работает по скорости, сравнимой с вышеупомянутой библиотекой Python. Здесь мы можем испортить то, что в будущем мы будем работать над улучшением сложности до O(TLD), что может позволить treeshap превзойти shap. Пакет также реализует другие функции, такие как различные функции построения графиков.

Теперь давайте посмотрим на пример, показывающий, как его использовать.

Как им пользоваться?

Давайте теперь проверим, как это работает на практике. В наших примерах мы будем использовать набор данных apartments, который доступен в пакете DALEX. Он содержит искусственно созданную информацию о квартирах в Варшаве. В настоящее время treeshap не работает с факторными функциями, поэтому мы сразу же кодируем их с помощью функции из пакета mlr.

library(treeshap)
aps_data <- mlr::createDummyFeatures(DALEX::apartments)

Как упоминалось выше, пакет treeshap работает для различных моделей ансамбля деревьев, однако для целей сегодняшних примеров мы будем использовать реализацию случайного леса из пакета ranger для оценки стоимости квадратного метра квартиры.

model <- ranger::ranger(m2.price ~ ., data = aps_data)

Начать надо с унификации модели. Эта операция изменяет объект модели ансамбля деревьев в форму, понятную treeshap. Эта унифицированная форма позволяет плавно вычислять значения Шепли. Унифицированную форму также легче интерпретировать пользователем, и ее можно использовать для прогнозирования с помощью функции predict. Требуется передать данные вместе с набором данных, для которого мы хотим вычислить значения Шепли. Имейте в виду, что сейчас treeshap работает только для числовых значений функций. Перед обучением модели необходимо закодировать категориальные переменные.

model_unified <- ranger.unify(model, aps_data)

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

unified2 <- set_reference_dataset(model_unified, aps_data[1:2000, ])

Имея на плате унифицированную модель, мы теперь можем вычислять значения SHAP. Доступ к необработанным значениям SHAP в форме фрейма данных можно получить как элемент$shaps объекта результата.

treeshap_res <- treeshap(model_unified, aps_data[1:500, ])
treeshap_res$shaps

Значения SHAP можно использовать для объяснения вклада функций в прогноз для одного наблюдения.

plot_contribution(treeshap_res, obs = 234, min_max = c(3400, 4200))

plot_contribution(treeshap_res, obs = 235, min_max = c(2500, 3600))

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

plot_feature_importance(treeshap_res, max_vars = 8)

Здесь мы видим, что расположение квартиры в Средместье, центре Варшавы, имеет огромное влияние на цену. Между ним и другими районами большой разрыв. Ródmieście является очень предпочтительным, и отсюда разница. Вторая по важности особенность - это поверхность. Мы можем профилировать переменную, чтобы узнать о ней больше.

plot_feature_dependence(treeshap_res, 'surface')

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

Взаимодействия

Значения взаимодействия SHAP - это просто значения SHAP для взаимодействий двух функций. Расчет их не сильно отличается от стандартных значений Шепли. Для этого требуется всего лишь установить interactionsparameter в функции treehap, и вы сможете наслаждаться новыми взаимодействиями без расчетного времени в 2 года.

inter <- treeshap(model_unified, aps_data[1:500,], interactions = T)

Вычисление взаимодействий может занять несколько минут, но это все равно очень быстро, и мы можем отслеживать прогресс по индикатору выполнения. Необработанные значения взаимодействия SHAP в форме массива доступны как $interactionselement объекта результата. Массив представляет собой матрицу размером M на M для каждого наблюдения. Более того, мы можем визуализировать эти взаимодействия! Разве это не потрясающе?

plot_interaction(treeshap_interactions, 'surface', 'no.rooms')

Попробуй сам!

treeshap доступен на гитхабе.

Вы можете установить последнюю версию с помощью devtools:

devtools::install_github('ModelOriented/treeshap')

Если вас интересуют другие сообщения об объяснимом, справедливом и ответственном машинном обучении, подписывайтесь на #ResponsibleML на Medium.

Чтобы увидеть больше материалов, связанных с R, посетите https://www.r-bloggers.com

  1. Лундберг, Скотт М., Габриэль Г. Эрион и Су-Ин Ли. «Последовательная индивидуальная атрибуция признаков для ансамблей деревьев». Препринт arXiv arXiv: 1802.03888 (2018)