Изучение идей PyMC с помощью SHAP Framework на примере увлекательной игрушки

Разрыв между байесовскими моделями и объяснимостью

Значения SHAP (Shapley Additive exPlanations) — это основанный на теории игр метод, используемый для повышения прозрачности и интерпретируемости моделей машинного обучения. Однако этот метод, наряду с другими структурами объяснимости машинного обучения, редко применялся к байесовским моделям, которые обеспечивают апостериорное распределение, отражающее неопределенность в оценках параметров, вместо точечных оценок, используемых в классических моделях машинного обучения.

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

В этой статье делается попытка объяснить байесовскую модель с использованием фреймворка SHAP на игрушечном примере. Модель построена на PyMC, библиотеке вероятностного программирования для Python, которая позволяет пользователям создавать байесовские модели с помощью простого API Python и подгонять их с помощью цепи Маркова Монте-Карло.

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

Все реализации можно найти в этом блокноте.

Байесовское моделирование с PyMC

Набор данных

Рассмотрим следующий набор данных, созданный автором, который содержит 250 точек: переменная y зависит от x1 и x2, оба из которых варьируются от 0 до 5. Изображение ниже иллюстрирует набор данных:

Давайте быстро изучим данные, используя парный график. Отсюда мы можем наблюдать следующее:

  1. Переменные x1 и x2 не коррелированы.
  2. Обе переменные в некоторой степени влияют на выход y. То есть одной переменной недостаточно для получения y.

Моделирование с помощью PyMC

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

Определим структуру модели следующим образом:

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

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

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

Мы можем определить структуру модели, как показано ниже:

Для априорных значений и вероятности, определенных выше, мы будем использовать стандартный алгоритм выборки PyMC NUTS. Этот алгоритм предназначен для автоматической настройки его параметров, таких как размер шага и количество скачкообразных шагов, для достижения эффективного исследования целевого распределения. Он повторяет исследование дерева, чтобы смоделировать траекторию точки в пространстве параметров и определить, следует ли принять или отклонить выборку. Итерация останавливается либо при достижении максимального количества итераций, либо при достижении уровня сходимости.

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

with pm.Model() as model:

    # Set priors.
    intercept=pm.Uniform(name="intercept",lower=-10, upper=10)
    x1_slope=pm.Uniform(name="x1_slope",lower=-5, upper=5)
    x2_slope=pm.Uniform(name="x2_slope",lower=-5, upper=5)
    interaction_slope=pm.Uniform(name="interaction_slope",lower=-5, upper=5)
    sigma=pm.Uniform(name="sigma", lower=1, upper=5)
    
    # Set likelhood.
    likelihood = pm.Normal(name="y", mu=intercept + x1_slope*x1+x2_slope*x2+interaction_slope*x1*x2, \
                           sigma=sigma, observed=y)
    # Configure sampler.
    trace = pm.sample(5000, chains=5, tune=1000, target_accept=0.87, random_seed=SEED)

График трассировки ниже отображает апостериорные значения параметров в модели.

Объясните модель с помощью SHAP

Теперь мы хотим реализовать SHAP на модели, описанной выше. Обратите внимание, что для данного входа (x1, x2) выход модели y является вероятностью, зависящей от параметров. Таким образом, мы можем получить детерминированную модель и соответствующие значения SHAP для всех признаков, взяв одну выборку из полученных апостериорных значений. В качестве альтернативы, если мы нарисуем ансамбль выборок параметров, мы получим ансамбль детерминированных моделей и, следовательно, выборки значений SHAP для всех признаков.

Апостериоры можно получить с помощью следующего кода, где мы рисуем 200 выборок на цепочку:

with model: 
    idata = pm.sample_prior_predictive(samples=200, random_seed=SEED)
    idata.extend(pm.sample(200, tune=2000, random_seed=SEED)here

Вот таблица переменных данных из апостериорного анализа:

Затем мы вычисляем одну пару значений SHAP для каждой выбранной выборки параметров модели. Приведенный ниже код перебирает параметры, определяет одну модель для каждой выборки параметров и вычисляет интересующие значения SHAP x_test=(2,3).

background=np.hstack((x1.reshape((250,1)),x2.reshape((250,1))))
shap_values_list=[]
x_test=np.array([2,3]).reshape((-1,2))
for i in range(len(pos_intercept)): 
  model=SimpleModel(intercept=pos_intercept[i],
                    x1_slope=pos_x1_slope[i], 
                    x2_slope=pos_x2_slope[i], 
                    interaction_slope=pos_interaction_slope[i],
                    sigma=pos_sigma[i])
  explainer = shap.Explainer(model.predict, background)
  shap_values = explainer(x_test)
  shap_values_list.append(shap_values.values)

Результирующий ансамбль двумерных входных значений SHAP показан ниже:

Из приведенного выше графика мы можем сделать следующие выводы:

  1. Значения SHAP обоих измерений формируют более или менее нормальное распределение.
  2. Первое измерение имеет положительный вклад (-1,75 как медиана) в модель, а второе имеет отрицательный вклад (3,45 как медиана). Однако вклад второго измерения имеет большее абсолютное значение.

Заключение

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

Обратите внимание, что SHAP не зависит от модели. Следовательно, с изменениями в его реализации в будущем можно будет применить SHAP непосредственно к самой байесовской модели.