Объясните любую модель машинного обучения на Python с помощью SHAP

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

Но какие факторы привели к такому прогнозу? Каков вклад каждого признака в предсказание? Было бы здорово, если бы вы могли увидеть график, показывающий, какой вклад вносит каждый признак в предсказание, как показано ниже.

Вот тогда-то и пригодится значение Шапли.
Что такое значение Шапли?
Значение Шэпли – это метод, используемый в теории игр, который предполагает справедливое распределение выгод и затрат между участниками, работающими в коалиции.
Поскольку каждый участник вносит свой вклад в коалицию, ценность Шэпли гарантирует, что каждый участник получит справедливую долю в зависимости от того, сколько он внес.

Простой пример
Значение Шапли используется для решения широкого круга задач, в которых ставится вопрос о вкладе каждого работника/функции в группе. Чтобы понять, как работает значение Шапли, представим, что ваша компания только что провела A/B-тестирование, в ходе которого проверяются различные комбинации рекламных стратегий.
Доходы по каждой стратегии в конкретном месяце составляют:
без рекламы: $150
социальные сети: $300
реклама Google: $200
маркетинг по электронной почте: $350
социальные сети и реклама Google: $320
социальные сети и email-маркетинг: $400
реклама Google и маркетинг электронной почты: $350
маркетинг электронной почты, реклама Google и социальные сети: $450

Разница в доходах между использованием трех объявлений и отсутствием рекламы составляет $300. Каков вклад каждого объявления в эту разницу?

Мы можем выяснить это, рассчитав значение Shapley для каждого типа рекламы. В этой статье приводится отличный способ расчета значения Шапли. Я кратко изложу его здесь.
Начнем с расчета общего вклада рекламы Google в доход компании. Общий вклад рекламы Google можно рассчитать по формуле:

Найдем маржинальный вклад рекламы Google и ее вес.
Найти маржинальный вклад рекламы Google
Сначала мы найдем маржинальный вклад рекламы Google в следующих группах:
- без рекламы
- реклама Google + социальные медиа
- реклама Google + маркетинг электронной почты
- реклама Google + маркетинг электронной почты + социальные медиа

Предельный вклад рекламы Google в отсутствие рекламы составляет:

Маржинальный вклад рекламы Google в группу рекламы Google и социальных сетей составляет:

Маржинальный вклад рекламы Google в группу рекламы Google и маркетинга по электронной почте составляет:

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

Найти вес
Чтобы найти веса, мы организуем комбинации различных рекламных стратегий в несколько уровней, как показано ниже. Каждый уровень соответствует количеству рекламных стратегий в каждой комбинации.
Затем мы присвоим веса, основываясь на количестве ребер на каждом уровне. Мы видим, что:
- Первый уровень содержит 3 ребра, поэтому вес каждого ребра будет равен 1/3.
- Второй уровень содержит 6 ребер, поэтому вес каждого ребра будет равен 1/6
- Третий уровень содержит 3 ребра, поэтому вес каждого ребра будет 1/3

Найти общий вклад Google Advertisemen
Теперь мы готовы найти общий вклад рекламы Google, основываясь на весах и предельных вкладах, которые мы нашли ранее!


Круто! Итак, вклад рекламы Google в общую разницу в доходах между использованием 3 рекламных стратегий и отсутствием рекламы составляет $36,67. 36,67 – это значение Шейпи для рекламы Google.

Повторив описанные выше шаги для двух других рекламных стратегий, мы можем увидеть следующее:
маркетинг электронной почты приносит $151,67
Социальные медиа – $111,67
реклама Google – $36,67

Вместе они вносят $300 в разницу между использованием 3 различных видов рекламы и отсутствием рекламы! Довольно круто, не так ли?
Теперь, когда мы понимаем значение Shapley, давайте посмотрим, как мы можем использовать его для интерпретации модели машинного обучения.
SHAP – объяснение любых моделей машинного обучения на Python
SHAP – это библиотека Python, которая использует значения Шэпли для объяснения вывода любой модели машинного обучения.
Чтобы установить SHAP, введите:
pip install shap
Обучение модели
Чтобы понять, как работает SHAP, мы проведем эксперимент с набором данных по рекламе:
import pandas as pd
data = pd.read_csv("advertising.csv")
data.columns = data.columns.map(lambda row: "_".join(row.lower().split(" ")))
data
| | daily_time_spent_on_site | age | area_income | daily_internet_usage | ad_topic_line | city | male | country | timestamp | clicked_on_ad |
|---:|---------------------------:|------:|--------------:|-----------------------:|:--------------------------------------|:-----------------|-------:|:-----------|:--------------------|----------------:|
| 0 | 68.95 | 35 | 61833.9 | 256.09 | Cloned 5thgeneration orchestration | Wrightburgh | 0 | Tunisia | 2016-03-27 00:53:11 | 0 |
| 1 | 80.23 | 31 | 68441.9 | 193.77 | Monitored national standardization | West Jodi | 1 | Nauru | 2016-04-04 01:39:02 | 0 |
| 2 | 69.47 | 26 | 59785.9 | 236.5 | Organic bottom-line service-desk | Davidton | 0 | San Marino | 2016-03-13 20:35:42 | 0 |
| 3 | 74.15 | 29 | 54806.2 | 245.89 | Triple-buffered reciprocal time-frame | West Terrifurt | 1 | Italy | 2016-01-10 02:31:19 | 0 |
| 4 | 68.37 | 35 | 73890 | 225.58 | Robust logistical utilization | South Manuel | 0 | Iceland | 2016-06-03 03:36:18 | 0 |
| 5 | 59.99 | 23 | 59761.6 | 226.74 | Sharable client-driven software | Jamieberg | 1 | Norway | 2016-05-19 14:30:17 | 0 |
| 6 | 88.91 | 33 | 53852.8 | 208.36 | Enhanced dedicated support | Brandonstad | 0 | Myanmar | 2016-01-28 20:59:32 | 0 |
| 7 | 66 | 48 | 24593.3 | 131.76 | Reactive local challenge | Port Jefferybury | 1 | Australia | 2016-03-07 01:40:15 | 1 |
| 8 | 74.53 | 30 | 68862 | 221.51 | Configurable coherent function | West Colin | 1 | Grenada | 2016-04-18 09:33:42 | 0 |
| 9 | 69.88 | 20 | 55642.3 | 183.82 | Mandatory homogeneous architecture | Ramirezton | 1 | Ghana | 2016-07-11 01:42:51 | 0 |
Наша цель – построить модель машинного обучения для предсказания того, кликнул ли пользователь на рекламу, основываясь на некоторой информации о нем.
Мы будем использовать Patsy для преобразования DataFrame в массив признаков и массив целевых значений:
from patsy import dmatrices
y, X = dmatrices(
"clicked_on_ad ~ daily_time_spent_on_site + age + area_income + daily_internet_usage + male -1",
data=data,
)
X_frame = pd.DataFrame(data=X, columns=X.design_info.column_names)
Разделите данные на обучающий и тестовый наборы:
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=7)
Далее мы будем использовать XGBoost для построения модели и составления прогнозов:
import xgboost
model = xgboost.XGBClassifier().fit(X_train, y_train)
predict = model.predict(X_test)
Чтобы узнать, насколько хорошо работает модель, мы будем использовать показатель F1:
from sklearn.metrics import f1_score
f1 = f1_score(y_test, predict)
f1
0.9619047619047619
Очень хорошо!
Интерпретировать модель
Модель хорошо справилась с предсказанием того, кликнул ли пользователь на рекламу. Но как она пришла к таким прогнозам? Какой вклад внесла каждая характеристика в разницу между окончательным прогнозом и средним прогнозом?
Обратите внимание, что эта проблема очень похожа на ту, которую мы рассматривали в начале статьи.
Поэтому нахождение значения по Шэпли для каждого признака может помочь нам определить их вклад. Шаги для получения важности признака i, где i – индекс признака, аналогичны предыдущим:
- Получить все подмножества, не содержащие признак i
- Найти маргинальный вклад признака i в каждое из этих подмножеств
- Агрегируйте все маргинальные вклады для вычисления вклада признака i
Чтобы найти значения Шапли с помощью SHAP, просто вставьте свою обученную модель в shap.Explainer :
import shap
explainer = shap.Explainer(model)
shap_values = explainer(X_frame)
Схема водопада SHAP
Визуализируйте объяснение первого предсказания:
shap.plots.waterfall(shap_values[0])

Ага! Теперь мы знаем вклад каждого признака в первое предсказание. Объяснения для приведенного выше графика:

- Синяя полоса показывает, насколько та или иная характеристика уменьшает ценность прогноза.
- Красная полоса показывает, насколько та или иная характеристика увеличивает ценность прогноза.
- Отрицательные значения означают вероятность того, что человек кликнул на объявление, меньше 0,5.
Для каждого из этих подмножеств SHAP не удаляет признак, а затем переобучает модель, но заменяет этот признак средним значением этого признака, а затем генерирует предсказания.
Мы должны ожидать, что общий вклад будет равен разнице между предсказанием и средним предсказанием. Давайте проверим это:

Круто! Они равны.
Визуализируйте объяснение второго предсказания:
shap.plots.waterfall(shap_values[1])

Сводный план SHAP
Вместо того чтобы рассматривать каждый отдельный экземпляр, мы можем визуализировать общее влияние этих характеристик на несколько экземпляров с помощью сводного графика SHAP:
shap.summary_plot(shap_values, X)

Сводный график SHAP показывает нам наиболее важные характеристики и диапазон их влияния на набор данных.
Из приведенного графика мы можем получить некоторые интересные сведения о прогнозах модели:
- Ежедневное использование интернета пользователем оказывает самое сильное влияние на то, нажмет ли пользователь на рекламу.
- По мере увеличения ежедневного использования Интернета пользователь с меньшей вероятностью нажмет на объявление.
- По мере увеличения ежедневного времени, проведенного на сайте, пользователь с меньшей вероятностью нажмет на объявление.
- С увеличением дохода в регионе пользователь с меньшей вероятностью нажмет на объявление.
- С увеличением возраста пользователь с большей вероятностью нажмет на объявление.
- Если пользователь – мужчина, он с меньшей вероятностью нажмет на объявление.
SHAP Bar Plot
Мы также можем получить график важности глобального признака, используя гистограмму SHAP.
shap.plots.bar(shap_values)

График рассеивания зависимости SHAP
Мы можем наблюдать влияние одной особенности на все предсказания, сделанные моделью, с помощью диаграммы рассеяния зависимости SHAP.
Ежедневное пользование Интернетом
Диаграмма рассеяния характеристики ежедневного использования интернета:
shap.plots.scatter(shap_values[:, "daily_internet_usage"])

Из приведенного выше графика видно, что по мере увеличения ежедневного использования интернета значение SHAP для ежедневного использования интернета уменьшается. Это подтверждает то, что мы видели на предыдущем графике.
Мы также можем наблюдать взаимодействие между признаком ежедневного использования интернета и другими признаками на том же графике, добавив color=shap_values .
На диаграмме рассеяния мы попытаемся выбрать столбец характеристик с наиболее сильным взаимодействием с ежедневным использованием интернета, а именно ежедневное время, проведенное на сайте.
shap.plots.scatter(shap_values[:, "daily_internet_usage"], color=shap_values)

Круто! Из приведенного выше графика видно, что человек, который пользуется интернетом 150 минут в день и проводит на сайте небольшое количество времени в день, с большей вероятностью кликнет на объявление.
Давайте посмотрим на диаграммы рассеяния некоторых других характеристик:
Ежедневное время, проведенное на объекте
shap.plots.scatter(shap_values[:, "daily_time_spent_on_site"], color=shap_values)

Доход по району
shap.plots.scatter(shap_values[:, "area_income"], color=shap_values)

Возраст
shap.plots.scatter(shap_values[:, "age"], color=shap_values)

Пол
shap.plots.scatter(shap_values[:, "male"], color=shap_values)

График взаимодействия SHAP
Вы также можете наблюдать матрицу взаимодействий между признаками с помощью сводного графика значений взаимодействия SHAP. На этом графике основные эффекты расположены на диагонали, а эффекты взаимодействия – вне диагонали.
# Get interaction values
shap_interaction_values = explainer.shap_interaction_values(X)
# Summarize the interaction values
shap.summary_plot(shap_interaction_values, X_frame)

Очень круто!
Заключение
Поздравляем! Вы только что узнали о значении Шейпи и о том, как использовать его для интерпретации модели машинного обучения. Я надеюсь, что эта статья даст вам необходимые знания для интерпретации вашей собственной модели машинного обучения с помощью Python.