La dernière fois, j'ai posté Les débutants de l'apprentissage automatique essayent de contacter Naive Bayes, mais cette fois j'aimerais écrire sur l'arbre de décision. (Cette fois aussi, je l'ai implémenté moi-même en Python)
Il y a beaucoup de détails dans d'autres endroits, alors je voudrais ici le décomposer et l'expliquer du point de vue de l'explication et de la programmation.
Il s'agit d'une méthode de classification des données d'entrée en générant un classificateur à structure arborescente à partir d'un ensemble de données de variables objectives et de variables explicatives.
Je n'ai pas compris, alors je vais commencer par expliquer les termes.
En général, je pense que ce qui précède est souvent un vecteur. (Cela semble être un apprentissage automatique général)
En bref, faites beaucoup de «if --elest». C'est.
J'écrirai le flux un peu plus en détail.
c'est tout.
Je pense que c'est le cœur de cette époque.
Je vais vous expliquer comment diviser les données. Les données suivantes sont créées à partir des données d'iris de sklearn.
from sklearn import datasets
iris = datasets.load_iris() #lecture de données d'iris
iris.data #Variable explicative
iris.target #Variable objectif
Considérez l'ensemble de données suivant. La cinquième dimension représente la variable objective (0, 1, 2: type de fleur), et les autres représentent les variables explicatives (longueur des pétales, etc.).
[
[5.1, 3.5, 1.4, 0.2, 0], 
[4.9, 3.0, 1.4, 0.2, 1], 
[4.7, 3.2, 1.3, 0.2, 0]
...
]
Maintenant, que faire lors de la division de ces données est la suivante.
Il semble qu'il existe plusieurs méthodes utilisées pour évaluer l'arbre de décision, mais cette fois nous utiliserons "Gini Impure".
Le mot «impur» est apparu pour la première fois, mais c'est facile. C'est bien de se répartir entre les variables explicatives, mais est-ce la bonne façon de se séparer? Je pense que la question demeure. Gini impur est celui qui le quantifie.
D'ailleurs, le mot «coefficient de Gini» a été utilisé sur d'autres sites, mais soyez prudent lors de la recherche car la différenciation ressort d'une manière ou d'une autre (un graphique de la courbe de Lorenz de la population et des revenus en sort. * Je ne sais pas grand chose, alors dites-moi qui le connaît ..)
En ce qui concerne l'impureté de Gini, il est également publié pour référence, mais le site suivant était facile à comprendre. Il est divisé en partie entière / seconde partie.
Coefficient statistique Honey Gini ...? (Partie 1)
Cette impureté gini est calculée pour les ensembles L et R obtenus en divisant l'ensemble A, et la valeur moyenne est prise pour obtenir la pureté gini: G (x).
G (A)> Moyenne de G (L) et G (R)
Si tel est le cas, cela signifie qu'il a été divisé avec succès.
C'est encore difficile, mais je posterai le code source pour le moment. Veuillez commenter si vous en avez! !!
# -*- coding: utf-8 -*-
from collections import defaultdict
class Sample:
    def __init__(self, label=0, features=[]):
        self.label    = label
        self.features = features
# ----------------------------------------------------------------------------
class Node:
    def __init__(self, level=0):
        self.level       = level #Profondeur de la hiérarchie
        self.l_node      = None  #Nœud enfant(la gauche)
        self.r_node      = None  #Nœud enfant(droite)
        self.t_value     = None  #Seuil
        self.feature_idx = None  #Quelle valeur diviser
        self.label       = None  #Étiquettes à classer
        self.samples     = []    #Échantillon auquel
    def __str__(self):
        if self.is_leaf():
            return "[%3s] Samples:%3s" % (self.level, len(self.samples))
        else:
            return "[%3s] Feature Idx:%3s, Threashold: %5s" % (self.level, self.feature_idx, self.t_value)
    def is_leaf(self):
        return (self.l_node is None) and (self.r_node is None)
    def child_nodes(self):
        return filter(None, [self.l_node, self.r_node])
    def classify(self, feature):
        node  = self
        label = None
        f = feature[node.feature_idx]
        while node:
            if node.is_leaf():
                label = node.label
                break
            elif f < node.t_value:
                node = node.l_node
            else:
                node = node.r_node
        return label
    def build_child_nodes(self, n_class, samples, max_depth, min_samples):
        self.samples = samples
        n_features   = len(samples[0].features) #Nombre de variables explicatives
        #Lorsque vous atteignez la profondeur maximale, vous avez terminé
        if self.level >= max_depth:
            self.build_leaf()
            return
        #Le meilleur résultat du classement
        best_feature_idx = None #Les variables explicatives les mieux classées
        best_t_value     = None #Meilleur seuil classé
        best_gini        = 1    #L'égalité à l'approche de 0
        best_l_samples   = []
        best_r_samples   = []
        #Évaluer en classant autant que le nombre de variables explicatives
        #Classer par chaque variable explicative(idx =Index des variables explicatives)
        for idx in range(0, n_features-1):
            #Rendre les variables explicatives à classer uniques et les trier par ordre croissant
            features = map(lambda x: x.features[idx] , samples)
            features = list(set(features))
            features.sort()
            for i in range(0, len(features)-2):
                #Classer par la valeur intermédiaire de chaque variable explicative.
                t_value = (features[i] + features[i+1]) / 2
                l_samples = []; l_sample_labels = defaultdict(lambda: 0)
                r_samples = []; r_sample_labels = defaultdict(lambda: 0)
                for s in samples:
                    if s.features[idx] < t_value:
                        l_samples.append(s)
                        l_sample_labels[s.label] += 1
                    else:
                        r_samples.append(s)
                        r_sample_labels[s.label] += 1
                #Il ne sert à rien de diviser si cela est,Calcul des variables explicatives suivantes
                if len(l_samples) == 0 or len(r_samples) == 0:
                    continue
                #Évaluation pour les divisés(coefficient de Gini,Entropie croisée)
                l_gini = 0; r_gini = 0
                for idx in range(0, n_class):
                    l_gini += (float(l_sample_labels[idx]) / len(l_samples)) ** 2
                    r_gini += (float(r_sample_labels[idx]) / len(r_samples)) ** 2
                #Coefficient de Gini global(l,Trouvez la valeur moyenne du coefficient gini de r)
                gini = (((1-l_gini) * len(l_samples)) + ((1-r_gini) * len(r_samples))) / len(samples)
                #Mettre à jour si meilleur que le meilleur
                if gini < best_gini:
                    best_gini        = gini
                    best_t_value     = t_value
                    best_feature_idx = idx
                    best_l_samples   = l_samples
                    best_r_samples   = r_samples
        #Si vous êtes biaisé d'un côté ou de l'autre, ne créez pas de nouvel arbre
        if len(best_l_samples) == 0 or len(best_r_samples) == 0:
            self.build_leaf()
            return
        # min_Pas besoin de séparer si les échantillons ne sont pas atteints.Mesures de surapprentissage
        if max(len(best_l_samples), len(best_r_samples)) < min_samples:
            self.build_leaf()
            return
        #Paramètres de nœud actuels
        self.samples     = []
        self.t_value     = best_t_value
        self.feature_idx = best_feature_idx
        #Créez un nouveau nœud parmi les meilleurs,Passer au nœud suivant
        next_level = self.level + 1
        self.r_node = Node(next_level)
        self.r_node.build_child_nodes(n_class, best_r_samples, max_depth, min_samples)
        self.l_node = Node(next_level)
        self.l_node.build_child_nodes(n_class, best_l_samples, max_depth, min_samples)
    def build_leaf(self):
        self.label = self.samples[0].label
# ----------------------------------------------------------------------------
class DecisionTree:
    def __init__(self, max_depth=10, min_samples=3):
        self.root_node   = Node(level=1) # root node
        self.max_depth   = max_depth     #Profondeur maximale de l'arbre
        self.min_samples = min_samples   #Nombre minimum d'éléments appartenant à Node
    def fit(self, data, target):
        #Nombre de classes de classification uniques
        labels = list(set(target))
        #Génération de données pour la formation
        samples = []
        for idx, sample in enumerate(data):
            samples.append(Sample(features=data[idx], label=target[idx]))
        #Apprentissage
        self.root_node.build_child_nodes(n_class=len(labels), samples=samples, max_depth=self.max_depth, min_samples=self.min_samples)
    def features(self):
        #Fonctionnalités du nœud de sortie pour chaque niveau
        print self.root_node
        current_nodes = self.root_node.child_nodes()
        child_nodes   = []
        while current_nodes:
            node = current_nodes.pop(0)
            print node
            child_nodes.extend(node.child_nodes())
            if len(current_nodes) == 0 and len(child_nodes) > 0:
                current_nodes = child_nodes
                child_nodes   = []
    def predict(self, data):
        return self.root_node.classify(data)
La page suivante a été très utile.