Пример 1. Вычисление индекса Джини

Дерево решений разделяет пространство признаков с помощью условий вида:

xⱼ ≤ t.

При классификации алгоритм стремится формировать узлы, содержащие преимущественно объекты одного класса.

Для оценки однородности узла используется индекс Джини:

G = 1 − Σpₖ²,

где pₖ — доля объектов класса k в узле.

Рассмотрим 10 объектов: 5 относятся к классу 0, а 5 — к классу 1.

Индекс Джини:

G = 1 − (0.5² + 0.5²) = 0.5.

Если узел содержит объекты только одного класса, индекс Джини равен 0.

Реализация на Python:

import numpy as np

 

def gini(y):

    classes, counts = np.unique(

        y, return_counts=True

    )

    probabilities = counts / counts.sum()

    return 1 - np.sum(probabilities ** 2)

 

y = np.array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1])

 

print("Индекс Джини:", gini(y))

print("Чистый узел:", gini(np.array([1, 1, 1])))

Результат:

Индекс Джини: 0.5

Чистый узел: 0.0

Пример 2. Обучение дерева решений для классификации

Дерево решений последовательно проверяет условия для признаков и направляет объект по ветвям до листа, содержащего прогноз.

Рассмотрим простую задачу классификации по одному числовому признаку.

import numpy as np

from sklearn.tree import DecisionTreeClassifier, export_text

 

X = np.array([

    [1], [2], [3], [4], [5], [6]

])

 

y = np.array([0, 0, 0, 1, 1, 1])

 

model = DecisionTreeClassifier(

    criterion="gini",

    max_depth=2,

    random_state=42

)

 

model.fit(X, y)

 

print(export_text(

    model,

    feature_names=["Признак"]

))

 

print("Прогноз для 2.5:", model.predict([[2.5]])[0])

print("Прогноз для 5.5:", model.predict([[5.5]])[0])

Результат:

Прогноз для 2.5: 0

Прогноз для 5.5: 1

Дерево находит правило разделения объектов на классы. В данном случае граница проходит между значениями 3 и 4.

Пример 3. Влияние глубины дерева на качество модели

Глубина дерева влияет на его сложность.

Глубокое дерево может подстраиваться под шум обучающих данных. Ограничения max_depth и min_samples_leaf помогают уменьшить риск переобучения.

from sklearn.datasets import make_classification

from sklearn.model_selection import train_test_split

from sklearn.tree import DecisionTreeClassifier

from sklearn.metrics import accuracy_score

 

X, y = make_classification(

    n_samples=300,

    n_features=5,

    n_informative=3,

    n_redundant=0,

    flip_y=0.1,

    random_state=42

)

 

X_train, X_test, y_train, y_test = train_test_split(

    X, y,

    test_size=0.2,

    stratify=y,

    random_state=42

)

 

for depth in [2, 4, None]:

    model = DecisionTreeClassifier(

        max_depth=depth,

        min_samples_leaf=3,

        random_state=42

    )

 

    model.fit(X_train, y_train)

 

    train_accuracy = accuracy_score(

        y_train, model.predict(X_train)

    )

 

    test_accuracy = accuracy_score(

        y_test, model.predict(X_test)

    )

 

    print("Глубина:", depth)

    print("Обучающая точность:", round(train_accuracy, 3))

    print("Тестовая точность:", round(test_accuracy, 3))

    print()

Сравнение результатов позволяет увидеть, как ограничение глубины влияет на качество классификации.

Для выбора гиперпараметров следует использовать валидационные данные, а тестовую выборку сохранять для итоговой независимой оценки.