Entscheidungsbaumanalyse

Machine LearningMachine LearningBeginner
Jetzt üben

This tutorial is from open-source community. Access the source code

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

Der Entscheidungsbaum-Klassifizierer ist ein populares Machine-Learning-Algorithmus, der für Klassifizierungs- und Regressionsprobleme verwendet wird. Es ist ein baum-basiertes Modell, das den Merkmalsraum in eine Reihe von nicht überlappenden Regionen aufteilt und den Zielwert für jede Region vorherzusagt. In diesem Lab werden wir lernen, wie man die Struktur des Entscheidungsbaums analysiert, um weitere Einblicke in die Beziehung zwischen den Merkmalen und dem vorherzusagenden Ziel zu erhalten.

VM-Tipps

Nachdem der VM-Start abgeschlossen ist, klicken Sie in der oberen linken Ecke, um zur Registerkarte Notebook zu wechseln und Jupyter Notebook für die Übung zu öffnen.

Manchmal müssen Sie einige Sekunden warten, bis Jupyter Notebook vollständig geladen ist. Die Validierung von Vorgängen kann aufgrund von Einschränkungen in Jupyter Notebook nicht automatisiert werden.

Wenn Sie bei der Lernphase Probleme haben, können Sie Labby gerne fragen. Geben Sie nach der Sitzung Feedback, und wir werden das Problem für Sie prompt beheben.

Ein Entscheidungsbaum-Klassifizierer trainieren

Zunächst müssen wir einen Entscheidungsbaum-Klassifizierer mit dem load_iris-Datensatz aus scikit-learn anpassen. Dieser Datensatz enthält 3 Klassen mit jeweils 50 Instanzen, wobei jede Klasse auf eine Art von Iris-Pflanze Bezug nimmt. Wir werden den Datensatz in Trainings- und Testsets unterteilen und einen Entscheidungsbaum-Klassifizierer mit maximal 3 Blättern anpassen.

from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier

iris = load_iris()
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

clf = DecisionTreeClassifier(max_leaf_nodes=3, random_state=0)
clf.fit(X_train, y_train)

Analysiere die Struktur des binären Baums

Der Entscheidungsbaum-Klassifizierer hat ein Attribut namens tree_, das den Zugang zu niedriger Ebene-Attributen wie node_count, der Gesamtzahl der Knoten, und max_depth, der maximalen Tiefe des Baums, ermöglicht. Es speichert auch die gesamte binäre Baumstruktur, dargestellt als eine Anzahl paralleler Arrays. Mit diesen Arrays können wir die Baumstruktur durchlaufen, um verschiedene Eigenschaften wie die Tiefe jedes Knotens und ob er ein Blatt ist, zu berechnen. Folgender Code berechnet diese Eigenschaften:

import numpy as np

n_nodes = clf.tree_.node_count
children_left = clf.tree_.children_left
children_right = clf.tree_.children_right
feature = clf.tree_.feature
threshold = clf.tree_.threshold

node_depth = np.zeros(shape=n_nodes, dtype=np.int64)
is_leaves = np.zeros(shape=n_nodes, dtype=bool)
stack = [(0, 0)]  ## starte mit der Wurzelknoten-ID (0) und ihrer Tiefe (0)
while len(stack) > 0:
    ## `pop` stellt sicher, dass jeder Knoten nur einmal besucht wird
    node_id, depth = stack.pop()
    node_depth[node_id] = depth

    ## Wenn das linke und rechte Kind eines Knotens nicht gleich ist, haben wir
    ## einen Split-Knoten
    is_split_node = children_left[node_id]!= children_right[node_id]
    ## Wenn es sich um einen Split-Knoten handelt, füge linkes und rechtes
    ## Kind und Tiefe zur `stack` hinzu, damit wir durch sie iterieren können
    if is_split_node:
        stack.append((children_left[node_id], depth + 1))
        stack.append((children_right[node_id], depth + 1))
    else:
        is_leaves[node_id] = True

print(
    "Die binäre Baumstruktur hat {n} Knoten und hat die "
    "folgende Baumstruktur:\n".format(n=n_nodes)
)
for i in range(n_nodes):
    if is_leaves[i]:
        print(
            "{space}node={node} ist ein Blattknoten.".format(
                space=node_depth[i] * "\t", node=i
            )
        )
    else:
        print(
            "{space}node={node} ist ein Split-Knoten: "
            "gehen Sie zu Knoten {left}, wenn X[:, {feature}] <= {threshold} "
            "sonst zu Knoten {right}.".format(
                space=node_depth[i] * "\t",
                node=i,
                left=children_left[i],
                feature=feature[i],
                threshold=threshold[i],
                right=children_right[i],
            )
        )

Visualisiere den Entscheidungsbaum

Wir können den Entscheidungsbaum auch mit der plot_tree-Funktion aus dem tree-Modul von scikit-learn visualisieren.

from sklearn import tree
import matplotlib.pyplot as plt

tree.plot_tree(clf)
plt.show()

Entscheidungsweg und Blattknoten abrufen

Wir können den Entscheidungsweg von interessierenden Proben mit der decision_path-Methode abrufen. Diese Methode gibt eine Indikatormatrix aus, die uns ermöglicht, die Knoten zu ermitteln, durch die die interessierenden Proben gehen. Die Blatt-IDs, die von interessierenden Proben erreicht werden, können mit der apply-Methode erhalten werden. Dies gibt ein Array der Knoten-IDs der Blätter zurück, die von jeder interessierenden Probe erreicht werden. Mit den Blatt-IDs und der decision_path können wir die Aufteilungsbedingungen ermitteln, die zur Vorhersage einer Probe oder einer Gruppe von Proben verwendet wurden. Folgender Code ruft den Entscheidungsweg und die Blattknoten für eine Probe ab:

node_indicator = clf.decision_path(X_test)
leaf_id = clf.apply(X_test)

sample_id = 0
## erhalte IDs der Knoten, durch die `sample_id` geht, d.h., Zeile `sample_id`
node_index = node_indicator.indices[
    node_indicator.indptr[sample_id] : node_indicator.indptr[sample_id + 1]
]

print("Regeln, die zur Vorhersage von Probe {id} verwendet werden:\n".format(id=sample_id))
for node_id in node_index:
    ## gehe zum nächsten Knoten, wenn es ein Blattknoten ist
    if leaf_id[sample_id] == node_id:
        continue

    ## überprüfe, ob der Wert der aufgeteilten Eigenschaft für Probe 0 unter der Schwelle liegt
    if X_test[sample_id, feature[node_id]] <= threshold[node_id]:
        threshold_sign = "<="
    else:
        threshold_sign = ">"

    print(
        "Entscheidungsknoten {node} : (X_test[{sample}, {feature}] = {value}) "
        "{inequality} {threshold})".format(
            node=node_id,
            sample=sample_id,
            feature=feature[node_id],
            value=X_test[sample_id, feature[node_id]],
            inequality=threshold_sign,
            threshold=threshold[node_id],
        )
    )

Bestimme gemeinsame Knoten für eine Gruppe von Proben

Für eine Gruppe von Proben können wir die gemeinsamen Knoten bestimmen, durch die die Proben gehen, indem wir die decision_path-Methode und die toarray-Methode verwenden, um die Indikatormatrix in ein dichtes Array umzuwandeln.

sample_ids = [0, 1]
## boolescher Array, das die Knoten angibt, durch die beide Proben gehen
common_nodes = node_indicator.toarray()[sample_ids].sum(axis=0) == len(sample_ids)
## erhalte Knoten-IDs mithilfe der Position im Array
common_node_id = np.arange(n_nodes)[common_nodes]

print(
    "\nDie folgenden Proben {samples} teilen die Knoten {nodes} im Baum.".format(
        samples=sample_ids, nodes=common_node_id
    )
)
print("Dies entspricht {prop}% aller Knoten.".format(prop=100 * len(common_node_id) / n_nodes))

Zusammenfassung

In diesem Lab haben wir gelernt, wie man die Struktur des Entscheidungsbaums analysiert, um weitere Einblicke in die Beziehung zwischen den Merkmalen und der Zielvariable zu erhalten, die vorhergesagt werden soll. Wir haben gesehen, wie man die binäre Baumstruktur abruft, den Entscheidungsbaum visualisiert und den Entscheidungsweg und die Blattknoten für eine einzelne Probe oder eine Gruppe von Proben abruft. Diese Techniken können uns helfen, besser zu verstehen, wie der Entscheidungsbaum-Klassifizierer seine Vorhersagen trifft, und uns dabei unterstützen, das Modell zu optimieren, um seine Leistung zu verbessern.