Полная реализация Python и объяснение вычислений, лежащих в основе измерения важности функций в алгоритмах машинного обучения на основе дерева.
Цель этой статьи — познакомить читателя с тем, как рассчитывается важность признаков в деревьях решений. Лично я не нашел подробного объяснения этой концепции, и поэтому родилась эта статья.
Весь код, использованный в этой статье, находится в открытом доступе, и его можно найти через:
https://github.com/Eligijus112/градиентное повышение
Прежде чем углубиться в расчет важности признаков, я настоятельно рекомендую освежить ваши знания о том, что такое дерево и как мы можем объединить их в случайный лес, используя эти статьи:
Мы будем использовать модель дерева решений, чтобы создать связь между средней ценой на жилье (Y) в Калифорнии с использованием различных регрессоров (X). Набор данных¹ можно загрузить с помощью пакета scikit-learn:
Функции X, которые мы будем использовать в моделях:
* MedInc — средний доход домохозяйства за последние 12 месяцев (сотни тысяч)
* HouseAge — возраст дома (годы)
* AveRooms – среднее количество комнат в жилом доме.
* AveBedrms — среднее количество спален на жилое помещение.
* AveOccup – среднее количество членов домохозяйства.
Переменная ответа Y – это медианная стоимость дома в округах Калифорнии, выраженная в сотнях тысяч долларов.
Форма данных следующая:
Быстрый взгляд на переменные функции:
Распределение переменной Y:
Чтобы анонимизировать данные, в данных есть предел дохода в 500 000 долларов: все, что выше этого, по-прежнему помечается как доход в 500 000 долларов. Это делается для того, чтобы никто не мог идентифицировать конкретное домашнее хозяйство, потому что еще в 1997 году было не так много домашних хозяйств, которые стоили так дорого.
Мы разделим данные на обучающий и тестовый наборы, подгоним модель дерева регрессии и выведем результаты как на обучающем наборе, так и на тестовом наборе.
Распечатки:
Взрослое дерево не перерастает. Эта статья посвящена выводу функций, поэтому мы не будем изо всех сил пытаться уменьшить количество ошибок, а попытаемся сделать вывод, какие функции оказались наиболее влиятельными.
Взрослое дерево на тренировочном наборе:
Дерево решений состоит из узлов,каждый из которых связан правилом разделения. Правило разделения включает функцию и значение, по которому она должна быть разделена.
Термин разделение означает, что если правило разделения выполняется, наблюдение из набора данных идет слева от узла. Если правило не выполняется, наблюдение идет вправо.
Каждый узел нумеруется от 1 до 15.
Давайте рассмотрим первый узел и информацию в нем. Логика для всех узлов будет одинаковой.
MedInc ≤ 5,029 — правило разделения узла. Если наблюдение имеет значение MedInc меньше или равное 5,029, то мы идем по дереву влево (переходим к узлу 2), в противном случае идем к правому узлу (узел номер 3).
squared_error — статистика, используемая в качестве критерия разделения. Squared_error рассчитывается по следующей формуле:
В первом узле статистика равна 1,335.
samples — количество наблюдений в узле. Поскольку это корневой узел, 15480 соответствует всему набору обучающих данных.
value — прогнозируемое значение узла. Другими словами, если путь наблюдения останавливается в этом узле, то прогнозируемое значение для этого узла будет равно 2,074.
Давайте создадим словарь, который содержит все наблюдения во всех узлах:
n_entries = { “node 1”: 15480, “node 2”: 12163, “node 3”: 3317, “node 4”: 5869, “node 5”: 6294, “node 6”: 2317, “node 7”: 1000, “node 8”: 2454, “node 9”: 3415, “node 10”: 1372, “node 11”: 4922, “node 12”: 958, “node 13”: 1359, “node 14”: 423, “node 15”: 577 }
При расчете важности признаков одной из используемых метрик является вероятность попадания наблюдения в определенный узел. Вероятность рассчитывается для каждого узла в дереве решений и рассчитывается просто путем деления количества выборок в узле на общее количество наблюдений в наборе данных (в нашем случае 15480).
Обозначим этот словарь как n_entries_weighted:
n_entries_weighted = { 'node 1': 1.0, 'node 2': 0.786, 'node 3': 0.214, 'node 4': 0.379, 'node 5': 0.407, 'node 6': 0.15, 'node 7': 0.065, 'node 8': 0.159, 'node 9': 0.221, 'node 10': 0.089, 'node 11': 0.318, 'node 12': 0.062, 'node 13': 0.088, 'node 14': 0.027, 'node 15': 0.037 }
Чтобы придать некоторую математическую строгость определению важности признаков, воспользуемся в тексте математическими обозначениями.
Обозначим каждый узел как
У каждого узла, вплоть до конечной глубины, есть левый и правый дочерние элементы. Обозначим их как:
Каждый узел имеет определенные свойства. Обозначим веса, которые мы только что вычислили в предыдущем разделе, как:
Обозначим статистику среднеквадратичной ошибки (MSE) как:
Одним очень важным атрибутом узла, у которого есть дочерние элементы, является так называемая важность узла:
Интуиция вышеприведенного уравнения заключается в том, что если MSE у дочерних элементов мала, то важность узла и особенно его функции правила разделения велика.
Давайте создадим словарь со статистикой MSE каждого узла:
i_sq = { “node 1”: 1.335, “node 2”: 0.832, “node 3”: 1.214, “node 4”: 0.546, “node 5”: 0.834, “node 6”: 0.893, “node 7”: 0.776, “node 8”: 0.648, “node 9”: 0.385, “node 10”: 1.287, “node 11”: 0.516, “node 12”: 0.989, “node 13”: 0.536, “node 14”: 0.773, “node 15”: 0.432 }
Авторы Тревор Хасти, Роберт Тибширани и Джером Фридман в своей замечательной книге Элементы статистического обучения: интеллектуальный анализ данных, вывод и прогнозированиеопределяют вычисление важности признаков с помощью следующего уравнения²:
Где
T — все дерево решений
l — рассматриваемая функция
J — количество внутренних узлов в дереве решений
i² — уменьшение показателя, используемого для разделения
II — индикаторная функция
v(t) — функция, используемая при разделении узла t, используемая при разделении узла.
Интуиция, стоящая за этим уравнением, состоит в том, чтобы суммировать все уменьшения метрики для всех признаков по всему дереву.
Scikit-learn использует предложенную ранее формулу важности узла. Основное отличие состоит в том, что в scikit-learn вводятся веса узлов, которые представляют собой вероятность попадания наблюдения в дерево.
Давайте немного увеличим масштаб и осмотрим узлы с 1 по 3 немного дальше.
Расчет важности узла (и, следовательно, важности функции) выполняется по одному узлу за раз. Последующая логика, объясненная для узла номер 1, верна для всех узлов до уровней ниже.
Только узлы с правилом разделения участвуют в расчете важности функции.
2-й узел является левым дочерним элементом, а 3-й узел — правым дочерним элементом узла номер 1.
Интуиция, стоящая за важностью признаков, начинается с идеи полного сокращения критериев разделения. Другими словами, мы хотим измерить, насколько данный признак и его значение разбиения (хотя само значение нигде не используется) уменьшают в нашем случае среднеквадратичную ошибку в системе. Уравнение важности узла, определенное в разделе выше, отражает этот эффект.
Если мы используем MedInc в корневом узле, 12163 наблюдения будут отправлены на второй узел и 3317 — на правый узел. Это означает, что вес левого узла равен 0,786 (12163/15480), а вес правого узла равен 0,214 (3317/15480). Среднеквадратическая ошибка в левом узле равна 0,892, а в правом узле — 1,214.
Нам нужно рассчитать важность узла:
Теперь мы можем сохранить важность узла в словаре. Ключи словаря — это функции, которые использовались в критериях разделения узла. Значения - это важность узла.
{ "MedInc": 0.421252, "HouseAge": 0, "AveRooms": 0, "AveBedrms": 0, "AveOccup": 0 }
Приведенную выше процедуру расчета необходимо повторить для всех узлов с правилом разделения.
Давайте сделаем еще несколько расчетов узлов, чтобы полностью освоить алгоритм:
Квадрат ошибки, если мы используем функцию MedInc в узле 2:
Словарь важности функций теперь выглядит следующим образом:
{ "MedInc": 0.421 + 0.10758 "HouseAge": 0, "AveRooms": 0, "AveBedrms": 0, "AveOccup": 0 }
{ "MedInc": 0.558, "HouseAge": 0, "AveRooms": 0.018817, "AveBedrms": 0, "AveOccup": 0 }
Мы не можем пойти дальше, потому что узлы 8 и 9 не имеют правила разделения и, следовательно, не уменьшают статистику среднеквадратичной ошибки.
Давайте закодируем реализацию, которая была представлена в разделах выше.
Теперь давайте определим функцию, которая вычисляет важность узла.
Собираем все вместе:
Отпечатки в приведенном выше фрагменте кода:
Node importance: { ‘node 1’: 0.421, ‘node 2’: 0.108, ‘node 3’: 0.076, ‘node 4’: 0.019, ‘node 5’: 0.061, ‘node 6’: 0.025, ‘node 7’: 0.013 } Feature importance before normalization: { ‘MedInc’: 0.618, ‘AveRooms’: 0.019, ‘AveOccup’: 0.086, ‘HouseAge’: 0, ‘AveBedrms’: 0 } Feature importance after normalization: { ‘MedInc’: 0.855, ‘AveRooms’: 0.026, ‘AveOccup’: 0.119, ‘HouseAge’: 0.0, ‘AveBedrms’: 0.0 }
Окончательный словарь признаков после нормализации — это словарь с окончательной важностью признаков. Согласно словарю, наиболее важной функцией является MedInc, за которой следуют AveOccup и AveRooms.
Признаки HouseAge и AveBedrms не использовались ни в одном из правил разделения, поэтому их важность равна 0.
Давайте сравним наш расчет с реализацией расчета важности признаков в scikit-learn.
Печать гласит:
Feature importance by sklearn: { ‘MedInc’: 0.854, ‘HouseAge’: 0.0, ‘AveRooms’: 0.027, ‘AveBedrms’: 0.0, ‘AveOccup’: 0.12 }
Сравнивая с нашими расчетами:
Есть минимальные различия, но они связаны с ошибками округления.
В этой статье я очень подробно продемонстрировал вычисление важности признаков для деревьев решений. Очень похожая логика применяется к деревьям решений, используемым в классификации. Единственная разница заключается в метрике — вместо квадрата ошибки мы используем метрику примесей GINI (или другую метрику, оценивающую классификацию). Все расчеты относительно важности узла остаются прежними.
Я надеюсь, что после прочтения всего этого у вас будет гораздо более четкое представление о том, как интерпретировать и как производятся расчеты относительно важности признаков.
Удачного кодирования!
[1] Автор:Пейс, Р. Келли и Рональд Барри
Год: 1997
Название: Разреженные пространственные авторегрессии
URL: https://archive.ics.uci.edu/ml
Журнал: Письма о статистике и вероятности
[2] Автор:Тревор Хасти, Роберт Тибширани и Джером Фридман
Год: 2017
Название: Элементы статистического обучения: данные Интеллектуальный анализ, логические выводы и прогнозирование
URL: https://archive.ics.uci.edu/ml
Страница: 368–370