L'importance des fonctionnalités avec scikit-learn Random Forest montre un écart-type très élevé

13

J'utilise scikit-learn Random Forest Classifier et je veux tracer l'importance des fonctionnalités, comme dans cet exemple .

Cependant, mon résultat est complètement différent, dans le sens où l'écart-type de l'importance des fonctionnalités est presque toujours plus important que l'importance des fonctionnalités elle-même (voir l'image jointe).

importance de la fonctionnalité

Est-il possible d'avoir un tel comportement ou est-ce que je fais des erreurs en le traçant?

Mon code est le suivant:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier

clf = RandomForestClassifier()
clf.fit(predictors.values, outcome.values.ravel())

importance = clf.feature_importances_
importance = pd.DataFrame(importance, index=predictors.columns, 
                          columns=["Importance"])

importance["Std"] = np.std([tree.feature_importances_
                            for tree in clf.estimators_], axis=0)

x = range(importance.shape[0])
y = importance.ix[:, 0]
yerr = importance.ix[:, 1]

plt.bar(x, y, yerr=yerr, align="center")

plt.show()
gc5
la source
IIUC, predictorsrenvoie un élément numpy arrayauquel vous faites référence à un pandas Dataframeobjet par ses colonnes, ce qui est incorrect car numpy arraysil n'a pas d'attribut columns.
Nickil Maveli
Désolé, c'était une faute de frappe sur le code. les prédicteurs et les résultats sont deux pandas DataFramede forme m x net de m x 1. Cela devrait être clair maintenant.
gc5
2
J'ai rencontré les mêmes conclusions il y a quelque temps. Cela pourrait être dû au fait qu'un certain nombre de fonctionnalités sont importantes, mais comme les fonctionnalités peuvent être élevées ou faibles dans l'arbre de décision (car seul un sous-ensemble aléatoire est proposé lors de la séparation), leur importance varie fortement d'un arbre à l'autre. arbre, ce qui entraîne un écart-type élevé.
Archie
Excellent article, j'ai rencontré un problème identique à celui que vous pouvez voir sur la photo. Il existe un package tsfreshqui m'a aidé à identifier les fonctionnalités pertinentes et à réduire mes fonctionnalités de 600+ à environ 400. ! [Mes 35 meilleures fonctionnalités ] ( i.stack.imgur.com/0MROZ.png ) Même avec cela, l'algorithme fonctionne bien pour moi. J'ai une classification binaire, succès / échec. Je n'obtiens pratiquement aucun faux succès, mais je rate un pourcentage considérable de succès. Toutes les suppositions ci-dessus semblent raisonnables. Cela pourrait être le cas, il devrait y avoir un plus grand ensemble de formation et de test. J'ai moins
super

Réponses:

3

Vous utilisez RandomForest avec le nombre d'arbres par défaut, qui est de 10. Pour environ 30 fonctionnalités, c'est trop peu. L'écart type est donc important. Essayez au moins 100 ou même 1000 arbres, comme

clf = RandomForestClassifier(n_estimators=1000)

Pour une analyse plus précise, vous pouvez également vérifier l'ampleur de la corrélation entre vos fonctionnalités.

lanenok
la source
Désolé lanenok, le nombre d'arbres n'est pas celui par défaut. Je mets un exemple de code (et cela est vrai pour tous les paramètres, par exemple min_samples_split) parce que je ne peux pas divulguer les données sur lesquelles je travaille. Cependant, est-ce dû au nombre d'arbres, ainsi qu'à d'autres paramètres, ou est-ce que je fais des erreurs ici?
gc5
2

Votre résultat n'est pas si étrange. Comme l' indique lanenok , vous devez dans un premier temps augmenter le nombre d'arbres afin de vous assurer d'obtenir un résultat «statistique» concernant les importances des fonctionnalités.

Cependant, comme cet article de Genuer et al. (2010) montre que vous pouvez réellement utiliser les écarts-types pour éliminer les fonctionnalités. Pour citer: " Nous pouvons voir que l'écart-type des variables réelles est important par rapport à celui des variables bruyantes, qui est proche de zéro. "

Archie
la source
L'utilisation de l'écart-type dans cet exemple pour éliminer les fonctionnalités éliminerait toutes les fonctionnalités. xD
Jorge Leitao
Haha, je ne suis pas tout à fait sûr, je pense que vous pouvez ignorer les fonctionnalités à l'extrême droite? Quoi qu'il en soit, le principal point que j'essaie de faire est que les écarts-types élevés ne sont pas si étranges et que vous pouvez réellement les utiliser dans votre stratégie pour éliminer les fonctionnalités.
Archie
1

Essayez clf = RandomForestClassifier(max_features=None). Le max_featuresparamètre par défaut 'auto'est équivalent à sqrt(n_features). max_featuresest décrit comme «le nombre de fonctionnalités à prendre en compte lors de la recherche de la meilleure répartition». Le fait de ne regarder qu’un petit nombre de caractéristiques à un moment quelconque de l’arbre de décision signifie que l’importance d’une seule caractéristique peut varier considérablement d’un arbre à l’autre. Donc, ne regardez pas un sous-ensemble aléatoire, regardez simplement toutes les fonctionnalités à chaque niveau de l'arborescence.

jamis
la source
1
Notez que cela équivaut à des arbres en sacs simples. Le «aléatoire» dans les forêts aléatoires signifie considérer un sous-ensemble aléatoire de caractéristiques à chaque division, généralement sqrt(n_features)ou log2(n_features). max_features=Nonene considère plus un sous-ensemble aléatoire de fonctionnalités. Je ne sais pas si cela affecte la solution proposée ci-dessus. Une possibilité est que de nombreuses caractéristiques ont simplement une grande importance et varient donc considérablement à travers l'ensemble des arbres. Ou peut-être qu'il n'y a pas assez d'échantillons et donc toutes les fonctionnalités ne sont pas prises en compte au moment où vous touchez une feuille.
jamis
1

Une raison courante à cela est que les paramètres que vous avez fournis (ou par défaut) RandomForestClassifierne sont pas adaptés à votre ensemble de données.

Une façon courante de résoudre ce problème consiste à rechercher l'espace hyperparamétrique en utilisant, par exemple GridSearchCV:

from sklearn.model_selection import GridSearchCV
from sklearn.metrics import accuracy_score, make_scorer

param_grid = {'n_estimators': [10, 100, 1000], 'max_features': [5, 10, 20, 30]}
clf = GridSearchCV(RandomForestClassifier(), param_grid, cv=5, scoring=make_scorer(accuracy_score))

param_gridvoici les permutations des paramètres que vous souhaitez rechercher, et make_scorer(accuracy_score)la mesure que vous souhaitez optimiser.

Notez que cela accuracy_scoreconvient aux ensembles symétriques, mais pas aux ensembles asymétriques. Choisissez une métrique appropriée pour votre objectif particulier.

Jorge Leitao
la source
0

Il peut y avoir plusieurs raisons. Le nombre d'arbres et la profondeur peuvent changer vos résultats. Si votre modèle ne fonctionne pas bien après avoir sélectionné les paramètres (validation croisée, etc.), c'est probablement parce que vos fonctionnalités ne sont pas très prédictives, donc elles sont choisies presque "au hasard", ce qui conduit à des écarts-types élevés d'arbre en arbre. Mais il existe d'autres possibilités, par exemple, il se pourrait également que vos fonctionnalités soient fortement corrélées. Un peu plus d'informations seraient utiles.

oW_
la source