Skillversitas

Decision Tree

A Decision Tree is a supervised learning algorithm that works by splitting the data into subsets based on features. It is highly intuitive and easy to visualize.

How It Works

A Decision Tree makes decisions in the form of a tree:
- Root Node: The first feature tested
- Internal Node: The next feature to test
- Leaf Node: The resulting prediction label/class

Gini Impurity

Gini impurity measures the impurity of a node. The lower the Gini, the purer the node.

Gini = 1 - Σ(pi²)

Where pi is the proportion of class i within the node.

Information Gain & Entropy

Entropy measures uncertainty:

Entropy = -Σ(pi × log2(pi))

Information Gain = Entropy of parent - Σ(weighted) Entropy of children.

import numpy as np

def gini_impurity(labels):
    classes = np.unique(labels)
    gini = 1
    for c in classes:
        p = np.sum(labels == c) / len(labels)
        gini -= p ** 2
    return gini

# Example
node1 = np.array([0, 0, 0, 1, 1])  # low Gini
node2 = np.array([0, 1, 0, 1, 0])  # high Gini

print(f"Node 1 Gini: {gini_impurity(node1):.4f}")
print(f"Node 2 Gini: {gini_impurity(node2):.4f}")

Implementation with Scikit-Learn

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

iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
    iris.data, iris.target, test_size=0.2, random_state=42
)

model = DecisionTreeClassifier(
    max_depth=3,
    criterion='gini',
    random_state=42
)
model.fit(X_train, y_train)

print(f"Accuracy: {model.score(X_test, y_test):.4f}")

# Tree as text
tree_rules = export_text(model, feature_names=iris.feature_names)
print(tree_rules)

Visualizing a Decision Tree

from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt

iris = load_iris()
model = DecisionTreeClassifier(max_depth=3, random_state=42)
model.fit(iris.data, iris.target)

plt.figure(figsize=(15, 8))
plot_tree(model,
          feature_names=iris.feature_names,
          class_names=list(iris.target_names),
          filled=True,
          rounded=True)
plt.title("Decision Tree Iris Dataset")
plt.tight_layout()
plt.show()

Pruning

Pruning prevents overfitting by limiting the depth of the tree.

Parameter Explanation Default
max_depth Maximum depth of the tree None
min_samples_split Minimum samples required to split 2
min_samples_leaf Minimum samples in a leaf 1
max_features Number of features per split None
from sklearn.tree import DecisionTreeClassifier

# Without pruning - prone to overfitting
model_full = DecisionTreeClassifier(random_state=42)
model_full.fit(X_train, y_train)
print(f"Without pruning - Train: {model_full.score(X_train, y_train):.4f}, "
      f"Test: {model_full.score(X_test, y_test):.4f}")

# With pruning
model_pruned = DecisionTreeClassifier(max_depth=3, random_state=42)
model_pruned.fit(X_train, y_train)
print(f"With pruning - Train: {model_pruned.score(X_train, y_train):.4f}, "
      f"Test: {model_pruned.score(X_test, y_test):.4f}")

Feature Importance

A Decision Tree provides information about how important each feature is:

import pandas as pd

importances = model.feature_importances_
features = iris.feature_names

df_imp = pd.DataFrame({
    'Feature': features,
    'Importance': importances
}).sort_values('Importance', ascending=False)

print(df_imp)

Pros and Cons

Pros Cons
Easy to understand Prone to overfitting
No scaling required Unstable
Handles categorical data Biased toward dominant features
Highly interpretable Axis-aligned decision boundaries

Decision Trees tend to overfit, which motivates the use of ensemble methods. Next chapter: Random Forest.

Next: Random Forest →