Подтвердить что ты не робот

Как определяются значения feature_importances в RandomForestClassifier?

У меня есть задача классификации с временным рядом в качестве ввода данных, где каждый атрибут (n = 23) представляет собой конкретный момент времени. Помимо абсолютного результата классификации, я хотел бы узнать, какие атрибуты/даты вносят вклад в результат. Поэтому я просто использую feature_importances_, который хорошо работает для меня.

Однако я хотел бы знать, как они вычисляются и какой метод измерения/алгоритма используется. К сожалению, я не смог найти документацию по этой теме.

4b9b3361

Ответ 1

Есть действительно несколько способов получить функцию "значения". Как часто, нет строгого консенсуса относительно того, что означает это слово.

В scikit-learn мы реализуем важность, как описано в [1] (часто цитируется, но, к сожалению, редко читается...). Его иногда называют "существенным значением" или "средним уменьшением примеси" и определяется как полное уменьшение примеси node (взвешенное по вероятности достижения этого node (которое приближается к доле образцов, достигающих этого node)), усредненная по всем деревьям ансамбля.

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

(Обратите внимание, что оба алгоритма доступны в пакете randomForest R.)

[1]: Брейман, Фридман, "Деревья классификации и регрессии", 1984 год.

Ответ 2

Обычный способ вычисления значений важности функции для одного дерева выглядит следующим образом:

  • вы инициализируете массив feature_importances всех нулей размером n_features.

  • вы пересекаете дерево: для каждого внутреннего node, который разбивается на функцию i, вы вычисляете уменьшение ошибки этого node, умноженное на количество выборок, которые были перенаправлены на node и добавлены эта величина равна feature_importances[i].

Уменьшение ошибок зависит от используемого вами критерия примеси (например, Gini, Entropy, MSE,...). Его примесь множества примеров, которые направляются во внутреннее node за вычетом суммы примесей двух разделов, созданных расколом.

Важно, чтобы эти значения относились к определенному набору данных (как уменьшение ошибок, так и количество выборок - это набор данных), поэтому эти значения не могут сравниваться между различными наборами данных.

Насколько я знаю, существуют альтернативные способы вычисления значений значения важности в деревьях решений. Краткое описание вышеупомянутого метода можно найти в "Элементах статистического обучения" Тревора Хасти, Роберта Тиббирани и Джерома Фридмана.

Ответ 3

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

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

Изменить: это описание является лишь частично правильным: ответы Гилла и Питера - правильный ответ.

Ответ 4

Как отметил @GillesLouppe выше, scikit-learn в настоящее время реализует метрику "среднего уменьшения примеси" для характеристик признаков. Я лично считаю вторую метрику более интересной, когда вы произвольно переставляете значения для каждой из своих функций один за другим и видите, насколько хуже ваша производительность вне пакета.

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

Если вам интересно, я написал небольшой пакет, который реализует метрику значения перестановки и может использоваться для вычисления значений из экземпляра класса случайных лекций scikit-learn:

https://github.com/pjh2011/rf_perm_feat_import

Изменение: это работает для Python 2.7, а не 3

Ответ 5

Позвольте мне ответить на вопрос. код:

iris = datasets.load_iris()  
X = iris.data  
y = iris.target  
clf = DecisionTreeClassifier()  
clf.fit(X, y)  

Участок принятия решения:
введите описание изображения здесь
Мы можем получить compute_feature_importance: [0. , 0.01333333,0.06405596,0.92261071]
Проверьте исходный код:

cpdef compute_feature_importances(self, normalize=True):
    """Computes the importance of each feature (aka variable)."""
    cdef Node* left
    cdef Node* right
    cdef Node* nodes = self.nodes
    cdef Node* node = nodes
    cdef Node* end_node = node + self.node_count

    cdef double normalizer = 0.

    cdef np.ndarray[np.float64_t, ndim=1] importances
    importances = np.zeros((self.n_features,))
    cdef DOUBLE_t* importance_data = <DOUBLE_t*>importances.data

    with nogil:
        while node != end_node:
            if node.left_child != _TREE_LEAF:
                # ... and node.right_child != _TREE_LEAF:
                left = &nodes[node.left_child]
                right = &nodes[node.right_child]

                importance_data[node.feature] += (
                    node.weighted_n_node_samples * node.impurity -
                    left.weighted_n_node_samples * left.impurity -
                    right.weighted_n_node_samples * right.impurity)
            node += 1

    importances /= nodes[0].weighted_n_node_samples

    if normalize:
        normalizer = np.sum(importances)

        if normalizer > 0.0:
            # Avoid dividing by zero (e.g., when root is pure)
            importances /= normalizer

    return importances

Попробуйте вычислить значение функции:

print("sepal length (cm)",0)
print("sepal width (cm)",(3*0.444-(0+0)))
print("petal length (cm)",(54* 0.168 - (48*0.041+6*0.444)) +(46*0.043 -(0+3*0.444)) + (3*0.444-(0+0)))
print("petal width (cm)",(150* 0.667 - (0+100*0.5)) +(100*0.5-(54*0.168+46*0.043))+(6*0.444 -(0+3*0.444)) + (48*0.041-(0+0)))

Мы получаем feature_importance: np.array([0,1.332,6.418,92.30]).
После нормализации мы можем получить массив ([0., 0.01331334, 0.06414793, 0.92253873]), это то же самое, что и clf.feature_importances_.
Будьте осторожны, все классы должны иметь вес один.

Ответ 6

Для тех, кто ищет ссылку на документацию scikit-learn по этой теме или ссылку на ответ от @GillesLouppe:

В RandomForestClassifier, estimators_ атрибут является список DecisionTreeClassifier (как указано в документации). Чтобы вычислить feature_importances_ для RandomForestClassifier, в исходном коде scikit-learn, он усредняет по всем признакам (всем DecisionTreeClassifer) атрибутам feature_importances_ в ансамбле.

В документации DecisionTreeClassifer упоминается, что "важность функции вычисляется как (нормализованное) полное снижение критерия, приносимого этой особенностью. Она также известна как значение Gini [1]".

Вот прямая ссылка для получения дополнительной информации о переменной и важности Gini, как указано в ссылке scikit-learn ниже.

[1] Л. Брейман и А. Катлер, "Случайные леса", http://www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm