УМК СПО

Учебно-методические комплексы

для преподавателей СПО








Деревья решений и случайный лес

ОП.10 Машинное обучение
Практическая работа №5
Тема: Деревья решений и случайный лес

Цель работы: Научиться строить и настраивать деревья решений и случайный лес для задач классификации, сравнивать их эффективность, анализировать важность признаков.
Время выполнения: 2 академических часа
Инструменты: Python + Jupyter Notebook, sklearn, matplotlib, seaborn

ЗАДАНИЕ ДЛЯ СТУДЕНТА

Этап 1. Загрузка данных и визуализация дерева (15 минут)



import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
from sklearn.preprocessing import StandardScaler

# Загрузка данных Iris
iris = load_iris()
X = iris.data
y = iris.target
feature_names = iris.feature_names
target_names = iris.target_names

print(f"Размер данных: {X.shape}")
print(f"Признаки: {feature_names}")
print(f"Классы: {target_names}")

# Разделение на выборки
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y
)

# Обучение дерева решений
tree = DecisionTreeClassifier(random_state=42, max_depth=3)
tree.fit(X_train, y_train)

# Визуализация дерева
plt.figure(figsize=(16, 10))
plot_tree(tree, feature_names=feature_names, class_names=target_names, filled=True, rounded=True)
plt.title("Дерево решений (глубина 3)")
plt.show()

# Предсказания
y_pred_tree = tree.predict(X_test)
print(f"Accuracy дерева решений: {accuracy_score(y_test, y_pred_tree):.4f}")



Вопрос: Какие признаки используются на первых узлах дерева? Сколько листьев получилось?

Этап 2. Влияние глубины дерева на качество (15 минут)



# Эксперимент с разной глубиной дерева
depths = range(1, 11)
train_scores = []
test_scores = []

for depth in depths:
tree = DecisionTreeClassifier(max_depth=depth, random_state=42)
tree.fit(X_train, y_train)
train_scores.append(accuracy_score(y_train, tree.predict(X_train)))
test_scores.append(accuracy_score(y_test, tree.predict(X_test)))

# Визуализация
plt.figure(figsize=(10, 6))
plt.plot(depths, train_scores, 'o-', label='Обучающая выборка', linewidth=2)
plt.plot(depths, test_scores, 's-', label='Тестовая выборка', linewidth=2)
plt.xlabel('Глубина дерева')
plt.ylabel('Accuracy')
plt.title('Влияние глубины дерева на качество')
plt.legend()
plt.grid(True, alpha=0.3)

# Определение точки переобучения
print("Результаты при разной глубине:")
for depth in depths:
print(f"Глубина {depth}: Train = {train_scores[depth-1]:.4f}, Test = {test_scores[depth-1]:.4f}")

best_depth = depths[np.argmax(test_scores)]
plt.axvline(x=best_depth, color='r', linestyle='--', label=f'Лучшая глубина = {best_depth}')
plt.legend()
plt.show()



Вопросы:
• Начиная с какой глубины наблюдается переобучение?
• Какая глубина оптимальна для данного датасета?

Этап 3. Важность признаков в дереве решений (10 минут)



# Обучение дерева с оптимальной глубиной
best_tree = DecisionTreeClassifier(max_depth=best_depth, random_state=42)
best_tree.fit(X_train, y_train)

# Важность признаков
feature_importance = pd.DataFrame({
'feature': feature_names,
'importance': best_tree.feature_importances_
}).sort_values('importance', ascending=False)

print("Важность признаков:")
print(feature_importance)

# Визуализация
plt.figure(figsize=(8, 5))
plt.barh(feature_importance['feature'], feature_importance['importance'], color='skyblue')
plt.xlabel('Важность')
plt.title('Важность признаков в дереве решений')
plt.gca().invert_yaxis()
plt.show()



Вопрос: Какой признак оказался самым важным? Соответствует ли это структуре дерева?

Этап 4. Случайный лес (Random Forest) (15 минут)



# Обучение случайного леса
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X_train, y_train)

# Предсказания
y_pred_rf = rf.predict(X_test)
y_pred_tree = best_tree.predict(X_test)

print("Сравнение моделей:")
print(f"Дерево решений: Accuracy = {accuracy_score(y_test, y_pred_tree):.4f}")
print(f"Случайный лес: Accuracy = {accuracy_score(y_test, y_pred_rf):.4f}")

# Детальный отчёт для случайного леса
print("\nClassification Report (Random Forest):")
print(classification_report(y_test, y_pred_rf, target_names=target_names))

# Матрица ошибок
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
from sklearn.metrics import ConfusionMatrixDisplay

ConfusionMatrixDisplay.from_predictions(y_test, y_pred_tree, ax=axes[0], cmap='Blues')
axes[0].set_title('Дерево решений')
ConfusionMatrixDisplay.from_predictions(y_test, y_pred_rf, ax=axes[1], cmap='Blues')
axes[1].set_title('Случайный лес')
plt.tight_layout()
plt.show()



Вопрос: Какая модель показала лучший результат? Почему?

Этап 5. Количество деревьев в случайном лесе (15 минут)



# Эксперимент с разным количеством деревьев
n_estimators_list = [1, 5, 10, 20, 50, 100, 150, 200]
rf_scores = []

for n in n_estimators_list:
rf = RandomForestClassifier(n_estimators=n, random_state=42)
rf.fit(X_train, y_train)
y_pred = rf.predict(X_test)
acc = accuracy_score(y_test, y_pred)
rf_scores.append(acc)
print(f"n_estimators={n}: Accuracy = {acc:.4f}")

# Визуализация
plt.figure(figsize=(10, 6))
plt.plot(n_estimators_list, rf_scores, 'o-', linewidth=2)
plt.xlabel('Количество деревьев (n_estimators)')
plt.ylabel('Accuracy')
plt.title('Влияние количества деревьев на качество случайного леса')
plt.grid(True, alpha=0.3)
plt.show()



Вопрос: С какого количества деревьев качество перестаёт расти? Какое значение выбрать?

Этап 6. Важность признаков в случайном лесе (10 минут)



# Важность признаков в случайном лесе
rf_importance = pd.DataFrame({
'feature': feature_names,
'importance': rf.feature_importances_
}).sort_values('importance', ascending=False)

print("Важность признаков (Random Forest):")
print(rf_importance)

# Сравнение важности признаков в двух моделях
fig, axes = plt.subplots(1, 2, figsize=(14, 5))

axes[0].barh(feature_importance['feature'], feature_importance['importance'], color='skyblue')
axes[0].set_title('Дерево решений')
axes[0].set_xlabel('Важность')
axes[0].invert_yaxis()

axes[1].barh(rf_importance['feature'], rf_importance['importance'], color='lightgreen')
axes[1].set_title('Случайный лес')
axes[1].set_xlabel('Важность')
axes[1].invert_yaxis()

plt.tight_layout()
plt.show()



Вопрос: Совпадает ли важность признаков в дереве и в случайном лесе? Если нет, то почему?

Этап 7. Практическое задание: датасет Wine (20 минут)



from sklearn.datasets import load_wine

# Загрузка данных Wine
wine = load_wine()
X_wine = wine.data
y_wine = wine.target

print("Датасет Wine:")
print(f"Размер: {X_wine.shape}")
print(f"Признаки: {wine.feature_names}")
print(f"Классы: {wine.target_names}")

# Разделение
X_train_w, X_test_w, y_train_w, y_test_w = train_test_split(
X_wine, y_wine, test_size=0.3, random_state=42, stratify=y_wine
)

# Задание 1: Обучите дерево решений (max_depth=4)
tree_wine = DecisionTreeClassifier(max_depth=4, random_state=42)
tree_wine.fit(X_train_w, y_train_w)
y_pred_tree_w = tree_wine.predict(X_test_w)
print(f"Дерево решений (глубина 4): Accuracy = {accuracy_score(y_test_w, y_pred_tree_w):.4f}")

# Задание 2: Обучите случайный лес (n_estimators=100)
rf_wine = RandomForestClassifier(n_estimators=100, random_state=42)
rf_wine.fit(X_train_w, y_train_w)
y_pred_rf_w = rf_wine.predict(X_test_w)
print(f"Случайный лес (100 деревьев): Accuracy = {accuracy_score(y_test_w, y_pred_rf_w):.4f}")

# Задание 3: Сравните важность признаков
tree_imp_w = pd.DataFrame({
'feature': wine.feature_names,
'importance': tree_wine.feature_importances_
}).sort_values('importance', ascending=False)

rf_imp_w = pd.DataFrame({
'feature': wine.feature_names,
'importance': rf_wine.feature_importances_
}).sort_values('importance', ascending=False)

print("\nТоп-3 важных признака (Дерево):")
print(tree_imp_w.head(3))
print("\nТоп-3 важных признака (Случайный лес):")
print(rf_imp_w.head(3))

# Задание 4: Визуализация
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
axes[0].barh(tree_imp_w['feature'].head(5), tree_imp_w['importance'].head(5), color='skyblue')
axes[0].set_title('Дерево решений (топ-5)')
axes[0].invert_yaxis()
axes[1].barh(rf_imp_w['feature'].head(5), rf_imp_w['importance'].head(5), color='lightgreen')
axes[1].set_title('Случайный лес (топ-5)')
axes[1].invert_yaxis()
plt.tight_layout()
plt.show()

# Задание 5: Кросс-валидация
rf_cv = cross_val_score(RandomForestClassifier(n_estimators=100, random_state=42), X_wine, y_wine, cv=5)
print(f"Случайный лес (CV): средняя точность = {rf_cv.mean():.4f} (+/- {rf_cv.std():.4f})")



Вопрос: Какой признак оказался самым важным в обеих моделях? Совпадают ли они?

Этап 8. Выводы (10 минут)

Напишите вывод, ответив на вопросы:
1. В чём преимущества и недостатки дерева решений?
2. Как случайный лес преодолевает проблему переобучения?
3. Какое влияние оказывает глубина дерева на качество модели?
4. Для каких задач лучше подходит дерево решений, а для каких — случайный лес?

КРИТЕРИИ ОЦЕНКИ



КритерийМакс. балл
Дерево решений построено и визуализировано2
Эксперимент с глубиной дерева выполнен2
Случайный лес обучен и сравнён с деревом2
Эксперимент с количеством деревьев выполнен2
Важность признаков проанализирована1
Практическое задание выполнено и выводы написаны1
Итого10


Автор: УМК СПО
Лицензия: Бесплатное использование с указанием источника





Логин: Пароль: Забыли пароль?Регистрация

Самозанятый: Стешенко Светлана Николаевна ИНН: 231408226339

Актуальная версия — 2026
Сайт сделан на SiNG cms © 2010-2020