1. Для первого узла:

p₀ = 7 / 10 = 0.7.

p₁ = 3 / 10 = 0.3.

G = 1 − (0.7² + 0.3²) = 0.42.

Для второго узла:

p₀ = 0.5.

p₁ = 0.5.

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

Реализация:

import numpy as np

 

def gini(y):

    _, counts = np.unique(y, return_counts=True)

    p = counts / counts.sum()

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

 

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

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

 

print("Первый узел:", gini(y1))

print("Второй узел:", gini(y2))

Результат:

Первый узел: 0.42

Второй узел: 0.5

Первый узел более однородный, поскольку его индекс Джини меньше.

2. Обучим дерево решений:

import numpy as np

from sklearn.tree import DecisionTreeClassifier, export_text

 

X = np.array([

    [2], [3], [4], [5],

    [6], [7], [8], [9]

])

 

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

 

model = DecisionTreeClassifier(

    criterion="gini",

    max_depth=2,

    random_state=42

)

 

model.fit(X, y)

 

print(export_text(

    model,

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

))

 

print("Класс для 3.5:", model.predict([[3.5]])[0])

print("Класс для 7.5:", model.predict([[7.5]])[0])

Результат:

Класс для 3.5: 0

Класс для 7.5: 1

Дерево использует условие:

Признак ≤ 5.5.

Если условие выполняется, объект относится к классу 0. В противном случае — к классу 1.

3. Сравним деревья различной сложности.

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=200,

    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 min_leaf in [1, 5]:

    for depth in [2, 5, None]:

        model = DecisionTreeClassifier(

            max_depth=depth,

            min_samples_leaf=min_leaf,

            random_state=42

        )

 

        model.fit(X_train, y_train)

 

        train_acc = accuracy_score(

            y_train,

            model.predict(X_train)

        )

 

        test_acc = accuracy_score(

            y_test,

            model.predict(X_test)

        )

 

        print(

            "Глубина:", depth,

            "min_samples_leaf:", min_leaf,

            "Train:", round(train_acc, 3),

            "Test:", round(test_acc, 3)

        )

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

Эти ограничения помогают предотвратить чрезмерную подгонку к шуму. Однако слишком строгие ограничения могут привести к недообучению.

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