SHAP и LIME: объяснимость ML-моделей
Модель XGBoost даёт AUC 0.91 на валидации. На продакшене появляются неожиданные предсказания — высокие скоры для явно нерелевантных объектов. Feature importance из самого бустинга показывает топ-10 признаков, но не объясняет конкретное предсказание. Почему этот конкретный объект получил score 0.87?
SHAP и LIME отвечают на разные версии этого вопроса. Важно понимать, когда применять каждый метод и где они ломаются.
SHAP: теория и практика
SHAP (SHapley Additive exPlanations, Lundberg & Lee, 2017) основан на теории кооперативных игр Шепли. Идея: вклад каждого признака в предсказание = среднее его маргинальное влияние при всех возможных коалициях признаков.
Ключевое свойство: аддитивность. Сумма SHAP values всех признаков + base value (среднее предсказание модели) = конкретное предсказание. Это математически точное разложение, не аппроксимация.
TreeSHAP — почему важна архитектурная специализация
Для tree-based моделей (XGBoost, LightGBM, CatBoost, sklearn RandomForest) существует TreeSHAP — алгоритм с полиномиальной сложностью O(TLD²), где T — число деревьев, L — максимальное число листьев, D — глубина. Это на порядки быстрее наивного KernelSHAP.
import shap
import xgboost as xgb
model = xgb.XGBClassifier()
model.fit(X_train, y_train)
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test)
# Waterfall plot для конкретного предсказания
shap.plots.waterfall(explainer(X_test)[0])
# Summary plot — глобальная важность
shap.summary_plot(shap_values, X_test)
На практике TreeSHAP на LightGBM модели с 500 деревьями обрабатывает 10 000 примеров за 2–3 секунды на CPU. Вполне приемлемо для batch inference.
DeepSHAP и GradientSHAP для нейросетей
Для нейронных сетей TreeSHAP неприменим. Используем:
- GradientSHAP (DeepLIFT + SHAP): интегрирует градиенты вдоль пути от baseline к входу. Быстрее KernelSHAP, но требует дифференцируемости.
- KernelSHAP: модель-агностик, работает для любой черноящичной модели. Медленный — для одного объяснения нужно 2^n−2 запросов к модели. На практике используется выборка (nsamples=100–1000).
Для BERT и трансформеров — отдельная история. SHAP на трансформерах через partition explainer работает, но latency объяснения одного текста может достигать 30–60 секунд при 512 токенах. Для продакшена обычно нужен trade-off: объяснения генерируются асинхронно по запросу.
LIME: локальная аппроксимация
LIME (Locally Interpretable Model-agnostic Explanations, Ribeiro et al., 2016) работает иначе: вокруг объекта генерируется случайное облако возмущений, для каждого получается предсказание черноящичной модели, затем на этом облаке обучается простая интерпретируемая модель (линейная регрессия или дерево).
Когда LIME лучше SHAP:
- Модель не поддерживается TreeSHAP и слишком медленна для KernelSHAP
- Нужно объяснение в терминах «супер-пикселей» для изображений (LIME для CV)
- Нужна текстовая объяснимость с выделением слов (LIME для NLP)
Проблема стабильности: LIME — стохастический алгоритм. При разных random_state объяснения для одного объекта могут значительно различаться. В продакшене фиксируем seed и используем большое число возмущений (num_samples=5000+).
from lime.lime_tabular import LimeTabularExplainer
explainer = LimeTabularExplainer(
X_train.values,
feature_names=feature_names,
class_names=['negative', 'positive'],
mode='classification'
)
explanation = explainer.explain_instance(
X_test.values[0],
model.predict_proba,
num_features=10,
num_samples=5000
)
explanation.show_in_notebook()
Сравнение методов
| Характеристика | TreeSHAP | KernelSHAP | LIME |
|---|---|---|---|
| Применимость | Только деревья | Любая модель | Любая модель |
| Математическая точность | Точная | Точная | Аппроксимация |
| Стабильность | Детерминированная | Детерминированная | Стохастическая |
| Скорость (10k объектов) | Секунды | Часы | Минуты |
| Поддержка текста/изображений | Нет | Нет нативно | Да |
Интеграция в production ML pipeline
Объяснения нужны не только для аудита — они часть операционного пайплайна.
Кейс из практики: клиент — страховая компания, модель расчёта страховых премий (LightGBM, 120 признаков). Требование: агент должен уметь объяснить клиенту по телефону, из-за чего высокая премия.
Решение: TreeSHAP в inference API. Для каждого предсказания возвращается топ-3 признака с наибольшими SHAP values + автоматический текстовый шаблон. «Ваша премия выше среднего по следующим причинам: возраст автомобиля (влияние +12%), регион регистрации (влияние +8%), история выплат (влияние +6%)».
Latency overhead: 35ms на TreeSHAP при среднем inference 18ms — приемлемо.
Мониторинг: SHAP values логируются в ClickHouse. Раз в неделю агрегируем — drift в распределении SHAP values сигнализирует о feature drift раньше, чем падение AUC.
Ограничения, о которых стоит знать
SHAP ≠ causality. Высокий SHAP value у признака означает корреляцию с предсказанием, а не причинно-следственную связь. «Признак X влияет на предсказание» ≠ «изменение X изменит результат в реальности».
Мультиколлинеарность ломает интерпретацию. Если два признака коррелируют (r > 0.8), SHAP делит их влияние произвольно. При интерпретации результатов нужен анализ корреляции.
Для LLM — оба метода дают грубые оценки. Attention weights более информативны для задач генерации, но тоже не являются строгим proxy для важности.
Сроки: внедрение SHAP/LIME в существующий пайплайн — 1–2 недели. Построение monitoring pipeline с SHAP-based drift detection — 3–4 недели.







