KLASSIFIZIERUNGSALGORITHMUS

Der einzige umgedrehte Baum, den Sie brauchen

Entscheidungsbäume sind im maschinellen Lernen allgegenwärtig und werden wegen ihrer intuitiven Ergebnisse geschätzt. Wer liebt nicht ein einfaches „Wenn-Dann“-Flussdiagramm? Trotz ihrer Beliebtheit ist es überraschend schwierig, eine klare, schrittweise Erklärung zu finden, wie Entscheidungsbäume funktionieren. (Es ist mir tatsächlich peinlich, wie lange ich gebraucht habe, um tatsächlich zu verstehen, wie der Algorithmus funktioniert.)

In dieser Aufschlüsselung werde ich mich additionally auf die Grundlagen der Baumkonstruktion konzentrieren. Wir werden GENAU darlegen, was in jedem Knoten passiert und warum, von der Wurzel bis zu den letzten Blättern (natürlich mit visuellen Darstellungen).

Alle Bilder: Vom Autor mit Canva Professional erstellt. Für Mobilgeräte optimiert; kann auf dem Desktop übergroß erscheinen.

Ein Entscheidungsbaum-Klassifikator erstellt einen umgedrehten Baum, um Vorhersagen zu treffen. Er beginnt oben mit einer Frage zu einem wichtigen Merkmal Ihrer Daten und verzweigt sich dann basierend auf den Antworten. Wenn Sie diesen Zweigen nach unten folgen, wird an jeder Haltestelle eine weitere Frage gestellt, wodurch die Möglichkeiten eingeschränkt werden. Dieses Frage-und-Antwort-Spiel geht weiter, bis Sie das untere Ende erreichen – einen Blattknoten –, wo Sie Ihre endgültige Vorhersage oder Klassifizierung erhalten.

Der Entscheidungsbaum ist einer der wichtigsten Algorithmen des maschinellen Lernens – es handelt sich um eine Reihe von Ja- oder Nein-Fragen.

In diesem Artikel verwenden wir diesen künstlichen Golfdatensatz (inspiriert von (1)) als Beispiel. Dieser Datensatz sagt basierend auf den Wetterbedingungen voraus, ob eine Individual Golf spielen wird.

Spalten: „Ausblick“ (bereits One-Sizzling-kodiert als sonnig, bewölkt, regnerisch), „Temperatur“ (in Fahrenheit), „Luftfeuchtigkeit“ (in %), „Wind“ (ja/nein) und „Wiedergabe“ (Zielfunktion)
# Import libraries
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import pandas as pd
import numpy as np

# Load information
dataset_dict = {
'Outlook': ('sunny', 'sunny', 'overcast', 'wet', 'wet', 'wet', 'overcast', 'sunny', 'sunny', 'wet', 'sunny', 'overcast', 'overcast', 'wet', 'sunny', 'overcast', 'wet', 'sunny', 'sunny', 'wet', 'overcast', 'wet', 'sunny', 'overcast', 'sunny', 'overcast', 'wet', 'overcast'),
'Temperature': (85.0, 80.0, 83.0, 70.0, 68.0, 65.0, 64.0, 72.0, 69.0, 75.0, 75.0, 72.0, 81.0, 71.0, 81.0, 74.0, 76.0, 78.0, 82.0, 67.0, 85.0, 73.0, 88.0, 77.0, 79.0, 80.0, 66.0, 84.0),
'Humidity': (85.0, 90.0, 78.0, 96.0, 80.0, 70.0, 65.0, 95.0, 70.0, 80.0, 70.0, 90.0, 75.0, 80.0, 88.0, 92.0, 85.0, 75.0, 92.0, 90.0, 85.0, 88.0, 65.0, 70.0, 60.0, 95.0, 70.0, 78.0),
'Wind': (False, True, False, False, False, True, True, False, False, False, True, True, False, True, True, False, False, True, False, True, True, False, True, False, False, True, False, False),
'Play': ('No', 'No', 'Sure', 'Sure', 'Sure', 'No', 'Sure', 'No', 'Sure', 'Sure', 'Sure', 'Sure', 'Sure', 'No', 'No', 'Sure', 'Sure', 'No', 'No', 'No', 'Sure', 'Sure', 'Sure', 'Sure', 'Sure', 'Sure', 'No', 'Sure')
}
df = pd.DataFrame(dataset_dict)

# Preprocess information
df = pd.get_dummies(df, columns=('Outlook'), prefix='', prefix_sep='', dtype=int)
df('Wind') = df('Wind').astype(int)
df('Play') = (df('Play') == 'Sure').astype(int)

# Reorder the columns
df = df(('sunny', 'overcast', 'wet', 'Temperature', 'Humidity', 'Wind', 'Play'))

# Put together options and goal
X, y = df.drop(columns='Play'), df('Play')

# Cut up information
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.5, shuffle=False)

# Show outcomes
print(pd.concat((X_train, y_train), axis=1), 'n')
print(pd.concat((X_test, y_test), axis=1))

Der Entscheidungsbaum-Klassifikator funktioniert, indem er die Daten rekursiv auf der Grundlage der informativsten Merkmale aufteilt. So funktioniert es:

  1. Beginnen Sie mit dem gesamten Datensatz beim Stammknoten.
  2. Wählen Sie das beste Merkmal zum Aufteilen der Daten aus (basierend auf Maßen wie der Gini-Unreinheit).
  3. Erstellen Sie untergeordnete Knoten für jeden möglichen Wert der ausgewählten Funktion.
  4. Wiederholen Sie die Schritte 2–3 für jeden untergeordneten Knoten, bis ein Abbruchkriterium erfüllt ist (z. B. maximale Tiefe erreicht, Mindestanzahl an Stichproben professional Blatt oder reine Blattknoten).
  5. Weisen Sie jedem Blattknoten die Mehrheitsklasse zu.

In scikit-learn heißt der Entscheidungsbaumalgorithmus CART (Classification and Regression Timber). Er erstellt binäre Bäume und folgt normalerweise diesen Schritten:

  1. Beginnen Sie mit allen Trainingsbeispielen im Stammknoten.
Ausgehend vom Stammknoten, der alle 14 Trainingsbeispiele enthält, ermitteln wir die beste Funktion und den besten Punkt zum Aufteilen der Daten, um mit dem Erstellen des Baums zu beginnen.

2.Für jede Funktion:
a. Sortieren Sie die Merkmalswerte.
b. Betrachten Sie alle möglichen Schwellenwerte zwischen benachbarten Werten als potenzielle Teilungspunkte.

In diesem Stammknoten müssen 23 Teilungspunkte geprüft werden. Binäre Spalten haben nur einen Teilungspunkt.
def potential_split_points(attr_name, attr_values):
sorted_attr = np.kind(attr_values)
unique_values = np.distinctive(sorted_attr)
split_points = ((unique_values(i) + unique_values(i+1)) / 2 for i in vary(len(unique_values) - 1))
return {attr_name: split_points}

# Calculate and show potential cut up factors for all columns
for column in X_train.columns:
splits = potential_split_points(column, X_train(column))
for attr, factors in splits.objects():
print(f"{attr:11}: {factors}")

3. Für jeden potenziellen Splittpunkt:
a. Berechnen Sie die Unreinheit (z. B. Gini-Unreinheit) des aktuellen Knotens.
b. Berechnen Sie den gewichteten Durchschnitt der Verunreinigungen.

Beispielsweise wird für das Merkmal „sonnig“ mit dem Teilungspunkt 0,5 die Unreinheit (wie die „Gini-Unreinheit“) für beide Teile des Datensatzes berechnet.
Ein weiteres Beispiel: Derselbe Vorgang kann auch für kontinuierliche Funktionen wie „Temperatur“ durchgeführt werden.
def gini_impurity(y):
p = np.bincount(y) / len(y)
return 1 - np.sum(p**2)

def weighted_average_impurity(y, split_index):
n = len(y)
left_impurity = gini_impurity(y(:split_index))
right_impurity = gini_impurity(y(split_index:))
return (split_index * left_impurity + (n - split_index) * right_impurity) / n

# Type 'sunny' function and corresponding labels
sunny = X_train('sunny')
sorted_indices = np.argsort(sunny)
sorted_sunny = sunny.iloc(sorted_indices)
sorted_labels = y_train.iloc(sorted_indices)

# Discover cut up index for 0.5
split_index = np.searchsorted(sorted_sunny, 0.5, facet='proper')

# Calculate impurity
impurity = weighted_average_impurity(sorted_labels, split_index)

print(f"Weighted common impurity for 'sunny' at cut up level 0.5: {impurity:.3f}")

4. Nachdem Sie alle Unreinheiten für alle Merkmale und Teilungspunkte berechnet haben, wählen Sie die niedrigste aus.

Die Funktion „überdeckt“ mit einem Splitpunkt von 0,5 ergibt die geringste Unreinheit. Das bedeutet, dass der Cut up von allen anderen Splitpunkten der reinste ist!
def calculate_split_impurities(X, y):
split_data = ()

for function in X.columns:
sorted_indices = np.argsort(X(function))
sorted_feature = X(function).iloc(sorted_indices)
sorted_y = y.iloc(sorted_indices)

unique_values = sorted_feature.distinctive()
split_points = (unique_values(1:) + unique_values(:-1)) / 2

for cut up in split_points:
split_index = np.searchsorted(sorted_feature, cut up, facet='proper')
impurity = weighted_average_impurity(sorted_y, split_index)
split_data.append({
'function': function,
'split_point': cut up,
'weighted_avg_impurity': impurity
})

return pd.DataFrame(split_data)

# Calculate cut up impurities for all options
calculate_split_impurities(X_train, y_train).spherical(3)

5. Erstellen Sie zwei untergeordnete Knoten basierend auf der gewählten Funktion und dem Teilungspunkt:
– Linkes Sort: Beispiele mit Merkmalswert <= Cut up-Punkt
– Rechtes Sort: Beispiele mit Merkmalswert > Cut up-Punkt

Der ausgewählte Teilungspunkt teilt die Daten in zwei Teile. Da ein Teil bereits rein ist (die rechte Seite! Deshalb ist die Unreinheit gering!), müssen wir den Baum nur am linken Knoten fortsetzen.

6. Wiederholen Sie die Schritte 2 bis 5 rekursiv für jeden untergeordneten Knoten. Sie können auch anhalten, bis ein Abbruchkriterium erfüllt ist (z. B. maximale Tiefe erreicht, Mindestanzahl von Samples professional Blattknoten oder minimale Verunreinigungsabnahme).

# Calculate cut up impurities forselected index
selected_index = (4,8,3,13,7,9,10) # Change it relying on which indices you need to examine
calculate_split_impurities(X_train.iloc(selected_index), y_train.iloc(selected_index)).spherical(3)
from sklearn.tree import DecisionTreeClassifier

# The entire Coaching Part above is finished inside sklearn like this
dt_clf = DecisionTreeClassifier()
dt_clf.match(X_train, y_train)

Endgültiger vollständiger Baum

Die Klassenbezeichnung eines Blattknotens ist die Mehrheitsklasse der Trainingsbeispiele, die diesen Knoten erreicht haben.

Der rechte ist der endgültige Baum, der zur Klassifizierung verwendet wird. Die Beispiele benötigen wir an dieser Stelle nicht mehr.
import matplotlib.pyplot as plt
from sklearn.tree import plot_tree
# Plot the choice tree
plt.determine(figsize=(20, 10))
plot_tree(dt_clf, stuffed=True, feature_names=X.columns, class_names=('Not Play', 'Play'))
plt.present()
In dieser Scikit-Be taught-Ausgabe werden auch die Informationen des Nicht-Blattknotens gespeichert, wie beispielsweise die Anzahl der Samples und die Nummer jeder Klasse im Knoten (Wert).

So funktioniert der Vorhersageprozess, nachdem der Entscheidungsbaum trainiert wurde:

  1. Beginnen Sie beim Stammknoten des trainierten Entscheidungsbaums.
  2. Bewerten Sie die Funktion und die Teilungsbedingung am aktuellen Knoten.
  3. Wiederholen Sie Schritt 2 an jedem nachfolgenden Knoten, bis Sie einen Blattknoten erreichen.
  4. Die Klassenbezeichnung des Blattknotens wird zur Vorhersage für die neue Instanz.
Wir benötigen nur die Spalten, die vom Baum abgefragt werden. Abgesehen von „bewölkt“ und „Temperatur“ spielen andere Werte bei der Vorhersage keine Rolle.
# Make predictions
y_pred = dt_clf.predict(X_test)
print(y_pred)
Der Entscheidungsbaum liefert eine angemessene Genauigkeit. Da unser Baum nur zwei Merkmale prüft, erfasst er die Eigenschaften des Testsatzes möglicherweise nicht intestine.
# Consider the classifier
print(f"Accuracy: {accuracy_score(y_test, y_pred)}")

Entscheidungsbäume haben mehrere wichtige Parameter, die ihr Wachstum und ihre Komplexität steuern:

1 . Max. Tiefe: Dadurch wird die maximale Tiefe des Baums festgelegt. Dies kann ein wertvolles Werkzeug zur Vermeidung einer Überanpassung sein.

👍 Hilfreicher Tipp: Beginnen Sie am besten mit einem flachen Baum (vielleicht 3–5 Ebenen tief) und erhöhen Sie die Tiefe schrittweise.

Beginnen Sie mit einem flachen Baum (z. B. Tiefe 3–5) und steigern Sie diese schrittweise, bis Sie das optimale Gleichgewicht zwischen Modellkomplexität und Leistung bei Validierungsdaten gefunden haben.

2. Mindestprobenaufteilung: Dieser Parameter bestimmt die Mindestanzahl an Samples, die zum Aufteilen eines internen Knotens erforderlich ist.

👍 Hilfreicher Tipp: Wenn Sie hier einen höheren Wert einstellen (etwa 5–10 % Ihrer Trainingsdaten), können Sie verhindern, dass der Baum zu viele kleine, spezifische Aufteilungen erstellt, die sich möglicherweise nicht intestine auf neue Daten übertragen lassen.

3. Min. Proben Blatt: Dies gibt die Mindestanzahl an Samples an, die an einem Blattknoten erforderlich sind.

👍 Hilfreicher Tipp: Wählen Sie einen Wert, der sicherstellt, dass jedes Blatt eine sinnvolle Teilmenge Ihrer Daten darstellt (ungefähr 1–5 % Ihrer Trainingsdaten). Dies kann dazu beitragen, zu spezifische Vorhersagen zu vermeiden.

4. Kriterium: Die Funktion, die zum Messen der Qualität einer Aufteilung verwendet wird (normalerweise „Gini“ für Gini-Unreinheit oder „Entropie“ für Informationsgewinn).

👍 Hilfreicher Tipp: Während Gini im Allgemeinen einfacher und schneller zu berechnen ist, ist die Entropie bei Mehrklassenproblemen oft besser. Allerdings führen sie häufig zu ähnlichen Ergebnissen.

Beispiel einer Entropieberechnung für „sonnig“ mit Splittpunkt 0,5.

Wie jeder Algorithmus im maschinellen Lernen haben Entscheidungsbäume ihre Stärken und Schwächen.

Vorteile:

  1. Interpretierbarkeit: Der Entscheidungsprozess ist leicht zu verstehen und zu visualisieren.
  2. Keine Characteristic-Skalierung: Kann sowohl numerische als auch kategorische Daten ohne Normalisierung verarbeiten.
  3. Behandelt nichtlineare Beziehungen: Kann komplexe Muster in den Daten erfassen.
  4. Wichtigkeit der Funktion: Bietet einen klaren Hinweis darauf, welche Merkmale für die Vorhersage am wichtigsten sind.

Nachteile:

  1. Überanpassung: Neigt zur Erstellung übermäßig komplexer Bäume, die sich nicht intestine verallgemeinern lassen, insbesondere bei kleinen Datensätzen.
  2. Instabilität: Kleine Änderungen in den Daten können dazu führen, dass ein völlig anderer Baum generiert wird.
  3. Verzerrt durch unausgewogene Datensätze: Kann gegenüber dominanten Klassen voreingenommen sein.
  4. Unfähigkeit zur Extrapolation: Es können keine Vorhersagen über den Bereich der Trainingsdaten hinaus getroffen werden.

In unserem Golfbeispiel könnte ein Entscheidungsbaum sehr genaue und interpretierbare Regeln erstellen, um basierend auf den Wetterbedingungen zu entscheiden, ob Golf gespielt werden soll. Er könnte jedoch bei bestimmten Kombinationen von Bedingungen überangepasst sein, wenn er nicht richtig beschnitten wird oder wenn der Datensatz klein ist.

Entscheidungsbaum-Klassifikatoren sind ein großartiges Werkzeug zum Lösen vieler Arten von Problemen im maschinellen Lernen. Sie sind leicht zu verstehen, können komplexe Daten verarbeiten und zeigen uns, wie sie Entscheidungen treffen. Dies macht sie in vielen Bereichen nützlich, von der Wirtschaft bis zur Medizin. Obwohl Entscheidungsbäume leistungsstark und interpretierbar sind, werden sie oft als Bausteine ​​für fortgeschrittenere Ensemblemethoden wie Random Forests oder Gradient Boosting Machines verwendet.

# Import libraries
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from sklearn.tree import plot_tree, DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# Load information
dataset_dict = {
'Outlook': ('sunny', 'sunny', 'overcast', 'wet', 'wet', 'wet', 'overcast', 'sunny', 'sunny', 'wet', 'sunny', 'overcast', 'overcast', 'wet', 'sunny', 'overcast', 'wet', 'sunny', 'sunny', 'wet', 'overcast', 'wet', 'sunny', 'overcast', 'sunny', 'overcast', 'wet', 'overcast'),
'Temperature': (85.0, 80.0, 83.0, 70.0, 68.0, 65.0, 64.0, 72.0, 69.0, 75.0, 75.0, 72.0, 81.0, 71.0, 81.0, 74.0, 76.0, 78.0, 82.0, 67.0, 85.0, 73.0, 88.0, 77.0, 79.0, 80.0, 66.0, 84.0),
'Humidity': (85.0, 90.0, 78.0, 96.0, 80.0, 70.0, 65.0, 95.0, 70.0, 80.0, 70.0, 90.0, 75.0, 80.0, 88.0, 92.0, 85.0, 75.0, 92.0, 90.0, 85.0, 88.0, 65.0, 70.0, 60.0, 95.0, 70.0, 78.0),
'Wind': (False, True, False, False, False, True, True, False, False, False, True, True, False, True, True, False, False, True, False, True, True, False, True, False, False, True, False, False),
'Play': ('No', 'No', 'Sure', 'Sure', 'Sure', 'No', 'Sure', 'No', 'Sure', 'Sure', 'Sure', 'Sure', 'Sure', 'No', 'No', 'Sure', 'Sure', 'No', 'No', 'No', 'Sure', 'Sure', 'Sure', 'Sure', 'Sure', 'Sure', 'No', 'Sure')
}
df = pd.DataFrame(dataset_dict)

# Put together information
df = pd.get_dummies(df, columns=('Outlook'), prefix='', prefix_sep='', dtype=int)
df('Wind') = df('Wind').astype(int)
df('Play') = (df('Play') == 'Sure').astype(int)

# Cut up information
X, y = df.drop(columns='Play'), df('Play')
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.5, shuffle=False)

# Practice mannequin
dt_clf = DecisionTreeClassifier(
max_depth=None, # Most depth of the tree
min_samples_split=2, # Minimal variety of samples required to separate an inner node
min_samples_leaf=1, # Minimal variety of samples required to be at a leaf node
criterion='gini' # Operate to measure the standard of a cut up
)
dt_clf.match(X_train, y_train)

# Make predictions
y_pred = dt_clf.predict(X_test)

# Consider mannequin
print(f"Accuracy: {accuracy_score(y_test, y_pred)}")

# Visualize tree
plt.determine(figsize=(20, 10))
plot_tree(dt_clf, stuffed=True, feature_names=X.columns,
class_names=('Not Play', 'Play'), impurity=False)
plt.present()

Von admin

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert