Интерпретируемость моделей
SHAP, LIME, feature importance, partial dependence — как объяснить предсказания модели.
Интерпретируемость моделей — почему «оно работает» недостаточно
Банк отказал в кредите. Клиент спрашивает: «Почему?». По закону (GDPR статья 22, EU AI Act) банк обязан объяснить решение. Если за отказом стоит ML-модель, которая не может объяснить — модель юридически непригодна. Это не теория: в 2024 году EU AI Act вступил в силу, и модели высокого риска (кредитный скоринг, медицина, страхование) обязаны быть объяснимыми.
Но даже без регуляции — необъяснимая модель опасна. Ты не знаешь, на что она опирается. Может, она «выучила» артефакт в данных (ID пациента коррелирует с диагнозом), а не реальные паттерны. Без интерпретации ты не отладишь модель, не получишь trust от стейкхолдеров, не найдёшь баги.

Зачем объяснять модель
Три причины, по которым интерпретируемость — не опция, а необходимость:
- Regulatory compliance. GDPR Article 22: право на объяснение автоматических решений. EU AI Act: модели высокого риска обязаны быть прозрачными. Пример: банк отказал в кредите → обязан объяснить, какие факторы повлияли.
- Debugging. Модель может выучить ложные корреляции (shortcut learning). Пример: модель диагностики COVID научилась определять больничные бирки на рентгенах, а не патологию лёгких. Без интерпретации это не обнаружить.
- Trust & buy-in. Бизнес-стейкхолдеры не развернут модель, которую не понимают. Data scientist объясняет модель продакт-менеджеру, тот — руководству. Пример: рекламный таргетинг — «почему этому пользователю показали эту рекламу?»
Feature Importance: быстро, но грубо
Impurity-based (встроенная в деревья)
Random Forest и Gradient Boosting имеют встроенный feature_importances_ — средний прирост чистоты (Gini impurity decrease) по всем деревьям. Плюсы: мгновенно, не требует дополнительных вычислений. Минусы: смещена в сторону high-cardinality фич (дата, ID), некорректна при коррелированных фичах (важность «размазывается» между ними). На практике часто врёт.
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
import numpy as np
X, y = make_classification(n_samples=1000, n_features=10, random_state=42)
feature_names = [f'feat_{i}' for i in range(10)]
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X, y)
# Impurity-based importance (встроенная, быстрая, но неточная)
importances = rf.feature_importances_
for name, imp in sorted(zip(feature_names, importances), key=lambda x: -x[1])[:5]:
print(f" {name}: {imp:.4f}")Permutation Importance — более честный вариант
Идея: перемешиваем значения одной фичи случайным образом, измеряем падение метрики. Если фича важна — метрика сильно упадёт. Если не важна — метрика почти не изменится. Model-agnostic (работает с любой моделью), лучше обрабатывает корреляции. Минус: медленно — N_features * N_repeats вычислений модели.
from sklearn.inspection import permutation_importance
# Permutation importance — честнее, но медленнее
# ВАЖНО: считаем на TEST данных, не на train!
perm_imp = permutation_importance(
rf, X_test, y_test, # X_test, y_test — тестовая выборка
n_repeats=10,
random_state=42,
scoring='f1'
)
for name, imp, std in sorted(
zip(feature_names, perm_imp.importances_mean, perm_imp.importances_std),
key=lambda x: -x[1]
)[:5]:
print(f" {name}: {imp:.4f} +/- {std:.4f}")Permutation importance на тестовых данных
SHAP — золотой стандарт объяснения
SHAP (SHapley Additive exPlanations) основан на значениях Шепли из теории игр. Каждая фича — «игрок», предсказание модели — «выигрыш». SHAP-значение фичи = средний маргинальный вклад этой фичи по всем возможным коалициям остальных фич. Математически строго, единственный метод, удовлетворяющий аксиомам эффективности, симметрии, линейности и dummy.
Shapley value: средний маргинальный вклад фичи i по всем подмножествам остальных фич
Три типа SHAP-графиков, которые должен знать каждый DS: (1) Summary plot — глобальная важность фич + направление влияния (красный = высокое значение фичи, синий = низкое). (2) Waterfall plot — объяснение одного предсказания: базовое значение + вклады каждой фичи = финальный скор. (3) Dependence plot — как одна фича влияет на предсказание с учётом взаимодействия с другой фичей.
import shap
import xgboost as xgb
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
# Обучаем XGBoost
X, y = make_classification(n_samples=2000, n_features=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
feature_names = [f'feat_{i}' for i in range(10)]
model = xgb.XGBClassifier(n_estimators=100, max_depth=5, random_state=42)
model.fit(X_train, y_train)
# TreeExplainer — точный и быстрый для деревьев (XGBoost, LightGBM, RF)
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test)
# 1. Summary plot — глобальная важность + направление влияния
shap.summary_plot(shap_values, X_test, feature_names=feature_names, show=False)
# 2. Waterfall — объяснение одного предсказания
shap.plots.waterfall(explainer(X_test)[0], show=False)
# 3. Dependence plot — эффект одной фичи
shap.dependence_plot('feat_0', shap_values, X_test,
feature_names=feature_names, show=False)SHAP для разных моделей: TreeSHAP — точный, O(TLD) для деревьев, за секунды на 100K объектов. KernelSHAP — для любой модели (нейросети, SVM), но медленный (sampling-based), минуты на 1K объектов. DeepSHAP — для нейросетей, gradient-based аппроксимация, быстрее KernelSHAP, но менее точный.
Выбирай метод по модели
LIME — объяснение одного предсказания
LIME (Local Interpretable Model-agnostic Explanations) объясняет одно конкретное предсказание. Как работает: возьми объект → сгенерируй возмущённые версии (перемешивая/маскируя фичи) → получи предсказания модели на них → обучи линейную модель на этих возмущениях → коэффициенты линейной модели = объяснение. Плюсы: работает с ЛЮБОЙ моделью (табулярные, текст, изображения). Минусы: нестабильный (разные perturbations → разные объяснения), медленный для batch.
import lime.lime_tabular
import numpy as np
# Создаём explainer
explainer = lime.lime_tabular.LimeTabularExplainer(
training_data=X_train,
feature_names=feature_names,
class_names=['negative', 'positive'],
mode='classification'
)
# Объяснение одного предсказания
explanation = explainer.explain_instance(
X_test[0], # объект для объяснения
model.predict_proba, # функция предсказания
num_features=5, # топ-5 фич
num_samples=1000 # сколько perturbations сгенерировать
)
# Топ-5 фич с вкладами
for feature, weight in explanation.as_list():
print(f" {feature}: {weight:+.4f}")
# Пример вывода:
# feat_2 > 0.47: +0.2134
# feat_5 <= -0.31: +0.1567
# feat_0 > 1.22: -0.0982LIME vs SHAP: LIME быстрее для объяснения одного предсказания (не нужно считать Shapley по всем коалициям). SHAP теоретически обоснованнее (аксиомы Шепли гарантируют уникальность и справедливость). На практике для табулярных данных SHAP доминирует. LIME до сих пор полезен для текстов (какие слова повлияли на тональность?) и изображений (какие пиксели важны?).
Partial Dependence Plots (PDP)
PDP показывает маргинальный эффект одной фичи на предсказание, усреднённый по всем остальным фичам. Отвечает на вопрос: «Как изменится предсказание, если увеличить возраст клиента при прочих равных?». Отлично подходит для объяснения бизнесу — показывает монотонные/немонотонные зависимости.
from sklearn.inspection import PartialDependenceDisplay
# PDP для двух фич
fig, ax = plt.subplots(figsize=(12, 4))
PartialDependenceDisplay.from_estimator(
model, X_test,
features=[0, 3], # индексы фич
feature_names=feature_names,
kind='both', # 'both' = PDP + ICE линии
ax=ax
)
# 'both' рисует:
# - PDP (синяя жирная линия) — средний эффект
# - ICE (серые тонкие линии) — индивидуальные эффектыPDP предполагает независимость фич — если фичи коррелированы, PDP может показывать нереалистичные комбинации (например, высокий рост + низкий вес). ICE plots (Individual Conditional Expectation) частично решают эту проблему — показывают отдельную линию для каждого объекта вместо среднего. Если ICE-линии параллельны — эффект фичи одинаков для всех. Если расходятся — есть interaction effect.
На собесе
Junior
Middle
Senior
Материалы
Бесплатная книга — лучший обзор всех методов интерпретации. Обязательна к прочтению.
Официальная документация SHAP: TreeExplainer, KernelSHAP, DeepSHAP, визуализации.
Permutation importance, PDP, ICE plots — встроенные инструменты sklearn.
Подробный разбор SHAP с примерами на Python от Open Data Science.