В прошлой статье мы лишь мельком затронули такую тему, как ансамблевое обучение, дав краткое определение парочке терминов. Сегодня в планах зарыться в это дело подробнее, рассмотрев некоторые из популярных методов. Поэтому предупреждаем сразу: букв будет много. А также концептов, терминов и примеров. Со своей стороны обещаем рассказать настолько простым языком, насколько это возможно в контексте машинного обучения. В любом случае располагайтесь поудобнее. Мы здесь надолго.
Ансамблевое обучение — это подход в машинном обучении, при котором несколько моделей объединяются вместе для решения задачи. Вместо того чтобы полагаться на одну модель, мы используем ансамбль моделей (согласитесь, звучит красиво?), чтобы получить более точные и устойчивые прогнозы.
Вот как они работают: объединяют несколько методов машинного обучения в одну модель, чтобы уменьшить разброс (в бэггинге), сместить предсказания в нужном направлении (в бустинге) или просто улучшить точность (в стекинге).
Это довольно старая школа: первые работы в этой области были ещё в 1970-х, но реальный бум начался в 1990-х, когда появились методы вроде бэггинга и бустинга. Сегодня ансамблевые методы — это такой стандарт, который стоит учитывать всякий раз, когда требуется высокая точность предсказаний.
Ансамблевое обучение повторяет процесс раз за разом, чтобы модель научилась данным и делала точные предсказания. Это действительно влияет на правильность предсказаний, особенно в сравнении с моделями, которые так не обучаются.
Да, это сложно, требует терпения и времени, но практика, как говорится, делает мастера. Если делать всё правильно и не сдаваться, то с каждым днем задача будет всё проще и больше не будет казаться такой трудной.
Если прежде сталкивались с таким типом обучения и видели все, да-да, все, ну или большинство методов, которых там немало, то у вас наверняка возникал вопрос:
Почему так много методов?
Всё просто и сложно одновременно: потому что разные методы ансамблевого обучения решают разные проблемы и имеют свои преимущества в различных сценариях. Например, случайный лес хорошо работает с большими данными и имеет низкие шансы переобучения, тогда как градиентный бустинг обычно обеспечивает лучшее качество предсказаний, но требует более тщательной настройки гиперпараметров.
Самые популярные методы ансамблевого обучения — это случайный лес, градиентный бустинг и стекинг. Эти методы вообще здорово применяются в разработке моделей и их исследованиях, потому что успели доказать свою эффективность и надежность. Вот о них мы сейчас и поговорим.
Что же такое случайный лес? Это группа деревьев решений, объединенных для выдачи одного результата. А как работает одно дерево решений? Оно делит данные с использованием различных критериев, таких как Джини, энтропия и т.д., и таким образом строит всё дерево. А случайный лес использует метод бэггинга, который объединяет множество таких деревьев из различных выборок, чтобы уменьшить разброс в данных.
Проще говоря, бутстрэпинг — это когда мы берем выборку из данных с возвращением, а затем объединяем все такие выборки, чтобы получить один результат. В случае со случайным лесом мы делаем много таких выборок и строим на них разные деревья решений. Потом мы смотрим на среднее значение всех предсказаний, сделанных этими деревьями, чтобы получить финальный результат. Этот метод ансамбля называется параллельным обучением, в отличие от бустинга, который использует последовательное обучение. В случайном лесе используется только бэггинг, что помогает уменьшить разброс в данных.
Бэггинг — это супер способ снизить дисперсию в данных. Дело в том, что если у нас много деревьев принятия решений, то обучение будет лучше, и данные будут тренироваться более качественно, а также снизится риск переобучения. В бэггинге мы просто объединяем выходные данные нескольких классификаторов, обученных на разных выборках тренировочных данных, что помогает снизить общую дисперсию.
Провести бэггинг — довольно просто, если вы знаком со случайным лесом.
from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier
from sklearn.model_selection import train_test_split
import numpy as np
# Проверка входных данных
assert isinstance(X, np.ndarray), "X должен быть массивом numpy"
assert isinstance(y, np.ndarray), "y должен быть массивом numpy"
assert X.shape[0] == y.shape[0], "Размерность X и y должна быть одинаковой"
assert np.isfinite(X).all(), "X содержит NaN или бесконечные значения"
assert np.isfinite(y).all(), "y содержит NaN или бесконечные значения"
# Разбиение данных на тренировочные и тестовые выборки
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=0)
# Создание модели
model = RandomForestRegressor(n_estimators=100, random_state=0)
# Обучение модели
model.fit(X_train, y_train)
# Предсказания на тестовых данных
y_pred = model.predict(X_test)
Этот код проверяет, что входные данные являются массивами numpy, что они имеют правильную размерность, и что они не содержат пропусков или бесконечных значений. Затем он разбивает данные на тренировочные и тестовые выборки, создает модель RandomForestRegressor с 100 деревьями и обучает ее на тренировочных данных. Затем он делает предсказания на тестовых данных.
Плюсы Random Forest:
Снижает переобучение и улучшает точность.
Может использоваться для решения задач классификации и регрессии.
Хорошо работает с категориальными и непрерывными значениями.
Автоматически обрабатывает пропущенные значения.
Нормализация данных не требуется.
Может обрабатывать большие объемы данных с высокой размерностью и определять наиболее значимые переменные.
Имеет методы для балансировки ошибок в несбалансированных данных.
Позволяет использовать внебазовые выборки для тестирования, что экономит время и ресурсы.
Минусы Random Forest:
Не дает точных непрерывных прогнозов в задачах регрессии.
Может казаться "черным ящиком" для статистических моделей, так как управление моделью практически отсутствует.
Требует много вычислительной мощности и ресурсов для построения множества деревьев решений.
Требует много времени для обучения модели.
Градиентный бустинг (Gradient Boosting) — одна из передовых техник ансамблевого машинного обучения, которая использует последовательность слабых моделей для создания надежной и точной модели. Может применяться для решения задач как регрессии, так и классификации.
Одним из главных преимуществ градиентного бустинга является его способность достигать хороших результатов даже при минимальной настройке. Он может обрабатывать большое количество признаков и не предвзято относится к любому конкретному типу признаков.
Без минусов градиентный бустинг тоже не обходится. Он более чувствителен к переобучению, чем другие методы, и может быть медленным при обучении на больших наборах данных. Но эти минусы не мешают ему оставаться на передовой для многих задач, благодаря своей гибкости, мощности и относительно хорошей производительности. Кстати, метод хорошо зарекомендовал себя в таких областях, как NLP (обработка естественного языка), CV (компьютерное зрение) и TSA (анализ временных рядов).
В отличие от AdaBoost, который применяет короткие деревья решений, называемых "пнями", градиентный бустинг начинает с простого предположения и постепенно строит более крупные деревья. Обычно в этом методе используются деревья с 8 до 32 "листьями". Ещё градиентный бустинг увеличивает размер деревьев с одинаковой скоростью, в то время как AdaBoost использует фиксированный размер для всех деревьев.
Если сразу смотреть на еще один пример бустинга – можно взглянуть и на XGBoost, который отличается от других моделей бустинга встроенной параллелизации и оптимизации процессов, а также встроенной регуляризацей, что предотвращает переобучение. И поднимает эффективность, конечно)
Процесс работы градиентного бустинга начинается с построения начальной модели, которая может быть простой и, как правило, дает невысокое качество предсказания. Затем для улучшения этой модели на каждом следующем шаге строится новая модель, которая исправляет ошибки предыдущей модели.
Формально, пусть имеется набор данных {(xi,yi)}, где xi — это наблюдение, а yi — целевой признак. Цель состоит в том, чтобы построить модель F(x), которая приближает целевую переменную y.
На каждом шаге m градиентного бустинга строится новая модель hm(x), которая аппроксимирует остатки предыдущих моделей.
На каждом шаге минимизируется функция потерь L(y,F(x)), где L — функция потерь, например, среднеквадратичная ошибка для задачи регрессии или логистическая функция потерь для задачи классификации.
Формула вычисления градиента функции потерь gi выглядит следующим образом: для каждого наблюдения i вычисляется частная производная функции потерь L(yi,F(xi)) по предсказанию модели F(xi).
Принцип работы градиентного бустинга для регрессии можно описать следующим образом:
1) Начинаем с прогнозирования среднего значения целевой переменной y_train для всех образцов.
2) Рассчитываем остатки модели на основе антиградиента функции потерь.
3) Обучаем регрессионное дерево на наборе данных X_train и остатках, затем делаем прогноз для X_train.
4) Полученный прогноз добавляется к начальному прогнозу, и шаги 2-4 повторяются для каждого дерева.
5) После обучения всех моделей снова создаём начальный прогноз из шага 1.
6) Затем делаем прогнозы для набора данных S_train на обученных деревьях и добавляем их к начальному прогнозу.
7) Полученная сумма является конечным прогнозом.
Путем использования оптимизации градиентного спуска для минимизации предопределенной функции потерь GBM постепенно от итерации к итерации улучшает прогнозы. Напоминаем, что градиентный спуск — это буквально спуск к минимуму функций. Чтобы случайно не начать подниматься — учитывается градиент, который показывает "угол наклона" функции. Хотя мы уверены, в этих терминах вы разбираетесь.
На каждом шаге обучения новое дерево настраивается на остатки предыдущего ансамбля, то есть на разницу между истинными значениями целевой переменной и предсказаниями текущего ансамбля. Это позволяет каждому новому дереву "сконцентрироваться" на ошибках предыдущих деревьев и постепенно уменьшать остатки.
Но, как мы уже сказали, GBM требует тонкой настройки гиперпараметров. Качество их подбора напрямую влияет на качество прогнозов: глубина деревьев, скорость обучения, число деревьев в ансамбле. GBM зачастую используют как раз в задачах классификации и регрессии — там "биг дата" обитает. А мы уже говорили, что GBM – наилучший вариант для работы с крупными данными.
Потестить метод можно прямо в библиотеке scikit-learn
# Импортируем необходимые библиотеки
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import accuracy_score
# Загружаем данные Iris
iris = load_iris()
X = iris.data
y = iris.target
# Разделяем данные на обучающий и тестовый наборы
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Создаем и обучаем модель градиентного бустинга
gbm = GradientBoostingClassifier(n_estimators=100, learning_rate=0.1, max_depth=3, random_state=42)
gbm.fit(X_train, y_train)
# Делаем предсказания на тестовом наборе
y_pred = gbm.predict(X_test)
# Оцениваем точность модели
accuracy = accuracy_score(y_test, y_pred)
print("Точность модели GBM:", accuracy)
Кратко о плюсах и минусах градиентного бустинга:
Плюсы:
Высокая точность прогнозирования.
Гибкость в работе с различными данными и задачами.
Устойчивость к переобучению при правильной настройке.
Автоматический отбор признаков.
Широкая поддержка в библиотеках машинного обучения.
Минусы:
Чувствительность к шуму и выбросам в данных.
Требует настройки сложных гиперпараметров.
Вычислительно затратен, особенно для больших данных и глубоких моделей.
Может быть сложным для интерпретации результатов.
Менее эффективен в задачах с дисбалансом классов.
В области машинного обучения стекинг является мощным методом в арсенале ансамблевых методов. Простыми словами, стекинг (или stacking) в машинном обучении — это как команда супергероев, которая объединяется, чтобы решить сложную задачу. У каждого супергероя есть свои уникальные способности, и они работают вместе и побеждают... Точно так же и в стекинге есть несколько моделей, каждая из которых обучена делать прогнозы по-своему. Затем есть еще одна модель, называемая мета-обучающейся, которая принимает прогнозы от других моделей и использует их, чтобы сделать окончательное предсказание.
Наверное, идеальное сравнение стеккинга с какой-нибудь вывернутой системой принятия решений в политике. Есть у нас группа политиканов, предлагающих свои решения относительно проблемы — есть президент, подписывающий документы. Как и у подобной демократии в политике, так и в ML у стеккинга есть существенный плюс — использование коллективного опыта. Сочетая дополняющие друг друга сильные стороны и смягчая индивидуальные слабости, стекинг снижает риск модельного предубеждения и переобучения — на выходе мы получаем оптимальные результаты.
В финансовых рынках стекинг нашел применение в прогнозировании цен на акции и алгоритмической торговле, где точное прогнозирование имеет первостепенное значение для принятия информированных решений. В здравоохранении стекинг помогает в диагностике и прогнозировании болезней, используя совершенно разные данные: от анамнеза и жалоб пациента в письменной форме до изображений флюорографий или данных с них.
Объединение прогнозов нескольких моделей может обеспечить более высокую производительность по сравнению с любой отдельной моделью. Стекинг расширяет этот принцип, представляя иерархический подход, в рамках которого прогнозы разнообразных базовых моделей фильтруются мета-обучающимся, тем самым синтезируя более надежное и точное окончательное предсказание.
В отличие от традиционных методов ансамблевого обучения, таких как бэггинг и бустинг, которые работают на одном уровне агрегации, стекинг представляет многоуровневую архитектуру. На базовом уровне ансамбль совершенно разнородных базовых моделей обучается независимо на входных данных, каждая из которых выявляет различные закономерности и взаимосвязи внутри набора данных. Ключевое тут слово — независимо.
Роль мета-обучающегося двойная: они изучают оптимальное сочетание прогнозов базовых моделей и генерировать окончательное предсказание на основе этого объединения. Мета-обучающийся может принимать различные формы, начиная с простых линейных моделей, таких как линейная регрессия, и заканчивая более сложными алгоритмами вплоть до нейронок или алгоритмов градиентного бустинга.
К слову, стекинг один из самых популярных методов в сравнении со всякими AdaBoost, Bagging, что можно наблюдать по количеству готовых реализаций в программных библиотеках, включая sklearn.ensemble в Python. Хотя и результаты зачастую достаточно неопределенные.
Алгоритм стекинга:
Деление выборки на k фолдов.
Для каждого объекта в k-ом фолде делается предсказание с помощью базовых алгоритмов, обученных на остальных k-1 фолдах.
Создается набор прогнозов базовых алгоритмов для каждого объекта выборки.
Метамодель обучается на сформированных прогнозах базовых алгоритмов.
Исходный тренировочный набор делится на k фолдов для кросс-валидации. Каждая базовая модель обучается на k-1 фолдах и делает прогнозы на оставшемся фолде. Это повторяется для каждого фолда, и прогнозы объединяются в новый признак. Такая процедура повторяется для каждой базовой модели. Кроме того, базовые модели обучаются на всем исходном тренировочном наборе, а затем делают прогнозы на тестовом наборе для создания нового тестового набора.
Кстати, есть упрощенная реализация “стеккинга” – блендинг. В блендинге исходный набор данных разделяется на две части: обучающий и валидационный. Базовые модели обучаются на обучающем наборе, а затем делают прогнозы на валидационном. Эти прогнозы используются для обучения мета-модели, которая затем используется для предсказания на тестовом наборе данных.
А как все это выглядит с кодом?
# Импортируем необходимые библиотеки
from sklearn.model_selection import KFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_iris
import numpy as np
# Загружаем набор данных Iris
data = load_iris()
X, y = data.data, data.target
# Разбиваем данные на обучающий и тестовый наборы
kf = KFold(n_splits=5, shuffle=True, random_state=42)
X_train_stacking = np.zeros((len(X),))
y_train_stacking = np.zeros((len(y),))
# Начинаем кросс-валидацию
for train_index, test_index in kf.split(X):
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
# Обучаем базовые модели
rf = RandomForestClassifier(n_estimators=50, random_state=42)
rf.fit(X_train, y_train)
svm = SVC(kernel='linear', C=1.0, probability=True, random_state=42)
svm.fit(X_train, y_train)
# Получаем прогнозы базовых моделей для мета-обучения
rf_pred = rf.predict_proba(X_test)
svm_pred = svm.predict_proba(X_test)
# Собираем прогнозы базовых моделей в матрицу признаков
X_train_stacking[test_index] = np.column_stack((rf_pred, svm_pred)).tolist()
y_train_stacking[test_index] = y_test.tolist()
# Создаем мета-обучающуюся модель
lr = LogisticRegression(max_iter=1000, random_state=42)
lr.fit(X_train_stacking, y_train_stacking)
# Получаем прогнозы стекинга на тестовых данных
stacking_pred = lr.predict(X_train_stacking)
# Оцениваем производительность стекинга
accuracy = accuracy_score(y_train_stacking, stacking_pred)
print("Accuracy of stacking:", accuracy)
Если быть кратким, то мы просто проводим кросс валидацию, обучаем параллельно базовые модели, снимаем их прогнозы и обучаем мета-модель на этих прогнозах и оцениваем производительность.
Кратко о плюсах и минусах стеккинга:
Плюсы стекинга:
Улучшенная обобщающая способность.
Учет разнообразия моделей.
Гибкость в выборе типов моделей.
Минусы стекинга:
Вычислительная сложность.
Сложность настройки гиперпараметров.
Риск переобучения.
Все же ансамблирование – метод, который сращивает и координирует работу нескольких моделей для достижения конечного результата. Методы могут быть разные, мы перечислили лишь несколько из них. Есть, например, метод голосования (Voting) – очень простой и чем-то напоминает стеккинг, но без авторитарной мета-модели. Он объединяет прогнозы нескольких моделей, чтобы улучшить качество предсказаний. В задачах классификации метод голосования использует схему большинства голосов: каждая модель в ансамбле делает свой прогноз, и окончательное решение принимается на основе большинства голосов. То есть класс, за который проголосовало большинство моделей, будет выбран как окончательный прогноз.
Однако метод голосования может быть как жестким (hard), так и мягким (soft). В случае жесткого голосования каждая модель предоставляет свой прогноз, и принимается решение на основе простого подсчета голосов. В мягком голосовании каждая модель, помимо прогноза, предоставляет также уровень уверенности в своем предсказании, например, вероятность принадлежности к каждому классу.
В задачах регрессии метод голосования аналогично использует усреднение прогнозов нескольких моделей. Здесь каждая модель предсказывает числовое значение, и окончательный прогноз определяется как среднее или взвешенное среднее предсказанных значений.
Почитать о нем подробнее можно – тут.
Еще один интересный метод — метод случайного подпространства (Random Subspace Method). Подход, при котором координируются несколько моделей путем обучения на различных подмножествах признаков, а не объектов. В отличие от других ансамблевых методов, которые изменяют состав обучающих выборок, метод случайного подпространства меняет состав признаков для обучения каждой модели.
Использование различных подмножеств признаков позволяет моделям обучаться на различных аспектах данных, что особенно полезно в случаях, когда данные имеют большое количество признаков или существуют взаимозависимости между ними. Метод случайного подпространства может быть особенно эффективным при работе с высокомерными данными, где количество признаков превышает количество образцов. В таких ситуациях модели могут столкнуться с проблемой переобучения или потери обобщающей способности из-за избыточной размерности данных.
В любом случае теоретически методов может быть и больше, но мы постарались привести самые популярные и используемые в машинном обучении. К сожалению, на одной модели зачастую далеко не уедешь...