[PYTHON] J'ai essayé de comprendre l'arbre de décision (CART) pour classer soigneusement

introduction

Jusqu'à présent, nous avons résumé la régression logistique, les machines vectorielles de support, les réseaux de neurones, etc. Cette fois, je vais résumer les arbres de décision de base tels que XGBoost, LightGBM et Random Forest.

Qu'est-ce qu'un arbre de décision?

Un arbre de décision est un algorithme qui «sépare les données étape par étape et produit des résultats d'analyse en forme d'arbre».

021.png

Les avantages de réaliser une analyse avec cet arbre de décision sont:

Il existe des fonctionnalités telles que. En particulier, je pense que le premier avantage est grand. D'autres classificateurs (machines vectorielles de support, réseaux de neurones, etc.) sont très compliqués et encadrés dans les calculs effectués à l'intérieur, il est donc difficile pour quiconque est familier avec le contenu du modèle de comprendre le contenu. Il y a un visage. D'autre part, l'arbre de décision est une fonctionnalité facile à comprendre car les motifs de division sont clairs, comme le montre la figure ci-dessus. Je pense que cela ** facile à comprendre ** est un énorme avantage. C'est parce que je ne pense pas que ce soit une bonne attitude pour un technicien pour une personne qui utilise un modèle pour produire des résultats en utilisant quelque chose qu'il ne comprend pas **.

Cet arbre de décision est un algorithme qui peut être appliqué à la fois à la classification et à la régression, mais cette fois, je voudrais résumer la classification. De plus, l'arbre de décision a un algorithme appelé CART et C4.5. Cette fois, nous parlons de CART.

Comment décider des critères de division

Divisez de sorte que les éléments après division (données à diviser) soient pour chaque élément que vous voulez diviser (= la pureté après division est le minimum). L'impureté est un indicateur de la façon dont différentes classes d'éléments sont mélangées.

Je voudrais l'examiner brièvement avec un exemple. Je voudrais charger et créer la méthode make_blobs () de scikit learn qui me donne un échantillon de spray.

RF.ipynb


#Imports
%matplotlib inline
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn

from sklearn.datasets import make_blobs

X, y = make_blobs(n_samples=500, centers=4,
                  random_state=8, cluster_std=2.2)

#Scatter plot the points
plt.figure(figsize=(10,10))
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='jet')

Le diagramme de dispersion original est ici.

022.png

Maintenant, réfléchissons à la façon de diviser ce diagramme de dispersion.

image.png

En raison de la ligne de séparation à gauche, l'élément $ [2], qui est l'opposé du groupe qui contient beaucoup d'élément $ [0], [1] $ (à l'inverse, ne contient pas $ [2], [3] $). Vous pouvez voir qu'il peut être divisé en groupes contenant beaucoup de [3] $ (à l'inverse, $ [0] et [1] $ ne sont pas inclus). Ce type de division est une méthode de division avec moins de pureté. Par contre, dans le cas de la ligne de division à droite, vous pouvez voir que les éléments de $ [0] à [3] $ sont mélangés dans le groupe après division. C'est ce qu'on appelle avoir beaucoup d'impuretés. Trouvez la ligne de division comme indiqué sur la gauche et classez-la plusieurs fois (= appelée la profondeur de l'arbre de décision) pour classer l'objectif.

Comment trouver la pureté

Maintenant, résumons comment exprimer cette impureté. Cette fois, nous nous concentrerons sur l'indice de diversité de Gini $. La traduction littérale est l'indice de diversité de Gini. Je pense que vous pouvez comprendre le sens en japonais, mais il semble que cela soit souvent appelé impur.

Considérons une hiérarchie (= nœud) $ t $ avec un arbre de décision. Un nœud est un groupe après avoir été divisé. Considérons ensuite le cas où il y a des échantillons $ n $ dans le nœud et des classes $ c $ dans le nœud. A ce moment, en supposant que le nombre d'échantillons appartenant à la classe $ i $ dans le nœud $ t $ est $ n_i $, le rapport des échantillons appartenant à la classe $ i $ $ p (i | t) $ peut être exprimé comme suit. Je peux le faire.

p(i|t) = \frac{n_i}{n} \tag{1}

A ce moment, Gini Impure $ I_G (t) $ peut être exprimé comme suit. $ I_G(t) = 1 - \sum_{i=1}^c {p(i|t)}^2 \tag{2} $

La somme de $ p (i | t) ^ 2 $ augmentera si une bonne division est faite. Par conséquent, $ I_G (t) $ devient plus petit. Nous ferons un bon classificateur en utilisant cet indice d'évaluation.

Conçu pour rendre le graphique plus facile à voir

Colorez chaque classe pour la rendre plus facile à comprendre.

RF.ipynb


def visualize_tree(classifier, X, y, boundaries=True,xlim=None, ylim=None):
    '''
Visualisez l'arbre de décision.
    INPUTS:Modèle de classification, X, y, optional x/y limits.
    OUTPUTS:Visualisation des arbres de décision à l'aide de Meshgrid
    '''
    #Construire un modèle à l'aide de l'ajustement
    classifier.fit(X, y)
    
    #Réglage automatique de l'axe
    if xlim is None:
        xlim = (X[:, 0].min() - 0.1, X[:, 0].max() + 0.1)
    if ylim is None:
        ylim = (X[:, 1].min() - 0.1, X[:, 1].max() + 0.1)

    x_min, x_max = xlim
    y_min, y_max = ylim
    
    
    #Créez une grille maillée.
    xx, yy = np.meshgrid(np.linspace(x_min, x_max, 100),
                         np.linspace(y_min, y_max, 100))
    
    #Enregistrer les prédictions du classificateur sous Z
    Z = classifier.predict(np.c_[xx.ravel(), yy.ravel()])

    #Utilisez meshgrid pour le façonner.
    Z = Z.reshape(xx.shape)
    
    #Colorez chaque catégorie.
    plt.figure(figsize=(10,10))
    plt.pcolormesh(xx, yy, Z, alpha=0.2, cmap='jet')
    
    #Il tire également des données d'entraînement.
    plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='jet')
    
    plt.xlim(x_min, x_max)
    plt.ylim(y_min, y_max)        
    
    def plot_boundaries(i, xlim, ylim):
        '''
Dessinez une bordure.
        '''
        if i < 0:
            return

        tree = classifier.tree_
        
        #Appelez récursivement pour tracer les limites.
        if tree.feature[i] == 0:
            plt.plot([tree.threshold[i], tree.threshold[i]], ylim, '-k')
            plot_boundaries(tree.children_left[i],
                            [xlim[0], tree.threshold[i]], ylim)
            plot_boundaries(tree.children_right[i],
                            [tree.threshold[i], xlim[1]], ylim)
        
        elif tree.feature[i] == 1:
            plt.plot(xlim, [tree.threshold[i], tree.threshold[i]], '-k')
            plot_boundaries(tree.children_left[i], xlim,
                            [ylim[0], tree.threshold[i]])
            plot_boundaries(tree.children_right[i], xlim,
                            [tree.threshold[i], ylim[1]])
    
    if boundaries:
        plot_boundaries(0, plt.xlim(), plt.ylim())

Essayez de classer par arbre de décision

RF.ipynb


from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier(criterion='entropy',max_depth=2,random_state=0)

visualize_tree(clf,X,y)

023.png

J'ai pu le diviser en un bon sentiment. Dans ce qui précède, déterminez la profondeur de l'arbre déterminé avec max_depth. Augmenter (= approfondir) la valeur de cette max_depth entraînera un surapprentissage. Essayez-le avec max_depth = 6.

024.png

Vous pouvez voir qu'il est sur-divisé (en particulier la classe rouge). Le fait est que vous devez ajuster vous-même cette profondeur.

Visualisation de la base de l'arbre de décision

À propos, l'image de l'arbre de décision lorsqu'elle est vérifiée à la profondeur 2 est présentée ci-dessous.

image.png

Les valeurs numériques et l'impureté de Gini qui servent de critères de classification sont listées. valeur est le nombre d'éléments dans les classes [0] à [3].

Comment générer une image d'arbre de décision

Au fait, c'est une image rapide, mais il faut importer la librairie et installer le logiciel.

  1. Installez pydotplus
  2. Installez graphviz
  3. À travers le chemin

Les trois actions ci-dessus étaient nécessaires pour que je sauve.

  1. Installez pydotplus

Il s'agit d'une bibliothèque qui enregistre le contenu divisé par l'arbre de décision dans un fichier .dot.

console


pip install pydotplus

Comme toute autre bibliothèque, vous pouvez l'installer avec pip.

  1. Installez graphviz

J'ai téléchargé le programme d'installation (graphviz-2.38.msi) à partir de cette URL.

https://graphviz.gitlab.io/_pages/Download/Download_windows.html

Lorsque le téléchargement est terminé, double-cliquez sur "graphviz-2.38.msi" pour l'installer. De plus, installez graph viz sur pip.

  1. passer le chemin

Ensuite, passez path pour le rendre pdf. Spécifiez le dossier où se trouve «dot.exe». J'ai déjà résumé la méthode, veuillez donc vous référer ici.

https://qiita.com/Fumio-eisan/items/340de9fe220a90607013

Enfin, vous devez réécrire la syntaxe dans graphviz.py comme suit:

image.png

À ce stade, l'arbre de décision peut être converti en .dot et pdf ci-dessous.

RF.ipynb



import pydotplus
import os
from graphviz import Source
from sklearn.tree import export_graphviz

export_graphviz(
        clf,
        out_file=os.path.join("text_classification.dot"),
        class_names=['1', '2','3','4'],
        rounded=True,
        filled=True
    )
with open("random.dot", 'w') as f:
    f = export_graphviz(clf, out_file=f)

data = export_graphviz(clf, out_file=None)
graph = pydotplus.graph_from_dot_data(data)
graph.write_pdf("random.pdf")

J'ai fait référence à ce site.

Gestion des erreurs GraphViz (exécutables GraphViz introuvables) https://niwakomablog.com/graphviz-error-handling/

À la fin

Cette fois, nous avons résumé le contenu et la mise en œuvre de la classification des arbres de décision. L'idée est facile à comprendre et à mettre en œuvre. Cependant, à la fin, j'ai senti qu'il y avait un léger obstacle à transformer l'arbre de décision en pdf. Ensuite, je voudrais faire un retour.

Le programme complet est ici. https://github.com/Fumio-eisan/RF_20200423

Recommended Posts

J'ai essayé de comprendre l'arbre de décision (CART) pour classer soigneusement
Python pratique 100 coups J'ai essayé de visualiser l'arbre de décision du chapitre 5 en utilisant graphviz
[Introduction] J'ai essayé de l'implémenter moi-même tout en expliquant pour comprendre la dichotomie
J'ai essayé de déplacer le ballon
J'ai essayé d'estimer la section.
(Python) Valeur attendue ・ J'ai essayé de comprendre attentivement l'échantillonnage Monte Carlo
J'ai essayé de créer un site qui permet de voir facilement les informations mises à jour d'Azure
J'ai essayé de résumer la commande umask
J'ai essayé de reconnaître le mot de réveil
Comprendre l'arbre de décision et classer les documents
J'ai essayé d'estimer le rapport de circonférence π de manière probabiliste
J'ai essayé de toucher l'API COTOHA
(Apprentissage automatique) J'ai essayé de comprendre attentivement la régression linéaire bayésienne avec l'implémentation
(Apprentissage automatique) J'ai essayé de comprendre attentivement l'algorithme EM dans la distribution gaussienne mixte avec l'implémentation.
J'ai essayé Web Scraping pour analyser les paroles.
J'ai essayé d'optimiser le séchage du linge
J'ai essayé de sauvegarder les données avec discorde
Arbre de décision (classification)
J'ai essayé de prédire les chevaux qui seront dans le top 3 avec LightGBM
J'ai essayé de corriger la forme trapézoïdale de l'image
Qiita Job J'ai essayé d'analyser le travail
J'ai essayé de comprendre attentivement la fonction d'apprentissage dans le réseau de neurones sans utiliser la bibliothèque d'apprentissage automatique (première moitié)
Je n'ai pas compris le redimensionnement de TensorFlow, alors je l'ai résumé visuellement.
LeetCode j'ai essayé de résumer les plus simples
J'ai essayé de mettre en œuvre le problème du voyageur de commerce
J'ai essayé de comprendre attentivement la machine vectorielle de support (Partie 1: J'ai essayé le noyau polynomial / RBF en utilisant MakeMoons comme exemple).
J'ai essayé de vectoriser les paroles de Hinatazaka 46!
[LPIC 101] J'ai essayé de résumer les options de commande qui sont faciles à faire une erreur
[Introduction] J'ai essayé de l'implémenter moi-même tout en expliquant l'arbre de dichotomie
J'ai essayé de comprendre comment utiliser les pandas et la colinéarité multiple en utilisant l'ensemble de données Affaires comme thème.
mong - J'ai essayé de porter le code qui génère de manière aléatoire le nom du conteneur Docker vers Python -
J'ai essayé d'entraîner la fonction péché avec chainer
J'ai essayé de représenter graphiquement les packages installés en Python
J'ai essayé de résumer la forme de base de GPLVM
J'ai essayé de toucher un fichier CSV avec Python
J'ai essayé de prédire le match de la J League (analyse des données)
La décision de scikit-learn Comment visualiser un modèle en bois
J'ai essayé de résoudre Soma Cube avec python
Je veux bien comprendre les bases de Bokeh
J'ai essayé d'approcher la fonction sin en utilisant le chainer
J'ai essayé de mettre Pytest dans la bataille réelle
J'ai essayé de visualiser les informations spacha de VTuber
J'ai essayé d'effacer la partie négative de Meros
J'ai essayé de résoudre le problème avec Python Vol.1
J'ai senti que j'avais porté le code Python en C ++ 98.
J'ai essayé de simuler la méthode de calcul de la moyenne des coûts en dollars
J'ai essayé de refaire la factorisation matricielle non négative (NMF)
J'ai essayé la méthode la plus simple de classification de documents multi-étiquettes
J'ai essayé d'identifier la langue en utilisant CNN + Melspectogram
J'ai essayé de compléter le graphe de connaissances en utilisant OpenKE
J'ai essayé de classer les voix des acteurs de la voix
J'ai essayé de compresser l'image en utilisant l'apprentissage automatique
J'ai essayé de résumer les opérations de chaîne de Python
J'ai essayé de bien le comprendre en implémentant l'algorithme Adaboost en machine learning (+ j'ai approfondi ma compréhension du calcul de tableaux)
J'ai essayé de déboguer.