Як визначаються особливості_визначення в RandomForestClassifier?


125

У мене є завдання класифікації із тимчасовим рядом як введення даних, де кожен атрибут (n = 23) являє собою певний момент часу. Окрім абсолютного результату класифікації, я хотів би з’ясувати, які ознаки / дати сприяють результату в якій мірі. Тому я просто використовую те feature_importances_, що добре працює для мене.

Однак я хотів би знати, як вони розраховуються та який міра / алгоритм використовується. На жаль, я не зміг знайти жодної документації на цю тему.


10
Вау три основні диски на одну нитку SO. Це має бути якийсь запис ^^
Андреас Мюллер

Відповіді:


158

Дійсно є декілька способів отримати функції "імпорт". Як часто, немає жорсткого консенсусу щодо того, що означає це слово.

У науці-науці ми реалізуємо важливість, описану в [1] (часто цитується, але, на жаль, рідко читається ...). Іноді його називають "значення джині" або "середнє зменшення домішки" і визначається як загальне зменшення домішки вузла (зважене на ймовірність досягнення цього вузла (яке приблизно оцінюється на частку зразків, що досягають цього вузла)) у середньому по всіх дерева ансамблю.

У літературі або в деяких інших пакетах ви також можете знайти імпорт функцій, реалізований як "середня точність зниження". В основному, ідея полягає в вимірюванні зниження точності даних OOB, коли ви випадково переставляєте значення для цієї функції. Якщо зниження низьке, то функція не важлива, і навпаки.

(Зверніть увагу, що обидва алгоритми доступні у пакеті randomForest R.)

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


48
Це може бути чудово, якби ця відповідь була зазначена в документації про важливі атрибути / приклад. Нещодавно шукали його :)
d1337

2
Здається, оцінка важливості є відносною? Наприклад, сума балів важливості всіх функцій завжди 1 (див. Приклад тут scikit-learn.org/stable/auto_examples/ensemble/… )
РНК,

5
@RNA: Так, імпорт змінних за замовчуванням нормалізується в scikit-learn, так що вони дорівнюють одиниці. Ви можете обійти це, переглянувши окремі базові оцінки та зателефонувавши tree_.compute_feature_importances(normalize=False).
Gilles Louppe

2
@GillesLouppe Чи використовуєте ви зразки мішків для вимірювання зменшення МСЕ для лісу регресорів дерев рішень у кожному дереві? Або всі дані тренувань, які використовуються на дереві?
Кокс

1
Два корисні ресурси. (1) blog.datadive.net/… блог Андо Саабас реалізує як "середнє зниження домішки", так і "середнє зниження точності", про що згадував Жилль. (2) Завантажте та прочитайте дисертацію Гілла Луппа.
Марк Тіз

54

Звичайний спосіб обчислення значень важливості функції одного дерева полягає в наступному:

  1. ви ініціалізуєте масив feature_importancesусіх нулів з розміром n_features.

  2. Ви переходите по дереву: для кожного внутрішнього вузла, який розбивається за функцією, iви обчислюєте зменшення помилок цього вузла, помножене на кількість зразків, які були перенаправлені до вузла, і додаєте цю кількість до feature_importances[i].

Зменшення помилок залежить від критерію домішки, який ви використовуєте (наприклад, Джині, Ентропія, MSE, ...). Це домішка набору прикладів, яка потрапляє на внутрішній вузол за мінусом суми домішок двох розділів, створених розщепленням.

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

Наскільки мені відомо, існують альтернативні способи обчислення значень важливості функції в деревах рішень. Короткий опис вищевказаного методу можна знайти в «Елементах статистичного навчання» Тревора Хасті, Роберта Тібширані та Джерома Фрідмана.


12

Це співвідношення між кількістю проб, направлених до вузла рішення, що включає цю особливість у будь-якому з дерев ансамблю, над загальною кількістю зразків у навчальному наборі.

Особливості, які задіяні у вузлах верхнього рівня дерев рішень, як правило, бачать більше зразків, отже, ймовірно, вони матимуть більше значення.

Редагувати : цей опис лише частково правильний: відповіді Гілла та Пітера - правильна відповідь.


1
Чи знаєте ви, чи є якийсь папір / документація про точний метод? напр. Брейман, 2001. Було б чудово, якби у мене був якийсь належний документ, який я міг би навести за методологією.
user2244670

@ogrisel, було б чудово, якби ви могли чітко позначити свою відповідь як пояснення "зважування". Само вагоме значення не визначає важливості функції. "Показник домішки" ("важливість джині" або RSS) у поєднанні з вагами, усередненими по деревах визначає загальну важливість функції. На жаль, документація про scikit-learn тут: scikit-learn.org/stable/modules/… не є точною і неправильно зазначає "глибину" як метрику домішок.
Аріель

11

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

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

Якщо вам цікаво, я написав невеликий пакет, який реалізує метрику важливості перестановки і може бути використаний для обчислення значень з екземпляра випадкового лісового класу scikit:

https://github.com/pjh2011/rf_perm_feat_import

Редагувати: Це працює для Python 2.7, а не 3


Привіт @Peter, коли я використовую ваш код, я отримую цю помилку: NameError: ім'я 'xrange' не визначено.
Aizzaac

Привіт @Aizzaac. Вибачте, я новачок у написанні пакунків, тому я повинен був зазначити, що написав це для Python 2.7. Спробуйте def xrange (x): поверніть ітер (діапазон (x)) перед його запуском
Пітер

2

Дозвольте спробувати відповісти на запитання. код:

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)))

Отримуємо особливість-значення: np.array ([0,1.332,6.418,92.30]).
Після нормалізації ми можемо отримати масив ([0., 0.01331334, 0.06414793, 0.92253873]), це те саме, що clf.feature_importances_.
Будьте уважні, всі класи повинні мати вагу.


1

Для тих, хто шукає посилання на документацію scikit-learn на цю тему або посилання на відповідь від @GillesLouppe:

У RandomForestClassifier estimators_атрибут - це список рішенняTreeClassifier (як зазначено в документації ). Для того, щоб обчислити feature_importances_RandomForestClassifier, у вихідному коді scikit-learn він в середньому оцінюється за всіма feature_importances_атрибутами оцінювача (усі рішенняTreeClassifer) в ансамблі.

У документації Рішення Дерево Класифікера згадується, що "Важливість ознаки обчислюється як (нормалізоване) загальне зниження критерію, приведеного цією ознакою. Також воно відоме як важливість Джині [1]".

Ось пряме посилання для отримання додаткової інформації про змінну та важливість Джині, як це надано в посиланнях scikit-learn нижче.

[1] Л. Брейман та А. Катлер, “Випадкові ліси”, http://www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.