Метод SHAP (SHapley Additive exPlanations), опирающийся на классическую теорию игр, утвердился в качестве стандарта для оценки значимости признаков в моделях машинного обучения. В задачах бинарной классификации процесс построения графиков waterfall plot или beeswarm plot достаточно тривиален и подробно описан в документации.
Однако при переходе к многоклассовой классификации возникают сложности, связанные с изменением размерности выходных данных. Прямое применение стандартного кода к многомерным выходным данным часто приводит к ошибкам несовпадения размерностей или некорректной интерпретации результатов.
В данной статье рассматриваются технические нюансы работы с SHAP в многоклассовых задачах и предлагается проверенное решение на языке Python. В качестве прикладного примера используется исследование 2025 года, опубликованное в журнале Measurement (Luo et al., "Thermodynamic simulation-assisted random forest: Towards explainable fault diagnosis of combustion chamber components of marine diesel engines"), где авторы реализовали интерпретируемую диагностику 14 категорий состояния судовых двигателей.
Репозиторий проекта на GitHub: https://github.com/TS-RF/TSRF
1. Технические особенности обработки тензоров
Основное препятствие при переходе от бинарных моделей к многоклассовым заключается в структуре переменной shap_values.
Бинарная классификация или регрессия: Переменная shap_values представляет собой матрицу размерностью (n_samples, n_features). Каждое значение является скаляром, отражающим вклад признака в прогноз.
Многоклассовая классификация: shap_values преобразуется в трехмерный тензор (или список матриц) размерностью (n_samples, n_features, n_classes).
Логическое различие: В многоклассовых моделях выходной слой генерирует не одно значение, а распределение вероятностей (или логитов) по всем классам. Следовательно, SHAP вычисляет вклад каждого признака отдельно для каждого целевого класса. Если передать трехмерный массив в функцию визуализации без предварительной обработки, интерпретатор не сможет определить, для какого именно класса требуется построить график, что приведет к исключению.
2. Реализация послойной визуализации
Для корректной работы требуется выполнить срез данных (slicing) по оси классов. Ниже представлена программная реализация, адаптированная под требования научных публикаций.

2.1 Глобальный анализ распределения признаков
Различные методы визуализации в библиотеке SHAP предъявляют разные требования к формату входных данных:
shap.plots.waterfall: требует объект Explanation, содержащий базовые значения и данные.
shap.summary_plot: лучше работает с массивами формата numpy.array.
import shap import matplotlib.pyplot as plt import numpy as np # Настройки графиков для соответствия академическим стандартам plt.rcParams['font.family'] = 'Arial' plt.rcParams['font.size'] = '24' plt.rcParams['axes.unicode_minus'] = False # Предполагается, что best_model — обученная модель (Random Forest, XGBoost и т.д.) # X_train, X_test — соответствующие наборы данных Pandas DataFrame # 1. Расчет значений SHAP в формате Numpy (для глобального анализа) explainer_tree = shap.TreeExplainer(best_model) shap_values_numpy = explainer_tree.shap_values(X_train) # В многоклассовых задачах это обычно список массивов длиной n_classes # 2. Создание объекта Explanation (для локального анализа, например, waterfall plot) explainer_obj = shap.Explainer(best_model, X_test) shap_values_obj = explainer_obj(X_test) # Размерность shap_values_obj.values: (n_samples, n_features, n_classes)
2.2 Локальная интерпретация: целевой график Waterfall
График waterfall plot используется для объяснения причин прогноза конкретного класса для отдельно взятого образца. Необходимо зафиксировать индекс класса через срез [:, class_idx].
# --- (a) Waterfall Plot: атрибуция для одного образца --- class_idx = 4 # Индекс целевого класса (например, тип неисправности F4) sample_idx = 3 # Индекс конкретного образца plt.figure() # Срез объекта Explanation для конкретного образца и класса shap.plots.waterfall( shap_values_obj[sample_idx, :, class_idx], max_display=9, show=False ) # Оформление графика ax = plt.gca() ax.set_xlabel(ax.get_xlabel(), fontsize=36) ax.set_ylabel(ax.get_ylabel(), fontsize=36) ax.spines['bottom'].set_linewidth(3) plt.show()
2.3 Глобальная интерпретация: Beeswarm Plot
График beeswarm plot демонстрирует общее распределение влияния признаков на выход модели. Для многоклассовых задач данные передаются в виде shap_values_numpy[..., class_idx].
# --- (b) Beeswarm Plot: глобальное распределение признаков --- class_idx = 5 plt.figure(figsize=(10, 8)) shap.summary_plot( shap_values_numpy[..., class_idx], X_train, feature_names=X_train.columns, plot_type="dot", show=False ) # Настройка цветовой шкалы (Color Bar) cbar = plt.gcf().axes[-1] cbar.set_ylabel('Parameter Value', fontsize=24) cbar.tick_params(labelsize=20) plt.show()
2.4 Комбинированная визуализация: важность и распределение
В статьях высокого уровня часто объединяют столбчатую диаграмму важности и график beeswarm plot. Это достигается через использование двойной оси (twiny) в matplotlib.
# --- (c) Составной график (Beeswarm + Bar Importance) --- class_idx = 5 fig, ax1 = plt.subplots(figsize=(10, 8)) # 1. Отрисовка beeswarm plot (основной слой) shap.summary_plot( shap_values_numpy[..., class_idx], X_train, feature_names=X_train.columns, plot_type="dot", show=False, color_bar=True ) plt.gca().set_position([0.2, 0.2, 0.65, 0.65]) # 2. Отрисовка столбчатой диаграммы важности на вторичной оси ax2 = ax1.twiny() shap.summary_plot( shap_values_numpy[..., class_idx], X_train, plot_type="bar", show=False ) plt.gca().set_position([0.2, 0.2, 0.65, 0.65]) # Настройка прозрачности столбцов bars = ax2.patches for bar in bars: bar.set_color('#CCE5FB') bar.set_alpha(0.4) # Стандартизация подписей осей ax1.set_xlabel(f'Shapley Value Contribution (F{class_idx})', fontsize=24, labelpad=5) ax2.set_xlabel('Mean Shapley Value (Parameter Importance)', fontsize=24, labelpad=10) ax2.xaxis.set_label_position('top') ax2.xaxis.tick_top() # Управление слоями: точки должны быть поверх столбцов ax1.set_zorder(ax1.get_zorder() + 1) ax1.patch.set_visible(False) plt.show()
3. Литература
При использовании SHAP для многоклассовых задач ключевыми являются следующие аспекты:
Контроль размерности: необходимо учитывать трехмерную структуру тензора значений SHAP и использовать срезы [..., class_idx] для анализа конкретных классов.
Совместимость интерфейсов: следует различать использование объектов Explanation для локальных графиков и массивов Numpy для глобальных сводных диаграмм.
Информативность визуализации: применение комбинированных графиков позволяет наглядно представить как среднюю важность признаков, так и характер их влияния на прогноз, что соответствует стандартам ведущих научных журналов.
[1] Luo C, Zhao M, Fu X, et al. Thermodynamic simulation-assisted random forest: Towards explainable fault diagnosis of combustion chamber components of marine diesel engines[J]. Measurement, 2025, 251: 117252.
