Почему после обучения модели почти всегда хочется открыть вопрос «а что было главным»
Как только модель начинает давать приемлемое качество, возникает естественное желание понять, за счет чего она вообще работает. Какие признаки тянут предсказание вверх, какие почти ничего не дают, какие дублируют друг друга. Именно в этой точке появляется feature importance. Это попытка перевести модель из режима «черного ящика» в более читаемую форму.
Но здесь есть важная ловушка. Важность признака — это свойство конкретной модели на конкретных данных при конкретной постановке задачи. Это не универсальная истина про мир и не доказательство причинного влияния.
Что обычно имеется в виду под важностью
$$ importance_j = score(X) - score(X_{perm(j)}) $$В permutation importance важность признака измеряется как падение качества модели после случайного перемешивания одного конкретного столбца. Если качество сильно просело, признак действительно нес полезный сигнал для модели.
importance_j— важность j-го признакаscore(X)— качество модели на исходных данныхscore(X_{perm(j)})— качество после перемешивания значений j-го признака
Эта идея хороша тем, что она не привязана к внутренностям конкретного алгоритма. Мы не спрашиваем модель напрямую, а проверяем, насколько она теряет опору, если один признак испортить.
Почему один и тот же признак может выглядеть по-разному в разных моделях
Потому что важность зависит от того, как именно модель использует пространство признаков. Линейная модель будет смотреть на веса и корреляции. Дерево — на разбиения. Бустинг — на последовательность локальных улучшений. Если признаки сильно коррелируют, один может забрать на себя большую часть важности, а другой при этом выглядеть почти бесполезным, хотя смыслово оба несут похожий сигнал.
Поэтому feature importance нужно читать вместе с пониманием данных, происхождения признаков и устойчивости результата на разных разрезах.
Как посмотреть на это в Python
import pandas as pd # создаем маленькую классификационную задачу с несколькими признаками
from sklearn.ensemble import RandomForestClassifier # используем модель, которая умеет ловить нелинейности
from sklearn.inspection import permutation_importance # оцениваем важность через перемешивание признаков
frame = pd.DataFrame({ # задаем признаки пользователя и target
'sessions': [1, 2, 3, 4, 5, 6, 7, 8], # число сессий
'avg_time': [2, 3, 3, 4, 5, 6, 8, 9], # средняя длительность
'tickets': [3, 2, 2, 1, 1, 1, 0, 0], # обращения в поддержку
'target': [0, 0, 0, 0, 1, 1, 1, 1], # целевой класс
})
X = frame[['sessions', 'avg_time', 'tickets']] # выделяем матрицу признаков
y = frame['target'] # сохраняем target отдельно
model = RandomForestClassifier(n_estimators=200, random_state=42) # обучаем ансамбль деревьев
model.fit(X, y) # подгоняем модель под данные
result = permutation_importance(model, X, y, n_repeats=20, random_state=42) # измеряем падение качества при перемешивании каждого признака
importance = pd.Series(result.importances_mean, index=X.columns).sort_values(ascending=False) # собираем важности в читаемый формат
print(importance.round(3)) # смотрим, какие признаки действительно поддерживают качество моделиЭтот способ полезен тем, что дает читаемую и достаточно честную интерпретацию. Но она все равно должна жить рядом с содержательным вопросом: почему именно этот признак оказался важным и не скрывает ли он более глубокую зависимость в данных.