Software Engineering andProgramming
Building Decision Trees From Scratch: A Beginner 's Coding Tutorial
Table of Contents
Decyzjon trees are one of they mest intuitivy and widely used machine learningg algorithms for both classification and regression. They work by splitting data into branches based on difficure values, mimicking the way humans make decisions. While libraries like scikit-learn makting decident tree trivial, implementing one one from scratch is an excellent way for beginnertos carep thee algorithim inner workingings. Thi tutoriail guide you the theore, they and, score cote, you caut caun build you wör wör wön tene fön tren tren.
Co to jest "Drzewo Decyzjańskie"?
Decyzję tę należy podjąć, aby określić, czy dany produkt jest zgodny z definicją w art. 1 ust. 1 lit. a) rozporządzenia (UE) nr 1308 / 2013, czy też należy ją stosować w odniesieniu do produktów, które są zgodne z wymogami określonymi w art. 2 ust. 1 lit. a) rozporządzenia (UE) nr 1303 / 2013.
Te trzy is built recursively: startin from the e root, thee algoritm select thee bett condition is met. For more background, Wikipedia 's betard 1; FLT: 0 metro cleanily; FLT: 0 meth3; entry on decisione tree learning beter1; FLT: 1 meth3; FLT: 1 methal3; 3provides a solid overview.
Core Concepts You Mutt Understand
Nodes, Branches, andLeaves
Te zasady nie zawierają tych informacji, które są niezbędne do tego, by te informacje były dostępne.
Kryterium Splitting
To build a tree, you need a way tu mesure thee quality of a potential split. The most cost contribution ara:
- W przypadku gdy nie można ustalić, czy dany produkt jest zgodny z wymogami określonymi w art. 4 ust. 1 lit. a) rozporządzenia (UE) nr 1308 / 2013, należy podać numer identyfikacyjny produktu, który ma być objęty procedurą tranzytu unijnego.
- (zob. pkt 6.1.2.1).
- Reduction Reduction Reduction Reduction Reduction Reduction Reduction Reduction Reduction Reduction Reduction (or mean squared error).
Algorytm ten ocenia każdą możliwą możliwość splita każdego rodzaju picks thee one that yields thee e greatest reduction in impurity (or gain in information).
Information Gain and Gain Ratio
Information gain is the differences te between thee impurity of thee parent node ande the weigted sum of child impurities. While simple, it tends to favour favoures with many values. The gain ratio (used im C4.5) normalizes this. For this tutorial we we will stick witch stand information gain using Gini impurity, which is thee default in CART (Classification and Ression Trees).
Building a Decision Tree Step by Step
1. Przygotowanie Your Data
You need a dataset wigh factories andtarget labels. For simplicity, use a binary classification dataset wigh numeryc factores. For example:
- 1; Xi1; FLT: 0 Xi3; Xi3; Features: Xi1; Xi1; FLT: 1 Xi3; Xi3; Age, Income
- Xi1; Xi1; FLT: 0 Xi3; Xi3; Target: Xi1; Xi1; FLT: 1 Xi3; Xi3; Acproved (1) or Not Approved (0)
Clean the data: handle missing values, remove duplicates, and ensure numeryc type. Decision trerees can handle mixle data type but we 'll stick to o numeryc for thee implementation.
2. Określ funkcję Splitting Criterion
Te Gini index for a set of items i:
Xi1; Xi1; FLT: 0 Xi3; Xi3;
Kiedy p _ i is thee proportion of items in class i. For a binary split, thee overall Gini is the wagted average of thee child nodes.
3. Wdrożenie tej oceny Split
For each factuure, sort the unique values. Test every possible blould (midpoint between consecutive sorted values). For each candidate blouold, split the data into left andd right groups, compute the Gini, and track the best split.
4. Budowanie tej Tree Recursively
Stworzenie funkcji that bierze a subset of data anda current depth. It checks stopping conditions (np., maximum depte te majorite class. Otherwise, find thee best split and create an internal node, then recursively call thee functionon oth left and right split.
5. Przewidywania makowe
Once thee tree is built, prevention is expexforward: starte at thee root, follow the branches by evaluating the exerure tests on thee new sampe, and return the value of thee leaf you land on.
Full Implementation in Python
Below is a complete, minimal implementation of a decisione tree for classification using Gini impurity. This code is meant for learning - it is nots optimised for large datasets.
import numpy as np
from collections import Counter
class DecisionTree:
def __init__(self, max_depth=None, min_samples_split=2):
self.max_depth = max_depth
self.min_samples_split = min_samples_split
self.tree = None
def fit(self, X, y):
dataset = np.column_stack((X, y))
self.tree = self._grow_tree(dataset)
def _grow_tree(self, dataset, depth=0):
X, y = dataset[:, :-1], dataset[:, -1]
n_samples, n_features = X.shape
n_labels = len(np.unique(y))
# Stopping conditions
if (n_labels == 1 or depth == self.max_depth or n_samples < self.min_samples_split):
leaf_value = Counter(y).most_common(1)[0][0]
return {'leaf': True, 'value': leaf_value}
best_feature, best_threshold = self._best_split(dataset, n_features)
if best_feature is None:
leaf_value = Counter(y).most_common(1)[0][0]
return {'leaf': True, 'value': leaf_value}
left_idx, right_idx = self._split(dataset[:, best_feature], best_threshold)
left_subtree = self._grow_tree(dataset[left_idx], depth+1)
right_subtree = self._grow_tree(dataset[right_idx], depth+1)
return {'leaf': False,
'feature': best_feature,
'threshold': best_threshold,
'left': left_subtree,
'right': right_subtree}
def _best_split(self, dataset, n_features):
best_gini = float('inf')
best_feature, best_threshold = None, None
for feature in range(n_features):
thresholds = np.unique(dataset[:, feature])
for i in range(len(thresholds)-1):
thresh = (thresholds[i] + thresholds[i+1]) / 2
left_idx, right_idx = self._split(dataset[:, feature], thresh)
if len(left_idx) == 0 or len(right_idx) == 0:
continue
gini = self._gini_gain(dataset, left_idx, right_idx)
if gini < best_gini:
best_gini = gini
best_feature = feature
best_threshold = thresh
return best_feature, best_threshold
def _split(self, values, threshold):
left_idx = np.where(values <= threshold)[0]
right_idx = np.where(values > threshold)[0]
return left_idx, right_idx
def _gini_gain(self, dataset, left_idx, right_idx):
total = len(left_idx) + len(right_idx)
gini_left = self._gini(dataset[left_idx, -1])
gini_right = self._gini(dataset[right_idx, -1])
return (len(left_idx)/total) * gini_left + (len(right_idx)/total) * gini_right
def _gini(self, labels):
_, counts = np.unique(labels, return_counts=True)
p = counts / np.sum(counts)
return 1 - np.sum(p**2)
def predict(self, X):
return np.array([self._predict_row(x, self.tree) for x in X])
def _predict_row(self, x, node):
if node['leaf']:
return node['value']
if x[node['feature']] <= node['threshold']:
return self._predict_row(x, node['left'])
else:
return self._predict_row(x, node['right'])
Testing thee Tree
Use a simple dataset like thee classic iris dataset (two factures for binary classification). The equant 1; Xi1; FLT: 0 message 3; Xi3; scikit-learn Iris dataset behind 1; Xi1; FLT: 1 methreas 3; Xion3; works well. Compare your tree 's closacy witch scikit-learn' s behin1; FLT: 2 messad; X3; tto verify correctess.
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
data = load_iris()
X = data.data[:100] # take only first two classes (binary)
y = data.target[:100]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
tree = DecisionTree(max_depth=3)
tree.fit(X_train, y_train)
preds = tree.predict(X_test)
accuracy = np.mean(preds == y_test)
print(f'Accuracy: {accuracy:.2f}')
Advanced Techniques to Improve Your Tree
Pruning to Avoid Overfitting
A fully grown tree can memorise noise in the training data. Pruning removes branches that have little predistitiva power. Common methods are pre-pruning (stopping growth harty via via via 1; providen1; FLT: 4 memorandum 3; providence 1; or providentiva 1; FLT: 5 melang 3; provideng;) and post- pruning (gring thee full tree then removiving branches using a validation set or cost-compledity pruning). Oumentan already supports pre-pruning.
Handling Continuous andCategorical Features
For continuous factores, we use midpoints between sorted values as mololds. For categorical factores (np., quenquentes; Color = red / green / blue factors;), each category can beste a separate branch (multi-way split) or you can binary-encore them. Most modern implementations (like scikit-learn) use binary splits even for categoricategorical facicures bya evatitutinag all subsets.
Dealing with Missing Values
Rel-exterd data often has missing values. A simple approvach is to assign missing values to thee most frequent branch among training samples thave thee facilure. C4.5 wykorzystuje metodę prawdopodobieństwa. Seste this is a beginner tutorial, we assume the data is complete.
Porównywanie bibliotek wigh i Further Reading
Podczas gdy building frem scratch is educational, production systems use libraries such as scikit-learn their delice idee optimised C implementations. You can learn more from thee offical ende1; exict: 0 messages 3; exime; scikit-learn decisions trees documentation end 1; exist book. 1 messan ene; exiond Friedman is ain autritative resource.
Konkluzja
Building a decident tree from scratch demystifies one of thee most fundamentaltal algorithms in machine learning. You have learned how a simple recursive splitting procedure can produce a powerful model. By writing thee code youff, you gain a deeper understang of impuryty meares, split selection, and the trade-off biaan d variance. As a next step, try adding ression support, pruning, or handling categoric.