Sitemap

๐——๐—ฒ๐—บ๐˜†๐˜€๐˜๐—ถ๐—ณ๐˜†๐—ถ๐—ป๐—ด ๐—š๐—ถ๐—ป๐—ถ ๐—œ๐—บ๐—ฝ๐˜‚๐—ฟ๐—ถ๐˜๐˜†: ๐—›๐—ผ๐˜„ ๐——๐—ฒ๐—ฐ๐—ถ๐˜€๐—ถ๐—ผ๐—ป ๐—ง๐—ฟ๐—ฒ๐—ฒ๐˜€ ๐—–๐—ต๐—ผ๐—ผ๐˜€๐—ฒ ๐˜๐—ต๐—ฒ ๐—ข๐—ฝ๐˜๐—ถ๐—บ๐—ฎ๐—น ๐—ฆ๐—ฝ๐—น๐—ถ๐˜

4 min readNov 2, 2026

--

A ๐˜ฎ๐˜ข๐˜ต๐˜ฉ๐˜ฆ๐˜ฎ๐˜ข๐˜ต๐˜ช๐˜ค๐˜ข๐˜ญ ๐˜ข๐˜ฏ๐˜ฅ ๐˜ฑ๐˜ณ๐˜ข๐˜ค๐˜ต๐˜ช๐˜ค๐˜ข๐˜ญ ๐˜ฅ๐˜ฆ๐˜ฆ๐˜ฑ ๐˜ฅ๐˜ช๐˜ท๐˜ฆ ๐˜ช๐˜ฏ๐˜ต๐˜ฐ ๐˜Š๐˜ˆ๐˜™๐˜› ๐˜ฅ๐˜ฆ๐˜ค๐˜ช๐˜ด๐˜ช๐˜ฐ๐˜ฏ ๐˜ต๐˜ณ๐˜ฆ๐˜ฆ๐˜ด, ๐˜Ž๐˜ช๐˜ฏ๐˜ช ๐˜ช๐˜ฎ๐˜ฑ๐˜ถ๐˜ณ๐˜ช๐˜ต๐˜บ ๐˜ฅ๐˜ฆ๐˜ณ๐˜ช๐˜ท๐˜ข๐˜ต๐˜ช๐˜ฐ๐˜ฏ๐˜ด, ๐˜ด๐˜ฑ๐˜ญ๐˜ช๐˜ต ๐˜ฆ๐˜ท๐˜ข๐˜ญ๐˜ถ๐˜ข๐˜ต๐˜ช๐˜ฐ๐˜ฏ, ๐˜ข๐˜ฏ๐˜ฅ ๐˜—๐˜บ๐˜ต๐˜ฉ๐˜ฐ๐˜ฏ ๐˜ช๐˜ฎ๐˜ฑ๐˜ญ๐˜ฆ๐˜ฎ๐˜ฆ๐˜ฏ๐˜ต๐˜ข๐˜ต๐˜ช๐˜ฐ๐˜ฏ. โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”

At the heart of every decision tree classifier lies a fundamental question: Which feature and threshold will split the data into the cleanest, most distinct subsets?

In algorithms like CART (Classification and Regression Trees), this decision is driven by a metric known as Gini Impurity. While modern ensemble methods like Random Forests and Gradient Boosted Trees obscure the math behind abstractions, understanding how Gini Impurity drives node splits is essential for diagnosing tree behavior, controlling overfitting, and interpreting classification boundaries.

โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”

๐Ÿญ. ๐—ช๐—ต๐—ฎ๐˜ ๐—œ๐˜€ ๐—š๐—ถ๐—ป๐—ถ ๐—œ๐—บ๐—ฝ๐˜‚๐—ฟ๐—ถ๐˜๐˜†?

Gini Impurity measures the likelihood that a randomly chosen element from a dataset would be incorrectly labeled if it were randomly labeled according to the class distribution in the subset.

For a node ๐‘š containing samples across ๐พ distinct classes, let ๐‘_๐‘˜ denote the proportion of training instances belonging to class ๐‘˜:

๐‘_๐‘˜ = (1 / ๐‘_๐‘š) โˆ‘_{๐‘– โˆˆ ๐‘…_๐‘š} ๐•€(๐‘ฆแตข = ๐‘˜)

The Gini Impurity ๐ผ_๐บ(๐‘š) is defined as:

๐ผ_๐บ(๐‘š) = โˆ‘{๐‘˜=1..๐พ} ๐‘_๐‘˜(1 โˆ’ ๐‘_๐‘˜) = 1 โˆ’ โˆ‘{๐‘˜=1..๐พ} ๐‘_๐‘˜ยฒ

๐—•๐—ผ๐˜‚๐—ป๐—ฑ๐—ฎ๐—ฟ๐˜† ๐—–๐—ผ๐—ป๐—ฑ๐—ถ๐˜๐—ถ๐—ผ๐—ป๐˜€: โ€ข ๐— ๐—ฎ๐˜…๐—ถ๐—บ๐˜‚๐—บ ๐—ฃ๐˜‚๐—ฟ๐—ถ๐˜๐˜† (๐ผ_๐บ = 0): Every sample in node ๐‘š belongs to a single class (๐‘_๐‘— = 1, and ๐‘_๐‘˜ = 0 for all ๐‘˜ โ‰  ๐‘—). The node is pure and requires no further splitting. โ€ข ๐— ๐—ฎ๐˜…๐—ถ๐—บ๐˜‚๐—บ ๐—œ๐—บ๐—ฝ๐˜‚๐—ฟ๐—ถ๐˜๐˜†: Samples are equally distributed among all ๐พ classes (๐‘_๐‘˜ = 1 / ๐พ for all ๐‘˜): ๐ผ_{๐บ, max} = 1 โˆ’ โˆ‘ (1 / ๐พ)ยฒ = 1 โˆ’ 1 / ๐พ For binary classification (๐พ = 2), maximum impurity is 0.5. For ๐พ = 3, it is 0.667.

โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”

๐Ÿฎ. ๐—˜๐˜ƒ๐—ฎ๐—น๐˜‚๐—ฎ๐˜๐—ถ๐—ป๐—ด ๐—ฆ๐—ฝ๐—น๐—ถ๐˜๐˜€: ๐—ช๐—ฒ๐—ถ๐—ด๐—ต๐˜๐—ฒ๐—ฑ ๐—š๐—ถ๐—ป๐—ถ ๐—œ๐—บ๐—ฝ๐˜‚๐—ฟ๐—ถ๐˜๐˜† ๐—ฅ๐—ฒ๐—ฑ๐˜‚๐—ฐ๐˜๐—ถ๐—ผ๐—ป

A decision tree evaluates every candidate feature ๐‘— and threshold ๐‘ก, splitting node ๐‘š into left (๐‘š_๐ฟ) and right (๐‘š_๐‘…) subsets: โ€ข ๐‘š_๐ฟ(๐‘—, ๐‘ก) = { (๐ฑ, ๐‘ฆ) โˆˆ ๐‘š โˆฃ ๐‘ฅ_๐‘— โ‰ค ๐‘ก } โ€ข ๐‘š_๐‘…(๐‘—, ๐‘ก) = { (๐ฑ, ๐‘ฆ) โˆˆ ๐‘š โˆฃ ๐‘ฅ_๐‘— > ๐‘ก }

The quality of the split is evaluated using the Weighted Gini Impurity:

๐บ_split(๐‘—, ๐‘ก) = (๐‘_๐ฟ / ๐‘_๐‘š) ๐ผ_๐บ(๐‘š_๐ฟ) + (๐‘_๐‘… / ๐‘_๐‘š) ๐ผ_๐บ(๐‘š_๐‘…)

Equivalently, the tree maximizes the Gini Gain (ฮ”๐ผ_๐บ):

ฮ”๐ผ_๐บ(๐‘—, ๐‘ก) = ๐ผ_๐บ(๐‘š) โˆ’ ๐บ_split(๐‘—, ๐‘ก)

The chosen split satisfies: (๐‘—*, ๐‘ก*) = arg min_{๐‘—, ๐‘ก} ๐บ_split(๐‘—, ๐‘ก)

โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”

๐Ÿฏ. ๐—ฆ๐˜๐—ฒ๐—ฝ-๐—ฏ๐˜†-๐—ฆ๐˜๐—ฒ๐—ฝ ๐—ก๐˜‚๐—บ๐—ฒ๐—ฟ๐—ถ๐—ฐ๐—ฎ๐—น ๐—˜๐˜…๐—ฎ๐—บ๐—ฝ๐—น๐—ฒ

Suppose a parent node contains 10 samples: 6 Class A and 4 Class B.

Get Vinaitheerthan Renganathanโ€™s stories inย yourย inbox

Join Medium for free to get updates fromย thisย writer.

๐—ฆ๐˜๐—ฒ๐—ฝ ๐Ÿญ: Calculate Parent Gini Impurity ๐‘_๐ด = 6 / 10 = 0.6, ๐‘_๐ต = 4 / 10 = 0.4 ๐ผ_๐บ(Parent) = 1 โˆ’ (0.โถยฒ + 0.โดยฒ) = 1 โˆ’ (0.36 + 0.16) = 0.48

๐—ฆ๐˜๐—ฒ๐—ฝ ๐Ÿฎ: Candidate Split 1 divides the data into: โ€ข Left Node (4 samples): 4 Class A, 0 Class B โ†’ ๐ผ_๐บ(Left) = 1 โˆ’ (1.โฐยฒ + 0.โฐยฒ) = 0.0 โ€ข Right Node (6 samples): 2 Class A, 4 Class B โ†’ ๐ผ_๐บ(Right) = 1 โˆ’ ((2/6)ยฒ + (4/6)ยฒ) = 1 โˆ’ 0.555 = 0.444

๐บ_split = (4 / 10)(0.0) + (6 / 10)(0.444) = 0.266 ฮ”๐ผ_๐บ = 0.48 โˆ’ 0.266 = 0.214

๐—ฆ๐˜๐—ฒ๐—ฝ ๐Ÿฏ: Candidate Split 2 divides the data into: โ€ข Left Node (5 samples): 3 Class A, 2 Class B โ†’ ๐ผ_๐บ(Left) = 1 โˆ’ (0.โถยฒ + 0.โดยฒ) = 0.48 โ€ข Right Node (5 samples): 3 Class A, 2 Class B โ†’ ๐ผ_๐บ(Right) = 1 โˆ’ (0.โถยฒ + 0.โดยฒ) = 0.48

๐บ_split = (5 / 10)(0.48) + (5 / 10)(0.48) = 0.48 ฮ”๐ผ_๐บ = 0.48 โˆ’ 0.48 = 0.000

The tree selects Split 1 because it yields a significant reduction in impurity (0.266 vs 0.480).

โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”

๐Ÿฐ. ๐—š๐—ถ๐—ป๐—ถ ๐—œ๐—บ๐—ฝ๐˜‚๐—ฟ๐—ถ๐˜๐˜† ๐˜ƒ๐˜€. ๐—˜๐—ป๐˜๐—ฟ๐—ผ๐—ฝ๐˜† (๐—œ๐—ป๐—ณ๐—ผ๐—ฟ๐—บ๐—ฎ๐˜๐—ถ๐—ผ๐—ป ๐—š๐—ฎ๐—ถ๐—ป)

โ€ข Gini Impurity (1 โˆ’ โˆ‘ ๐‘_๐‘˜ยฒ): Computationally faster because it avoids logarithmic operations. It tends to favor isolating the most frequent class quickly. โ€ข Entropy (โˆ’โˆ‘ ๐‘_๐‘˜ logโ‚‚(๐‘_๐‘˜)): Slower due to log calls. It penalizes mixed distributions somewhat more heavily, often yielding slightly more balanced subtrees.

In practice, both criteria make identical split choices 97โ€“99% of the time, making Gini the preferred default in high-throughput implementations like scikit-learn.

โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”

๐Ÿฑ. ๐—ฃ๐˜†๐˜๐—ต๐—ผ๐—ป ๐—œ๐—บ๐—ฝ๐—น๐—ฒ๐—บ๐—ฒ๐—ป๐˜๐—ฎ๐˜๐—ถ๐—ผ๐—ป

Python

import numpy as np
from sklearn.tree import DecisionTreeClassifier, export_text
# 1. Define synthetic feature and binary target
X = np.array([[1], [2], [3], [4], [5], [6], [7], [8], [9], [10]])
y = np.array([0, 0, 0, 0, 1, 1, 0, 0, 1, 1])
# 2. Fit CART decision tree (single depth stump)
clf = DecisionTreeClassifier(criterion="gini", max_depth=1, random_state=42)
clf.fit(X, y)
# 3. Print learned split rule
print(export_text(clf, feature_names=["Feature_X"]))
# 4. Verification function
def calculate_gini(labels):
_, counts = np.unique(labels, return_counts=True)
probs = counts / len(labels)
return 1.0 - np.sum(probs ** 2)
print(f"Parent Gini Impurity: {calculate_gini(y):.4f}")

โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”

๐Ÿฒ. ๐—ž๐—ฒ๐˜† ๐—ง๐—ฎ๐—ธ๐—ฒ๐—ฎ๐˜„๐—ฎ๐˜†๐˜€ ๐—ณ๐—ผ๐—ฟ ๐—ฃ๐—ฟ๐—ฎ๐—ฐ๐˜๐—ถ๐˜๐—ถ๐—ผ๐—ป๐—ฒ๐—ฟ๐˜€

  • Pre-pruning is Essential: Without depth limits or leaf constraints, trees partition until every node reaches ๐บ = 0, capturing dataset noise.
  • High-Cardinality Bias: Categorical features with many levels can unfairly minimize Gini impurity through sheer partition variety.
  • Foundation of Ensembles: The speed of Gini impurity calculations allows ensembles like Random Forests to evaluate thousands of candidate feature splits across hundreds of trees in seconds.

--

--