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.