Лабораторная работа №11: Ансамбли. Random Forest
Цель: На практике убедиться в превосходстве ансамблей над одиночными моделями. Мы сравним неустойчивое Дерево Решений с мощным Случайным Лесом, научимся использовать OOB Score для валидации без отложенной выборки и визуализируем важность признаков для картинок.
Инструменты:
sklearn.ensemble: RandomForestClassifier.sklearn.tree: DecisionTreeClassifier.sklearn.datasets: load_digits (Рукописные цифры).
Данные: Digits Dataset. Это набор изображений 8x8 пикселей (всего 64 признака), где каждая картинка — это рукописная цифра от 0 до 9.
Часть 1: Одиночное Дерево vs Случайный Лес
Деревья склонны к переобучению (высокая дисперсия). Лес усредняет множество деревьев, снижая дисперсию.
Часть 2: Out-of-Bag (OOB) Score
При бутстрэпе (создании подвыборок для каждого дерева) часть данных (~37%) не попадает в обучение. Лес может использовать их как валидационную выборку. Это позволяет оценить качество модели прямо в процессе обучения.
Задание 2.1: Включаем OOB
- Создайте Random Forest с параметром
oob_score=True. - Обучите его на X_train.
- Сравните атрибут
oob_score_с реальным скором наX_test. Они должны быть близки.
# TODO: Создайте лес с oob_score=True
# forest_oob = RandomForestClassifier(n_estimators=100, oob_score=True, random_state=42, n_jobs=-1)
# forest_oob.fit(X_train, y_train)
# print(f"OOB Score (на Train): {forest_oob.oob_score_:.4f}")
# print(f"Test Score (на Test): {forest_oob.score(X_test, y_test):.4f}")
Преимущество OOB Score
Вывод: OOB Score дает отличную оценку обобщающей способности без выделения отдельной валидационной выборки.
Часть 3: Важность признаков (Feature Importance)
У нас 64 признака (пикселя). Какие из них важны для распознавания цифры?
В Random Forest мы можем посмотреть на feature_importances_. Так как признаки — это пиксели картинки 8x8, мы можем нарисовать важность как тепловую карту.
Задание 3.1: Визуализация важности пикселей
- Извлеките массив важностей из обученной модели
forest. - Измените его форму (
reshape) обратно в 8x8. - Постройте
sns.heatmap.
# TODO: Получите важность признаков
# importances = forest.feature_importances_
# TODO: Преобразуйте в матрицу 8x8
# importances_img = importances.reshape(8, 8)
# Визуализация
# plt.figure(figsize=(8, 6))
# sns.heatmap(importances_img, cmap='hot', annot=False)
# plt.title("Какие пиксели важны для распознавания цифр?")
# plt.show()
Пища для размышлений
Почему края картинки (черные/темные области) имеют почти нулевую важность? А где находится центр принятия решений?
Часть 4: Влияние количества деревьев
Работает ли правило “Больше — лучше”?
Задание 4.1: Кривая обучения
Проверьте, как меняется качество при увеличении числа деревьев от 10 до 200.
n_trees = [10, 50, 100, 200]
scores = []
# TODO: Напишите цикл
# for n in n_trees:
# rf = RandomForestClassifier(n_estimators=n, random_state=42, n_jobs=-1)
# rf.fit(X_train, y_train)
# scores.append(rf.score(X_test, y_test))
# plt.plot(n_trees, scores, marker='o')
# plt.xlabel("Количество деревьев")
# plt.ylabel("Accuracy")
# plt.title("Зависимость качества от размера леса")
# plt.show()
Инженерный вывод
Обычно график быстро растет и выходит на плато. Ставить 1000 деревьев редко имеет смысл — качество не вырастет, а время расчета увеличится.