← Назад к вопросам

Как увеличение глубины дерева влияет на дисперсию модели?

1.0 Junior🔥 183 комментариев
#Машинное обучение

Комментарии (3)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Влияние глубины дерева на дисперсию модели

Глубина дерева решений — один из ключевых гиперпараметров, который прямо влияет на компромисс между смещением (bias) и дисперсией (variance) модели.

Основные концепции

Дисперсия (Variance) — чувствительность модели к малым изменениям в обучающих данных. Высокая дисперсия означает, что модель сильно меняется при незначительных изменениях данных.

Смещение (Bias) — неправильные предположения, встроенные в алгоритм. Высокое смещение означает, что модель недообучена.

Как глубина дерева влияет на дисперсию

Мелкое дерево (max_depth=1-3)

  • Низкая дисперсия — модель стабильна
  • Высокое смещение — модель недообучена
  • Результат: Underfitting
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
import numpy as np

X, y = make_classification(n_samples=1000, n_features=20, random_state=42)

# Мелкое дерево
shallow_tree = DecisionTreeClassifier(max_depth=2)
scores = cross_val_score(shallow_tree, X, y, cv=5, scoring='accuracy')
print(f"Shallow tree - Mean: {scores.mean():.3f}, Std: {scores.std():.3f}")
# Output: Mean: 0.795, Std: 0.012 (низкая дисперсия, высокое смещение)

Глубокое дерево (max_depth=15-30)

  • Высокая дисперсия — модель нестабильна
  • Низкое смещение — модель переобучена
  • Результат: Overfitting
# Глубокое дерево
deep_tree = DecisionTreeClassifier(max_depth=30)
scores = cross_val_score(deep_tree, X, y, cv=5, scoring='accuracy')
print(f"Deep tree - Mean: {scores.mean():.3f}, Std: {scores.std():.3f}")
# Output: Mean: 0.82, Std: 0.045 (высокая дисперсия, низкое смещение)

Визуализация компромисса

Дисперсия
    ↑
    │         ╱╲
    │        ╱  ╲
    │       ╱    ╲
    │      ╱      ╲  Глубокое дерево
    │     ╱        ╲
    │    ╱          ╲
    │   ╱            ╲
    │  ╱              ╲
    │ ╱                ╲
    │╱──────────────────╲────→ Глубина дерева
    
Мелкое дерево     Оптимум    Глубокое дерево
(Высокий bias)             (Высокая variance)
Underfitting              Overfitting

Практический пример: обучение и тестирование

from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt

X, y = make_classification(n_samples=1000, n_features=20, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

depths = range(1, 20)
train_scores = []
test_scores = []
variances = []

for depth in depths:
    tree = DecisionTreeClassifier(max_depth=depth, random_state=42)
    
    # Cross-validation для измерения дисперсии
    cv_scores = cross_val_score(tree, X_train, y_train, cv=5)
    variance = cv_scores.std()  # Дисперсия — это std()
    
    tree.fit(X_train, y_train)
    train_scores.append(tree.score(X_train, y_train))
    test_scores.append(tree.score(X_test, y_test))
    variances.append(variance)

# Визуализация
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))

# Точность обучения vs тестирования
ax1.plot(depths, train_scores, label='Train Accuracy', marker='o')
ax1.plot(depths, test_scores, label='Test Accuracy', marker='s')
ax1.set_xlabel('Tree Depth')
ax1.set_ylabel('Accuracy')
ax1.legend()
ax1.grid(True)
ax1.set_title('Bias-Variance Tradeoff')

# Дисперсия по глубине
ax2.plot(depths, variances, label='Variance (CV Std)', color='red', marker='o')
ax2.set_xlabel('Tree Depth')
ax2.set_ylabel('Variance')
ax2.legend()
ax2.grid(True)
ax2.set_title('Variance vs Tree Depth')

plt.tight_layout()
plt.show()

Кривые обучения

from sklearn.model_selection import learning_curve

tree = DecisionTreeClassifier(max_depth=10)

train_sizes, train_scores, val_scores = learning_curve(
    tree, X_train, y_train, 
    train_sizes=np.linspace(0.1, 1.0, 10),
    cv=5,
    scoring='accuracy'
)

train_mean = np.mean(train_scores, axis=1)
train_std = np.std(train_scores, axis=1)
val_mean = np.mean(val_scores, axis=1)
val_std = np.std(val_scores, axis=1)

plt.figure(figsize=(10, 6))
plt.plot(train_sizes, train_mean, label='Train Score', marker='o')
plt.fill_between(train_sizes, train_mean - train_std, train_mean + train_std, alpha=0.2)
plt.plot(train_sizes, val_mean, label='Validation Score', marker='s')
plt.fill_between(train_sizes, val_mean - val_std, val_mean + val_std, alpha=0.2)
plt.xlabel('Training Set Size')
plt.ylabel('Accuracy')
plt.legend()
plt.grid(True)
plt.title('Learning Curve: Impact of Tree Depth on Variance')
plt.show()

Регуляризация дерева для контроля дисперсии

# 1. max_depth — ограничение глубины
tree = DecisionTreeClassifier(max_depth=10)

# 2. min_samples_split — минимум образцов для разделения
tree = DecisionTreeClassifier(min_samples_split=20)

# 3. min_samples_leaf — минимум образцов в листе
tree = DecisionTreeClassifier(min_samples_leaf=10)

# 4. max_features — количество признаков для рассмотрения
tree = DecisionTreeClassifier(max_features='sqrt')

# 5. Комбинированная регуляризация
tree = DecisionTreeClassifier(
    max_depth=10,
    min_samples_split=20,
    min_samples_leaf=10,
    max_features='sqrt'
)

tree.fit(X_train, y_train)
print(f"Train: {tree.score(X_train, y_train):.3f}")
print(f"Test: {tree.score(X_test, y_test):.3f}")

Ensemble методы для снижения дисперсии

Несмотря на высокую дисперсию отдельного дерева, ensemble методы используют эту свойство:

from sklearn.ensemble import RandomForestClassifier, BaggingClassifier

# Bagging — усреднение множества глубоких деревьев
# Каждое дерево имеет высокую дисперсию, но ensemble снижает её
bagging = BaggingClassifier(
    estimator=DecisionTreeClassifier(max_depth=30),
    n_estimators=100
)

# Random Forest — улучшенный Bagging с случайностью в признаках
rf = RandomForestClassifier(
    n_estimators=100,
    max_depth=30,  # Глубокие деревья
    random_state=42
)

bagging.fit(X_train, y_train)
rf.fit(X_train, y_train)

print(f"Bagging Train: {bagging.score(X_train, y_train):.3f}")
print(f"Bagging Test: {bagging.score(X_test, y_test):.3f}")
print(f"RF Train: {rf.score(X_train, y_train):.3f}")
print(f"RF Test: {rf.score(X_test, y_test):.3f}")

Пример анализа дисперсии

# Обучение несколько раз на случайных подвыборках
np.random.seed(42)
predictions = []

for i in range(10):
    # Случайная подвыборка
    indices = np.random.choice(len(X_train), size=int(0.8*len(X_train)), replace=False)
    X_subset = X_train[indices]
    y_subset = y_train[indices]
    
    tree = DecisionTreeClassifier(max_depth=15)
    tree.fit(X_subset, y_subset)
    pred = tree.predict_proba(X_test)[:, 1]
    predictions.append(pred)

predictions = np.array(predictions)
variance = np.var(predictions, axis=0).mean()
print(f"Average variance of predictions: {variance:.4f}")

# Глубокое дерево выдаст разные предсказания на разных подвыборках
# Мелкое дерево будет более стабильно

Когда увеличивать глубину

  • Если train accuracy >> test accuracy (большой gap) → дерево переобучено, уменьшайте глубину
  • Если train accuracy ≈ test accuracy (малый gap) → хороший баланс
  • Если train accuracy ≈ test accuracy ≈ 50% (оба низкие) → дерево недообучено, увеличивайте глубину

Ключевые выводы

  1. Мелкие деревья (low variance): Стабильны, но недообучены
  2. Глубокие деревья (high variance): Гибкие, но переобучаются
  3. Оптимальная глубина — компромисс между bias и variance
  4. Cross-validation помогает найти оптимальную глубину
  5. Ensemble методы (Random Forest, Bagging) используют высокую дисперсию в своих целях

Понимание влияния глубины на дисперсию критично для построения хороших моделей и избежания переобучения.

Как увеличение глубины дерева влияет на дисперсию модели? | PrepBro