Введение

Всем привет! Меня зовут Анар. Я инженер по машинному обучению и, в качестве подработки, совладелец компании SPUNCH, где имею честь исследовать новые горизонты в области науки о данных :) В этой серии статей я сосредоточусь на реальных случаях из делового мира, которые помогли мне и, надеюсь, помогут и вам.

Хорошо, давайте начнем!

Сегодня я хочу рассказать о достаточно сложном процессе анализа важности признаков после получения результатов модели и инструменте для работы с ним. Этот процесс имеет решающее значение, когда вам нужно:

  1. Улучшите качество модели.
  2. Интерпретируйте вклад функций в модель.
  3. Визуализируйте влияние функций на целевую переменную.
  4. Презентуйте полученные результаты руководству или клиентам.

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

Важность перестановки

Проще говоря, анализ важности функций включает в себя перетасовку значений внутри каждого объекта. Это означает, что вместо таких значений, как b21, b22, у вас будут такие значения, как b24, b29. В этом случае распределение признака остается прежним, но меняется соотношение между значениями признака и классами. Если качество прогнозирования значительно ухудшается после такого изменения признака, можно сделать вывод, что признак очень важен.

Давайте углубимся в код:

  1. Мы создадим синтетические данные для нашей задачи двоичной классификации с двумя признаками и двумя классами: 0 и 1. Вот код Python для генерации этих синтетических данных:
N = 2000
X, y = make_blobs(n_samples=N, n_features=2,
                  cluster_std=4, centers=2,
                  shuffle=True, random_state=42)

2. Давайте разделим их на наборы данных для обучения и проверки:

X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.33, 
                                                      shuffle=True, random_state=42)

3. Давайте инициализируем модель XGBoost (или любую другую модель по вашему выбору) и сделаем прогнозы:

clf = XGBClassifier()
clf.fit(X_train, y_train)

y_valid_pred = clf.predict(X_valid)

print(classification_report(y_valid, y_valid_pred))

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

4. Инициализируем объект класса permutation_importance, которому мы передадим нашу обученную модель, данные проверки, количество таких перестановок и установим случайное_состояние для согласованных результатов:

r = permutation_importance(clf, X_valid, y_valid,
                           n_repeats=30, random_state=42)

# Here we create the list of features for more convenient work with them
features = ['x1', 'x2']

Далее нам необходимо пройтись по полученным результатам и в понятной форме представить информацию:

for el in r.importances_mean.argsort():
  print(f"Importance: {features[el]}", r.importances_mean[el], "Std +/-: ", r.importances_std[el])

В этом выводе мы можем наблюдать среднюю важность каждой функции после 30 итераций перестановок, а также стандартное отклонение значений важности после 30 итераций.

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

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