Новый взгляд на ценности Шепли: наивный метод Шепли

Узнайте больше о SHAP, исследуя концептуальную альтернативу.

** EDIT, январь 2020 г .: Я переименовал представленный здесь метод в Naive Shapley из менее интуитивно понятного Radical Shapley. Это было изменено на протяжении всего сообщения, но фрагменты кода и репозиторий git могут по-прежнему отражать старое имя. **

Зачем вам читать этот пост?

  • Чтобы получить представление о ценностях Шепли и инструменте SHAP. Большинство других источников по этим темам представляют собой объяснения, основанные на существующих первичных источниках (например, академических статьях и документации SHAP). Этот пост представляет собой попытку получить некоторое понимание с помощью эмпирического подхода.
  • Чтобы узнать об альтернативном подходе к вычислению значений Шепли, который при некоторых (ограниченных) обстоятельствах может быть предпочтительнее, чем SHAP (или дождитесь следующей публикации для более широко применимой идеи).

Если вы не знакомы со значениями Shaply или SHAP или хотите вкратце описать, как работают объяснители SHAP, прочтите этот пост.

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

Более многословное введение

Мой интерес к ценностям Шепли возник, когда я использовал библиотеку SHAP во время недавнего хакатона, чтобы объяснить предсказания модели Isolation Forest. Я заметил, что для нашей модели вычисление SHAP показалось довольно неэффективным и занимало слишком много времени для выполнения для всего набора данных. Фактически, так долго, что я задавался вопросом, действительно ли в данном случае грубая сила, экспоненциально-сложный подход к ценностям Шепли был лучшим вариантом. Это побудило меня написать функцию, которая вычисляет значения Шепли, используя подход, который мне показался интуитивно понятным: вместо моделирования отсутствующих функций путем интегрирования их возможных значений (как в методе SHAP) их можно полностью удалить из модели. во время тренировки. Из-за отсутствия существующего термина в литературе я решил назвать их Наивными значениями Шепли в том смысле, что они основаны только на наборе данных (плюс класс модели), а не на обученной модели. .

Одна вещь, которую я усвоил, будучи аспирантом-неврологом, заключается в том, что если вы хотите понять свои инструменты анализа и доверять им, вам необходимо подвергнуть их тщательному эмпирическому изучению, как если бы они были вашим реальным объектом исследования. Чтение существующей литературы важно, как и получение практического опыта, но я считаю, что реальное понимание приходит не в том случае, если результаты инструмента не воспринимаются как должное, а в том, чтобы тестировать их в сравнении с искусственными крайними случаями или другими методами. Основная идея этого поста состоит в том, чтобы лучше понять преимущества и ограничения объяснителей SHAP, сравнив их с наивным подходом Шепли.

Код функции Шепли и примеры, использованные в этом посте, доступны здесь.

Наброски (не совсем тл; др)

В этом посте я постараюсь показать следующее:

  • Наивные значения Шепли можно вычислить для небольшого количества функций путем повторного обучения модели для каждого из 2ᴹ подмножеств функций (где M - количество функций).
  • Объяснения библиотеки SHAP и наивный метод Шепли обеспечивают две разные интерпретации значений Шепли. Первый лучше всего подходит для объяснения индивидуальных прогнозов для данной (обученной) модели, а второй лучше подходит для объяснения важности функций. для набора данных и модели класс (например, случайный лес, инициализированный определенными параметрами, но не обученный случайный лес).
  • При некоторых (ограниченных) обстоятельствах вычисление Наивного Шепли может быть быстрее, чем метод SHAP. Эти обстоятельства в целом имеют место, когда выполняются все следующие условия: a. небольшое число функций (‹~ 15), б. с использованием модели, которая не поддерживается эффективными объяснителями SHAP, и c. значения Shapley требуются для большого количества выборок (например, для всего набора данных).

В одном из будущих постов я надеюсь обсудить более практичную, полиномиально-сложную альтернативу оценки наивных значений Шепли с помощью выборки.

Так что же такое «наивные» ценности Шепли?

Во-первых, что такое значение Шепли? Если у вас есть команда людей, каждый из которых вносит свой вклад в общий выигрыш, но чей вклад не обязательно является независимым (например, вклад менеджера группы зависит также от наличия сотрудников), то значение Шепли количественно определяет вклад каждого из них в общий выигрыш как средневзвешенное значение их предельного вклада по всем возможным командам (так, вклад нашего менеджера команды может быть 0 без дополнительных работников, 100 с хотя бы одним работником и т. д., и это среднее значение по всем возможным перестановкам в команде). Говоря техническим языком, значение Шепли отражает ожидаемую величину дополнительного выигрыша, полученного при добавлении игрока в коалицию, во всех возможных коалициях, не включающих игрока.

В сфере статистических моделей значения Шепли количественно определяют разницу в прогнозе модели, основанную на добавлении каждой функции в модель. Однако, поскольку такие модели обычно не могут обрабатывать неполные входные данные, невозможно просто удалить объект из набора данных, чтобы вычислить его предельный вклад. Поэтому реализация концепции значений Шепли для объяснения моделей прогнозирования требует некоторой интерпретации. Конкретно,

  • Специалисты по объяснению SHAP интерпретируют «добавление функции» с точки зрения того, что она имеет определенное значение по сравнению с тем, что ее значение неизвестно для данной выборки на этапе прогнозирования. Например, предельный вклад «Возраст = 30» в результат модели, прогнозирующей уровень дохода людей, может быть вычислен относительно среднего прогнозируемого уровня дохода при замене других возможных значений «Возраст» из набора данных. С другой стороны,
  • Наивный метод Шепли основан на альтернативной интуиции измерения влияния функции по отношению к ее отсутствию в модели во время обучения. Таким образом, вклад «Возраст = 30» в нашем примере будет относиться к случаю, когда модель изначально обучалась без функции возраста вообще.

Обе интерпретации согласуются с математическим понятием значений Шепли, но измеряют несколько разные вещи.

Вычисление наивных ценностей Шепли

Функция для вычисления наивных значений Шепли (код здесь) принимает набор данных и функцию выигрыша и вычисляет выигрыш для каждой возможной комбинации характеристик (или коалиции игроков). Затем значения Шепли вычисляются по стандартной формуле Шепли:

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

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

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

Основным недостатком этого алгоритма является его вычислительная сложность - его нужно запускать 2ᴹ раза (где M - количество функций), каждый раз повторно обучая модель. Эта сложность, конечно же, является основной причиной необходимости библиотеки SHAP; с другой стороны, при некоторых ограниченных обстоятельствах это может быть более быстрым вариантом, чем использование объяснителя ядра SHAP. Вопрос о сравнительном времени работы рассматривается в конце этого сообщения.

Чем это отличается от SHAP и почему это должно нас волновать?

Я сравнил результаты наивного метода Шепли как с SHAP KernelExplainer, так и с TreeExplainer. Я не стал сравнивать с DeepExplainer, поскольку модели нейронных сетей редко имеют небольшое количество входных переменных, из-за чего сравнение актуально. Вкратце: наивный метод Шепли концептуально отличается от всех объяснителей SHAP тем, что представляет вклад функций в саму модель, а не в отдельные прогнозы; в то же время он обычно медленнее (и непрактичен для более чем небольшого числа функций), хотя в некоторых случаях может быть более эффективным, чем KernelExplainer. Еще раз, этот пост может помочь вам, если вы не уверены в том, что делают объяснители SHAP.

Наивные ценности Шепли против TreeExplainer

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

Мы можем продемонстрировать значимость этой разницы на простом искусственном примере. Давайте сгенерируем модель линейной регрессии с тремя характеристиками, с одной характеристикой x1, которая является сильным предиктором y, и второй характеристикой x2, которая строго коррелировал с ним (и поэтому с меньшей вероятностью y), и третья функция, не являющаяся прогнозирующей, x3:

Чтобы получить наивные значения Шепли, нам нужно сначала определить функцию выигрыша, которая просто обучает модель и возвращает ее прогнозы (для простоты я не включаю никакого разделения на обучение и проверку и т. Д.).

А теперь запустите саму функцию Shapley (reshape_shapley_output просто переупорядочивает исходный вывод, поскольку compute_shapley_values ​​ возвращает словарь, который не предполагает конкретный формат выплаты. Объяснение функции ввод и вывод осуществляется на гитхабе.

Чтобы получить значения SHAP, мы определим модель регрессора XGB, обучим ее и вычислим значения SHAP с помощью TreeExplainer:

Теперь давайте посмотрим, как значения SHAP и значения Naive Shapley соотносятся друг с другом. Мы будем использовать изящный инструмент визуализации summary_plot библиотеки SHAP, который отображает распределение значений Шепли для каждой функции:

Давайте разберем это:

  • С помощью TreeExplainer модель уже обучена всем 3 функциям, поэтому значения SHAP отражают тот факт, что x1 оказывает наибольшее влияние на обученную модель, а x2 играет гораздо меньшую роль, поскольку в основном избыточен.
  • С другой стороны, с наивным методом Шепли влияние x2 на y почти такое же большое, как x1, потому что когда модель обучается без x1, x2 почти так же информативен.
  • В то же время непредсказуемому x3 приписывают более высокий эффект при использовании наивного метода Шепли - просто потому, что, тем более, что мы не делали разделения обучения / проверки, он может чрезмерно соответствовать данные в отсутствие лучших предикторов.

А теперь давайте рассмотрим реальный пример. Мы рассмотрим значения Шепли для одного из наборов данных, включенных в библиотеку SHAP - базы данных переписи взрослого населения, с 12 демографическими характеристиками, которые используются для прогнозирования того, составляет ли доход человека ›50 тыс. $ (Загрузите с помощью shap.datasets.adult ()). Для наглядности и сокращения времени выполнения вычислений мы включим в нашу модель только 6 из 12 функций (Возраст, Количество часов в неделю, Образование, Семейное положение, Прирост капитала и Пол). Наша модель будет классификатором XGBoost. Как значения SHAP TreeExplainer и значения Naive Shapley сравниваются друг с другом в этом случае? Диаграмма рассеяния дает нам быстрое первое впечатление:

Результаты кажутся сильно коррелированными, и это уже должно указывать на то, что, несмотря на их концептуальные различия, два подхода, вероятно, не слишком сильно расходятся в своих результатах. Теперь с summary_plot:

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

Что тут происходит?

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

Примечание. Преимущество реализации нашей собственной пользовательской функции Шепли заключается в том, что у нас есть легкий доступ к множеству промежуточных результатов, например, к размеру прибыли, которую мы рассчитали для каждой возможной комбинации функций с или без данной функции (и средневзвешенное значение которой является значением Шепли для каждой выборки). Просто для удовольствия я извлек его из функции compute_shapley_values ​​, чтобы мы могли посмотреть, как окончательные значения Шепли возникают из этих индивидуальных полей выплат. Это распределения прибыли для переменной Пол в зависимости от количества функций, к которым она добавлена:

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

Итак, какой метод мы должны использовать, чтобы объяснить роль переменной Пол в наших данных и модели? Я думаю, что лучше всего это выразить:

  • Наивные значения Шепли лучше отражают глобальное влияние функций в нашем наборе данных, а
  • Значения SHAP лучше объясняют конкретные прогнозы с учетом нашей существующей обученной модели.

Два дополнительных замечания перед тем, как двигаться дальше:

Практическое замечание: я не предлагаю, чтобы, если вы заботитесь о влиянии глобальных функций в своем наборе данных, вы обязательно должны использовать наивный метод Шепли - главным образом потому, что в большинстве случаев это трудноразрешимо с вычислительной точки зрения (хотя см. разделы о том, когда этого может не быть). Из моих примеров также очевидно, что результаты объяснений SHAP обычно не настолько различаются, что их не следует использовать для этой цели. Моя главная мотивация здесь - лучше понять результаты SHAP и их ограничения.

Техническое примечание. Если вы знакомы с TreeExplainer, вы можете знать, что, поскольку в случае двоичной классификации веса узлов дерева содержат не вероятности, а логарифмически нечетные значения (которые преобразуются в вероятности с логистическая функция в качестве последнего шага) - подход к оптимизации по умолчанию, используемый TreeExplainer, предоставляет значения SHAP, которые суммируются с этими непреобразованными значениями (а не окончательными вероятностями). Простое применение логистической функции к самим значениям SHAP не сработает, поскольку сумма преобразованных значений! = Преобразованное значение суммы. Чтобы получить значения SHAP, которые напрямую соответствуют выходным данным вероятности, TreeExplainer должен пожертвовать частью своей эффективности и использовать подход, аналогичный KernelExplainer, для моделирования отсутствующих функций путем замены фоновым набором данных - естественно, более медленный и менее точный метод. С другой стороны, чтобы напрямую объяснить выходные данные вероятности с помощью наивного метода Шепли, все, что нам нужно сделать, это выбрать выход функции выигрыша как вероятность. Поскольку с помощью наивного метода Шепли мы всегда платим максимальную стоимость вычислений, мы могли бы также использовать функцию выплаты, которая дает нам именно то, что мы хотим, чтобы наши значения Шепли объясняли.

Наивные ценности Шепли против KernelExplainer

KernelExplainer - это слепой метод вычисления значений SHAP. Вкратце, это работает:

  1. Выборка лишь небольшого подмножества возможных перестановок функций.
  2. Для каждой такой перестановки моделирование «отсутствующих функций» путем создания множества самонастраиваемых выборок, в которых значения этих функций заменяются значениями из небольшого «набора фоновых данных», и усреднения прогнозов этих выборок.

Это означает, что по сравнению с TreeExplainer, KernelExplainer:

  1. Медленнее - необходимо вычислить большое количество прогнозов для каждого объясненного экземпляра в наборе данных (поскольку отсутствующие значения моделируются путем усреднения по множеству возможных значений функции).
  2. Недетерминированный - значения SHAP KernelExplainer оцениваются с отклонением, вносимым как методом коалиционной выборки, так и выбором фонового набора данных.

Как это складывается при сравнении значений SHAP KernelExplainer со значениями Naive Shapley? Давайте использовать тот же набор данных переписи с 6 объектами, прогнозирующий ›доход в 500 тыс. долларов в качестве тестового примера. На этот раз, следуя примеру этой записной книжки библиотеки SHAP, мы будем использовать модель KNN, чтобы сделать это предсказание, и KernelExplainer, чтобы предоставить значения Shapley, которые мы можем сравнить со значениями Naive Shapley:

Сравнение результатов:

Эти два метода дают разные, но коррелированные результаты. Если мы отсортируем и ранжируем значения Шепли для каждой выборки (от 1 до 6), порядок будет отличаться в среднем примерно на 0,75 ранга (например, примерно в 75% выборок меняется порядок двух соседних функций). Напомним, что мы не рассматриваем связь между точными значениями и их зашумленной оценкой: скорее, Наивные значения Шепли являются детерминированной мерой одного, а значения SHAP ядра являются оценкой другого (связанного) вещь.

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

Может ли Naive Shapley быть быстрее KernelExplainer?

Как мы установили, метод Naive Shapely требует повторного обучения модели и создания прогнозов 2ᴹ раза. Это делает его непрактичным, если количество функций невелико (скажем, более 15–20). Но сравнимо ли оно с объяснениями SHAP по небольшому количеству функций?

Следует уйти с пути: оптимизированные объяснители SHAP всегда будут быстрее, чем наивный метод Шепли, но не учитывающий модели KernelExplainer может быть очень медленным при объяснении большого набора данных. Чтобы получить лучшее представление, давайте посмотрим, что входит во время выполнения KernelExplainer по сравнению с наивным методом Шепли:

Полужирным шрифтом выделены слабые стороны каждого метода. Наивный метод Шепли, конечно, наиболее уязвим для увеличения количества функций, а также зависит от времени обучения модели, тогда как на KernelExplainer эти факторы не влияют (хотя его прогноз становится более изменчивым с увеличением количества функций). Недостатки KernelExplainer с точки зрения времени выполнения заключаются в том, что, хотя ему не нужно тратить время на повторное обучение модели, он запускается отдельно для каждого объясненного прогноза (в то время как Наивный Шепли запускается для всех прогнозов одновременно), каждый раз создавая прогнозы для ~ 200 000 выборок (nsamples X num. background samples, которые по умолчанию составляют 2048 + 2M и 100 соответственно).

Хорошим примером модели, для которой наивный метод Шепли потенциально может работать быстрее, чем KernelExplainer, при небольшом количестве функций, является модель Isolation Forest, популярный инструмент для обнаружение аномалий, поскольку, несмотря на то, что это древовидная модель, она не поддерживается TreeExplainer, и время ее обучения (по сравнению с прогнозированием) относительно быстрое. Чтобы продемонстрировать это, я использую набор данных Обнаружение мошенничества с кредитными картами от Kaggle, образец размером около 285 КБ, набор данных с 30 функциями, используемый для прогнозирования аномальной транзакции по кредитной карте. Для нашей демонстрации возьмем 100 тыс. Образцов и сократим 30 функций до 15. На моем старом ноутбуке я получаю следующее приблизительное время работы:

- Обучить модель: 8 секунд
- Сделать прогнозы для всех 100 000 выборок: 8 секунд < br /> - Вычислить значения SHAP для одного прогноза: 18 секунд (что неудивительно, примерно столько же, сколько требуется для вычисления прогнозов для ~ 200K загрузочных выборок)

Основываясь на этом, мы можем сделать приблизительную оценку того, сколько времени потребуется, чтобы вычислить значения Шепли для всего набора данных. KernelExplainer должен просто занять 100 000 x 18 секунд или около 500 часов. Наивная функция Шепли будет работать до 2¹⁵ * (15 + 13) секунд или около 150 часов (на самом деле, более точная оценка может составлять около 50 часов, так как наборы данных начальной загрузки, используемые для обучения на каждой итерации алгоритма будет иметь от 1 до 15 функций, или в среднем 7–8, что обычно ускоряет обучение). Оба метода медленные (хотя оба могут выиграть от распараллеливания), но здесь важен не конкретный пример, а понимание того, откуда берется время вычислений в каждом случае. Обобщить:

  • Если вам нужно объяснить только небольшую группу «важных» прогнозов, KernelExplainer должен быть достаточно быстрым.
  • Если вам нужно объяснить миллион прогнозов и у вас меньше 10–15 функций, наивный метод Шепли должен быть намного быстрее.

Практический компромисс? Оценка наивных значений Шепли с помощью выборки

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

Почему бы не попытаться оценить наивные значения Шепли с помощью коалиционной выборки? Использование случайной выборки для оценки значений Шепли для большого числа игроков (как это делается, например, с помощью KernelExplainer) подробно обсуждается в литературе, и улучшенные методы все еще разрабатываются (см., например, Castro et al. 2009, Castro et al. 2017 или Benati et al. 2019). Я бы предположил, что выборка может хорошо работать в сочетании с наивным подходом Шепли, то есть для выборки пространства комбинаций функций, на которых обучается модель (таким образом, нет необходимости имитировать недостающие функции путем усреднения по загрузочным выборкам).

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

На данный момент это только теоретическая идея, и этот пост достаточно длинный, чтобы не развивать его здесь. Я был бы рад получить ваши комментарии по поводу этой идеи (может быть, вы уже сталкивались с ней где-то еще?), И я надеюсь развить и обсудить ее в следующем посте.

Первоначально опубликовано на https://edden-gerber.github.io 8 декабря 2019 г.