Puis-je extraire les règles de décision sous-jacentes (ou «chemins de décision») à partir d'un arbre formé dans un arbre de décision sous forme de liste textuelle?
Quelque chose comme:
if A>0.4 then if B<0.2 then if C>0.8 then class='X'
Merci de votre aide.
Réponses:
Je pense que cette réponse est plus correcte que les autres réponses ici:
Cela imprime une fonction Python valide. Voici un exemple de sortie pour un arbre qui tente de renvoyer son entrée, un nombre compris entre 0 et 10.
Voici quelques pierres d'achoppement que je vois dans d'autres réponses:
tree_.threshold == -2
pour décider si un nœud est une feuille n'est pas une bonne idée. Et si c'était un vrai nœud de décision avec un seuil de -2? Au lieu de cela, vous devriez regardertree.feature
outree.children_*
.features = [feature_names[i] for i in tree_.feature]
plante avec ma version de sklearn, car certaines valeurs detree.tree_.feature
sont -2 (spécifiquement pour les nœuds feuilles).la source
print "{}return {}".format(indent, tree_.value[node])
doit être remplacé parprint "{}return {}".format(indent, np.argmax(tree_.value[node][0]))
pour que la fonction renvoie l'index de classe.RandomForestClassifier.estimators_
, mais je n'ai pas pu trouver comment combiner les résultats des estimateurs.print "bla"
=>print("bla")
J'ai créé ma propre fonction pour extraire les règles des arbres de décision créés par sklearn:
Cette fonction commence par les nœuds (identifiés par -1 dans les tableaux enfants), puis trouve récursivement les parents. J'appelle cela la «lignée» d'un nœud. En cours de route, je saisis les valeurs dont j'ai besoin pour créer une logique SAS if / then / else:
Les ensembles de tuples ci-dessous contiennent tout ce dont j'ai besoin pour créer des instructions SAS if / then / else. Je n'aime pas utiliser des
do
blocs dans SAS, c'est pourquoi je crée une logique décrivant le chemin complet d'un nœud. Le seul entier après les tuples est l'ID du nœud terminal dans un chemin. Tous les tuples précédents se combinent pour créer ce nœud.la source
(0.5, 2.5]
. Les arbres sont réalisés avec un partitionnement récursif. Rien n'empêche une variable d'être sélectionnée plusieurs fois.J'ai modifié le code soumis par Zelazny7 pour imprimer un pseudocode:
si vous appelez
get_code(dt, df.columns)
le même exemple vous obtiendrez:la source
(threshold[node] != -2)
à( left[node] != -1)
(similaire à la méthode ci-dessous pour obtenir les identifiants des nœuds enfants)Scikit learn a introduit une nouvelle méthode délicieuse appelée
export_text
dans la version 0.21 (mai 2019) pour extraire les règles d'un arbre. Documentation ici . Il n'est plus nécessaire de créer une fonction personnalisée.Une fois que vous avez adapté votre modèle, il vous suffit de deux lignes de code. Tout d'abord, importez
export_text
:Deuxièmement, créez un objet qui contiendra vos règles. Pour rendre les règles plus lisibles, utilisez l'
feature_names
argument et transmettez une liste de vos noms de fonctionnalités. Par exemple, si votre modèle est appelémodel
et que vos entités sont nommées dans un dataframe appeléX_train
, vous pouvez créer un objet appelétree_rules
:Ensuite, imprimez ou enregistrez simplement
tree_rules
. Votre sortie ressemblera à ceci:la source
Il existe une nouvelle
DecisionTreeClassifier
méthode ,,decision_path
dans la version 0.18.0 . Les développeurs fournissent une procédure pas à pas détaillée (bien documentée) .La première section de code de la procédure pas à pas qui imprime la structure arborescente semble être correcte. Cependant, j'ai modifié le code dans la deuxième section pour interroger un échantillon. Mes changements indiqués par
# <--
Modifier Les modifications marquées par
# <--
dans le code ci-dessous ont depuis été mises à jour dans le lien de visite virtuelle après que les erreurs aient été signalées dans les demandes d'extraction # 8653 et # 10951 . C'est beaucoup plus facile à suivre maintenant.Modifiez le
sample_id
pour afficher les chemins de décision des autres échantillons. Je n'ai pas interrogé les développeurs sur ces changements, je me suis simplement senti plus intuitif en travaillant sur l'exemple.la source
Vous pouvez voir un arbre digraph. Ensuite,
clf.tree_.feature
etclf.tree_.value
sont respectivement un tableau de fonctions de division de nœuds et un tableau de valeurs de nœuds. Vous pouvez vous référer à plus de détails à partir de cette source github .la source
Juste parce que tout le monde a été si utile, je vais juste ajouter une modification aux belles solutions de Zelazny7 et Daniele. Celui-ci est pour python 2.7, avec des onglets pour le rendre plus lisible:
la source
Les codes ci-dessous sont mon approche sous anaconda python 2.7 plus un nom de package "pydot-ng" pour créer un fichier PDF avec des règles de décision. J'espère que c'est utile.
une représentation graphique d'arbre ici
la source
J'ai vécu cela, mais j'avais besoin que les règles soient écrites dans ce format
J'ai donc adapté la réponse de @paulkernfeld (merci) que vous pouvez personnaliser à votre besoin
la source
Voici un moyen de traduire l'ensemble de l'arbre en une seule expression python (pas nécessairement trop lisible par l'homme) à l'aide de la bibliothèque SKompiler :
la source
Cela s'appuie sur la réponse de @paulkernfeld. Si vous avez une dataframe X avec vos fonctionnalités et une dataframe cible y avec vos réponses et que vous souhaitez avoir une idée de la valeur y terminée dans quel nœud (et aussi de la tracer en conséquence), vous pouvez faire ce qui suit:
pas la version la plus élégante mais elle fait le travail ...
la source
C'est le code dont vous avez besoin
J'ai modifié le code préféré pour indenter correctement dans un notebook jupyter python 3
la source
Voici une fonction, imprimant les règles d'un arbre de décision scikit-learn sous python 3 et avec des décalages pour les blocs conditionnels pour rendre la structure plus lisible:
la source
Vous pouvez également le rendre plus informatif en le distinguant à quelle classe il appartient ou même en mentionnant sa valeur de sortie.
la source
Voici mon approche pour extraire les règles de décision sous une forme qui peut être utilisée directement dans SQL, afin que les données puissent être regroupées par nœud. (Basé sur les approches des affiches précédentes.)
Le résultat sera des
CASE
clauses ultérieures qui peuvent être copiées dans une instruction SQL, ex.SELECT COALESCE(*CASE WHEN <conditions> THEN > <NodeA>*, > *CASE WHEN <conditions> THEN <NodeB>*, > ....)NodeName,* > FROM <table or view>
la source
Vous pouvez maintenant utiliser export_text.
Un exemple complet de [sklearn] [1]
la source
Modification du code de Zelazny7 pour récupérer SQL à partir de l'arbre de décision.
la source
Apparemment, il y a longtemps, quelqu'un a déjà décidé d'essayer d'ajouter la fonction suivante aux fonctions d'exportation d'arborescence officielle de scikit (qui ne supporte fondamentalement que export_graphviz)
Voici son engagement complet:
https://github.com/scikit-learn/scikit-learn/blob/79bdc8f711d0af225ed6be9fdb708cea9f98a910/sklearn/tree/export.py
Je ne sais pas exactement ce qui est arrivé à ce commentaire. Mais vous pouvez également essayer d'utiliser cette fonction.
Je pense que cela justifie une demande de documentation sérieuse aux bonnes personnes de scikit-learn pour documenter correctement le
sklearn.tree.Tree
API qui est l'arborescence sous-jacente quiDecisionTreeClassifier
expose comme son attributtree_
.la source
Utilisez simplement la fonction de sklearn.tree comme ceci
Et puis cherchez dans votre dossier de projet le fichier tree.dot , copiez TOUT le contenu et collez-le ici http://www.webgraphviz.com/ et générez votre graphique :)
la source
Merci pour la merveilleuse solution de @paulkerfeld. En plus de sa solution, pour tous ceux qui veulent avoir une version sérialisée d'arbres, utilisez simplement
tree.threshold
,tree.children_left
,tree.children_right
,tree.feature
ettree.value
. Étant donné que les feuilles n'ont pas de fractionnement et donc pas de noms de caractéristiques et d'enfants, leur espace réservé danstree.feature
ettree.children_***
sont_tree.TREE_UNDEFINED
et_tree.TREE_LEAF
. Chaque division se voit attribuer un index unique pardepth first search
.Notez que le
tree.value
est de forme[n, 1, 1]
la source
Voici une fonction qui génère du code Python à partir d'un arbre de décision en convertissant la sortie de
export_text
:Exemple d'utilisation:
Exemple de sortie:
L'exemple ci-dessus est généré avec
names = ['f'+str(j+1) for j in range(NUM_FEATURES)]
.Une caractéristique pratique est qu'il peut générer une taille de fichier plus petite avec un espacement réduit. Juste réglé
spacing=2
.la source