Время прочтения: 8 мин.

Библиотека scikit-learn для многих профессионалов в области машинного обучения является своего рода «lingua franca» (международный язык, на котором говорят и которому учатся по всему миру), без которой не обойтись. Но, в тоже время, она имеет ряд таких недостатков, как отсутствие объяснения выбранных весов в моделях машинного обучения и сделанных этими моделями прогнозов. Компенсировать это обстоятельство пытается библиотека eli5.

eli5 означает «объясни, как будто мне 5». Использование этого термина обычно предполагает объяснение сложной или непонятной темы простыми словами, таким образом, чтобы это мог понять даже пятилетний ребенок. Однако это сокращение редко используется буквально, eli5 означает ответ на вопрос через понятные читателю термины.

eli5 эта библиотека по выводу классификаторов и объяснению их предсказаний. eli5 работает с такими библиотеками машинного обучения, как:

  • Scikit-learn
  • XGBoost
  • CatBoost
  • Keras
  • lightning
  • LightGBM
  • sklearn-crfsuite

Как установить библиотеку eli5?

! pip install eli5

Импортируем библиотеку eli5

import eli5

Далее о том, как использовать Python-библиотеки eli5 для анализа двух типов моделей: линейной регрессии и решающего дерева, а также о том, как библиотека eli5 представляет параметры этих моделей на известных датасетах.

1. Линейная регрессия

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

Описание признаков датасета boston:

ZN: Proportion of residential land zoned for lots over 25,000 sq. ft

INDUS: Proportion of non-retail business acres per town

CHAS: Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)

NOX: Nitric oxide concentration (parts per 10 million)

RM: Average number of rooms per dwelling

AGE: Proportion of owner-occupied units built prior to 1940

DIS: Weighted distances to five Boston employment centers

RAD: Index of accessibility to radial highways

TAX: Full-value property tax rate per $10,000

PTRATIO: Pupil-teacher ratio by town

B: 1000(Bk — 0.63)², where Bk is the proportion of [people of African American descent] by town

LSTAT: Percentage of lower status of the population

MEDV: Median value of owner-occupied homes in $1000s

#загрузка библиотеки
import numpy as np
from sklearn import datasets, linear_model, metrics
  
# загрузка датасета Бостон
boston = datasets.load_boston(return_X_y=False)
  
# определение матрицы признаков Х и результирующего набора y
X = boston.data
y = boston.target
  
# разбивка X и y на тестовую и обучающую части
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4,
                                                    random_state=1)
  
# создание объекта линейной регрессии
reg = linear_model.LinearRegression()
  
# тренировка модели на обучающем множестве
reg.fit(X_train, y_train)

Библиотека eli5 имеет два общих метода, которые могут использоваться в разных моделях:

  • show_weights() — отображает значение весов признаков модели в виде HTML-таблицы, текста и т.д. Они, как правило, такие же, как coef_ и featureimportances, используемые с линейными, древовидными или ансамблевыми оценками sklearn;
  • show_prediction() — отображает производительность оценщика для конкретного образца в виде HTML-таблицы, дерева, текста и т.д.

Первый метод, который я рассмотрю с использованием eli5 – это show_weights().

Ниже приведен список важных параметров метода show_weights(), которые могут быть сгенерированы этим методом:

  • feature_names: принимает список строк, определяющих имена объектов;
  • top: принимает кортеж int или (pos:int, neg:int). Отображает признаки с наибольшим по абсолюту значением. Если используется кортеж чисел (pos, neg), выведется количество признаков с не большим количеством положительных признаков и не большим количеством отрицательных признаков;   
  • target_names: принимает значения в виде списка строк или словаря с отображением старых целевых имен на новые целевые имена. Этот параметр принимает список имен объектов, для которых мы хотим видеть отображаемые веса. Это может быть полезно, если в нашей задаче классификации много классов, и мы хотим видеть веса только нескольких из них;
  • feature_re: принимает строку, определяющую регулярное выражение, которое позволяет выбирать имена объектов, удовлетворяющие критериям этого регулярного выражения.

Сформирую таблицу с признаками, каждому из которых задан определенный вес:

from eli5 import show_weights

show_weights(reg, feature_names=boston.feature_names)

Полученные значения говорят о том, какое влияние на предсказание в среднем оказывает каждый признак, а знак показывает в каком направлении оказывается это влияние. Как видно, наибольший вклад вносит BIAS (+33,79), наименьший – NO (-17,205), все показатели упорядочены по значению весов. Под <BIAS> понимается ожидаемый средний выход модели, основанный на распределении обучающего множества.

Выберу семь наиболее перспективных признаков в модели линейной регрессии по абсолютному значению весов.

show_weights(reg, feature_names=boston.feature_names, top=7)

Для вывода трех наибольших положительных признаков и одного наименьшего отрицательного можно использовать команду:

show_weights(reg, feature_names=boston.feature_names, top=(3,1))

Второй важный метод, который предоставляет eli5 – это show_prediction(), который можно использовать, чтобы показать, какой вклад вносит отдельный признак при составлении прогноза для конкретной выборки. Это может дать больше информации о том, как работает модель для конкретной выборки данных. Ниже представлена случайная выборка из тестовых данных, а затем построение графика того, как отдельные функции влияют на прогнозирование выходных данных для этой случайной выборки вместе со значениями функций в виде HTML-таблицы.

Метод show_prediction() имеет те же параметры, что и show_weights(), и несколько дополнительных. Ниже выделю все параметры с описанием только для новых параметров:

  • top_targets: имеет то же значение, что и в show_weights();
  • target_names: имеет то же значение, что и в show_weights();
  • feature_names: имеет то же значение, что и в show_weights();
  • feature_re: имеет то же значение, что и в show_weights();
  • horizontal_layout: принимает значение bool. Если установлено значение True, то таблицы весов объектов располагаются горизонтально, а в случае False – вертикально;
  • highlight_spaces: принимает значение bool, указывающее, следует ли выделять пространство между объектами при выделении текстовых данных или нет;
  • force_weights: принимает значение bool, указывающее, показывать ли таблицу весов, если объекты уже выделены в текстовом представлении;
  • preserve_density: при работе с текстовыми данными принимает значение bool, задающее интенсивность цвета образца текста;
  • show_feature_values: принимает значение bool, указывающее, должны ли значения объектов отображаться вместе с весами в таблице или нет.

Вывод объяснения предсказаний эстиматора:

from eli5 import show_prediction
import random

rand = random.randint(1, len(X_test))
print("Actual Target Value : ", y_test[rand])

show_prediction(reg, X_test[rand], feature_names=boston.feature_names, show_feature_values=True)

Actual Target Value :  21.5 
y (score 24.160) top features

Данная команда выводит топ-5 по модулю предсказанных признаков.

show_prediction(lr,X_test[rand],feature_names=boston.feature_names, show_feature_values=True, top=5)
y (score 24.160) top features

Если проанализировать полученные выше значения, то можно сделать вывод, что признаки NOX, RM, PTRATIO, LSTAT, AGE являются основными при прогнозировании цены на жилье. Благодаря их использованию в качестве основных признаков можно построить модель линейной регрессии, которая с высокой точностью предсказывает цены на жилье в городе Бостон.

2.  Модель решающего дерева.

Построю модель решающего дерева по датасету ирисы Фишера для решения задачи классификации цветов.

Создание модели решающего дерева.

# Импорт библиотеки
from sklearn.datasets import load_iris
from sklearn import tree

# Загрузка датасета
iris = load_iris()

# Определение переменных X и y
X, y = iris.data, iris.target

# Определение классификатора решающего дерева
clf = tree.DecisionTreeClassifier()

# Обучение модели на данных
clf = clf.fit(X, y)

Структура датасета:

1. sepal length in cm
2. sepal width in cm
3. petal length in cm
4. petal width in cm
5. class:
— Iris Setosa
— Iris Versicolour
— Iris Virginica

show_weights(clf, feature_names=iris.feature_names,
             show=["feature_importances"]) 

Наиболее информативным признаком при разделении на классы является petal width in cm 0,9226.

Построю диаграмму дерева решений:

show_weights(clf, feature_names=iris.feature_names,-
             show=["decision_tree", "method", "description"])
from eli5 import show_prediction
import random
rand = random.randint(1, len(X))

print("Actual Target Value : ", y[rand])

show_prediction(clf,
                X[rand],
                feature_names=iris.feature_names,
                show_feature_values=True,
                )

Представленный код выводит коэффициенты модели с объяснением действий самой модели.

from eli5.sklearn import explain_prediction

rand = random.randint(1, len(X))
print("Actual Target Value : ", iris.target_names[y[rand]])

explanation = explain_prediction.explain_prediction_tree_classifier(clf, X[rand],
                                                     targets=[0,1,2], target_names=iris.target_names,
                                                     feature_names=iris.feature_names
                                                      )

from eli5.formatters import format_as_html
from IPython.display import HTML

HTML(format_as_html(explanation))

В полученной таблице представлены классы ирисов с наибольшим / наименьшим выраженным значением признаков. При решении задачи классификации, благодаря пакету eli5, у класса ирисов setosa выявлено, что наиболее значимым признаком является petal width -0,333, по классу versicolor этот признак +0,595, а также признак petal length c +0,072. По классу virginica оба признака petal length и petal width идут с отрицательными знаком ‑0,072 и -0,262, соответственно. Представленные комбинации признаков позволяют классифицировать наблюдения на три вида ирисов.

Вывод:

Основное внимание в своем посте я уделил двум основным алгоритмам show_weights() и show_prediction() библиотеки eli5, благодаря которым можно выбрать наиболее информативные признаки. Я рассказал об использовании данных алгоритмов в моделях линейной регрессии и решающих деревьев.

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