Das letzte Mal habe ich Anfänger des maschinellen Lernens versuchen, Naive Bayes zu erreichen gepostet, aber dieses Mal möchte ich über den Entscheidungsbaum schreiben. (Auch diesmal habe ich es selbst in Python implementiert)
Es gibt viele Details an anderen Stellen, deshalb möchte ich sie hier aufschlüsseln und aus der Perspektive der Erklärung und Programmierung erklären.
Dies ist eine Methode zum Klassifizieren von Eingabedaten durch Generieren eines baumstrukturierten Klassifizierers aus einem Datensatz objektiver Variablen und erklärender Variablen.
Ich habe es nicht verstanden, also erkläre ich zunächst die Begriffe.
Im Allgemeinen denke ich, dass das Obige oft ein Vektor ist. (Es scheint allgemeines maschinelles Lernen zu sein)
Der Punkt ist, viel "wenn - am wenigsten" zu machen. Das ist.
Ich werde den Ablauf etwas detaillierter schreiben.
das ist alles.
Ich denke, das ist das Herz dieser Zeit.
Ich werde erklären, wie man die Daten teilt. Die folgenden Daten werden basierend auf den Irisdaten von sklearn erstellt.
from sklearn import datasets
iris = datasets.load_iris() #Lesen von Irisdaten
iris.data #Erklärende Variable
iris.target #Objektive Variable
Betrachten Sie den folgenden Datensatz. Die fünfte Dimension repräsentiert die Zielvariable (0, 1, 2: Blütentyp) und die anderen repräsentieren die erklärenden Variablen (Blütenblattlänge usw.).
[
[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]
...
]
Wenn Sie diese Daten aufteilen, gehen Sie wie folgt vor.
Es scheint, dass es mehrere Methoden gibt, um den Entscheidungsbaum zu bewerten, aber dieses Mal werden wir "Gini Impure" verwenden.
Das Wort "unrein" erschien zuerst, aber es ist einfach. Es ist schön, zwischen den erklärenden Variablen aufzuteilen, aber ist dies der richtige Weg, um aufzuteilen? Ich denke, die Frage bleibt. Gini unrein ist derjenige, der es quantifiziert.
Übrigens wurde das Wort "Gini-Koeffizient" auf anderen Websites verwendet, aber seien Sie bitte vorsichtig bei der Suche, da die Differenzierung irgendwie herauskommt (ein Diagramm der Lorenz-Kurve von Bevölkerung und Einkommen kommt heraus. * Ich weiß nicht viel, also sag mir bitte, wer damit vertraut ist ..)
In Bezug auf Gini Unreinheit wird es auch als Referenz veröffentlicht, aber die folgende Seite war leicht zu verstehen. Es ist in den ganzen Teil / den zweiten Teil unterteilt.
Statistischer Honig-Gini-Koeffizient ...? (Teil 1)
Diese Gini-Unreinheit wird für die Sätze L und R berechnet, die durch Teilen des Satzes A erhalten werden, und der Durchschnittswert wird genommen, um die Gini-Reinheit zu erhalten: G (x).
G (A)> Durchschnitt von G (L) und G (R)
Wenn ja, bedeutet dies, dass es erfolgreich geteilt wurde.
Es ist immer noch rau, aber ich werde den Quellcode vorerst veröffentlichen. Bitte kommentieren Sie, wenn Sie welche haben! !!
# -*- 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 #Hierarchietiefe
self.l_node = None #Untergeordneter Knoten(links)
self.r_node = None #Untergeordneter Knoten(richtig)
self.t_value = None #Schwelle
self.feature_idx = None #Welchen Wert zu teilen
self.label = None #Zu klassifizierende Etiketten
self.samples = [] #Probe zu welcher
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) #Anzahl der erklärenden Variablen
#Wenn Sie die maximale Tiefe erreicht haben, sind Sie fertig
if self.level >= max_depth:
self.build_leaf()
return
#Das beste Ergebnis der Klassifizierung
best_feature_idx = None #Die am besten klassifizierten erklärenden Variablen
best_t_value = None #Beste klassifizierte Schwelle
best_gini = 1 #Gleichheit bei Annäherung an 0
best_l_samples = []
best_r_samples = []
#Bewerten Sie, indem Sie so viele wie die Anzahl der erklärenden Variablen klassifizieren
#Klassifizieren Sie nach jeder erklärenden Variablen(idx =Erklärender Variablenindex)
for idx in range(0, n_features-1):
#Machen Sie die zu klassifizierenden erklärenden Variablen eindeutig und sortieren Sie sie in aufsteigender Reihenfolge
features = map(lambda x: x.features[idx] , samples)
features = list(set(features))
features.sort()
for i in range(0, len(features)-2):
#Klassifizieren Sie nach dem Zwischenwert jeder erklärenden Variablen.
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
#Es macht keinen Sinn zu teilen, wenn es auf beides voreingenommen ist,Berechnung der folgenden erklärenden Variablen
if len(l_samples) == 0 or len(r_samples) == 0:
continue
#Bewertung für die geteilten(Gini-Koeffizient,Gekreuzte Entropie)
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
#Gesamt-Gini-Koeffizient(l,Finden Sie den Durchschnittswert des Gini-Koeffizienten von r)
gini = (((1-l_gini) * len(l_samples)) + ((1-r_gini) * len(r_samples))) / len(samples)
#Update wenn besser als am besten
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
#Wenn Sie zu beiden Seiten voreingenommen sind, erstellen Sie keinen neuen Baum
if len(best_l_samples) == 0 or len(best_r_samples) == 0:
self.build_leaf()
return
# min_Keine Trennung erforderlich, wenn die Proben nicht erreicht werden.Überlernen von Maßnahmen
if max(len(best_l_samples), len(best_r_samples)) < min_samples:
self.build_leaf()
return
#Aktuelle Knoteneinstellungen
self.samples = []
self.t_value = best_t_value
self.feature_idx = best_feature_idx
#Erstellen Sie einen neuen Knoten von den besten,Gehen Sie zum nächsten Knoten
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 #Maximale Tiefe des Baumes
self.min_samples = min_samples #Mindestanzahl der zum Knoten gehörenden Elemente
def fit(self, data, target):
#Anzahl der eindeutigen Klassifizierungsklassen
labels = list(set(target))
#Datengenerierung für das Training
samples = []
for idx, sample in enumerate(data):
samples.append(Sample(features=data[idx], label=target[idx]))
#Lernen
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):
#Ausgabeknotenfunktionen für jede Ebene
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)
Die folgende Seite war sehr hilfreich.
Recommended Posts