Методы ансамбля: элегантные методы для получения улучшенных результатов машинного обучения
Опубликовано: 2022-03-11Методы ансамбля — это методы, которые создают несколько моделей, а затем объединяют их для получения улучшенных результатов. Методы ансамбля обычно дают более точные решения, чем одна модель. Так было в ряде соревнований по машинному обучению, где в победивших решениях использовались ансамблевые методы. Победитель популярного конкурса Netflix использовал ансамблевый метод для реализации мощного алгоритма совместной фильтрации. Другой пример — KDD 2009, где победитель также использовал ансамблевые методы. Вы также можете найти победителей, которые использовали эти методы в соревнованиях Kaggle, например, вот интервью с победителем конкурса CrowdFlower.
Важно, чтобы мы поняли несколько терминов, прежде чем мы продолжим эту статью. На протяжении всей статьи я использовал термин «модель» для описания результатов алгоритма, который обучался на данных. Затем эта модель используется для прогнозирования. Этот алгоритм может быть любым алгоритмом машинного обучения, таким как логистическая регрессия, дерево решений и т. д. Эти модели, когда они используются в качестве входных данных для ансамблевых методов, называются «базовыми моделями».
В этом сообщении блога я расскажу о методах ансамбля для классификации и опишу некоторые широко известные методы ансамбля: голосование, суммирование, бэггинг и бустинг.
Ансамблевые методы на основе голосования и усреднения
Голосование и усреднение — два самых простых ансамблевых метода. Они оба просты для понимания и реализации. Голосование используется для классификации, а усреднение — для регрессии.
В обоих методах первым шагом является создание нескольких моделей классификации/регрессии с использованием некоторого обучающего набора данных. Каждая базовая модель может быть создана с использованием разных разбиений одного и того же обучающего набора данных и одного и того же алгоритма или с использованием одного и того же набора данных с разными алгоритмами или любым другим методом. Следующий псевдокод в стиле Python показывает использование одного и того же обучающего набора данных с разными алгоритмами.
train = load_csv("train.csv") target = train["target"] train = train.drop("target") test = load_csv("test.csv") algorithms = [logistic_regression, decision_tree_classification, ...] #for classification algorithms = [linear_regression, decision_tree_regressor, ...] #for regression predictions = matrix(row_length=len(target), column_length=len(algorithms)) for i,algorithm in enumerate(algorithms): predictions[,i] = algorithm.fit(train, target).predict(test)
В соответствии с приведенным выше псевдокодом мы создали прогнозы для каждой модели и сохранили их в матрице, называемой прогнозами, где каждый столбец содержит прогнозы одной модели.
Голосование большинством
Каждая модель делает прогноз (голосования) для каждого тестового экземпляра, и окончательный выходной прогноз — это тот, который получает более половины голосов. Если ни один из прогнозов не получил более половины голосов, мы можем сказать, что метод ансамбля не может дать устойчивый прогноз для этого случая. Хотя это широко используемый метод, вы можете попробовать прогноз с наибольшим количеством голосов (даже если он составляет менее половины голосов) в качестве окончательного прогноза. В некоторых статьях вы можете увидеть, что этот метод называется «многочисленным голосованием».
Взвешенное голосование
В отличие от голосования большинством, где каждая модель имеет одинаковые права, мы можем повысить важность одной или нескольких моделей. При взвешенном голосовании вы несколько раз учитываете прогноз лучших моделей. Поиск разумного набора весов зависит от вас.
Простое усреднение
В простом методе усреднения для каждого экземпляра набора тестовых данных рассчитываются средние прогнозы. Этот метод часто уменьшает переобучение и создает более сглаженную регрессионную модель. Следующий код псевдокода демонстрирует этот простой метод усреднения:
final_predictions = [] for row_number in len(predictions): final_predictions.append( mean(prediction[row_number, ]) )
Взвешенное усреднение
Взвешенное усреднение — это слегка модифицированная версия простого усреднения, где предсказание каждой модели умножается на вес, а затем рассчитывается их среднее значение. Следующий код псевдокода показывает взвешенное усреднение:
weights = [..., ..., ...] #length is equal to len(algorithms) final_predictions = [] for row_number in len(predictions): final_predictions.append( mean(prediction[row_number, ]*weights) )
Объединение нескольких моделей машинного обучения
Стекирование, также известное как обобщение с накоплением, представляет собой ансамблевый метод, при котором модели объединяются с использованием другого алгоритма машинного обучения. Основная идея состоит в том, чтобы обучить алгоритмы машинного обучения с помощью обучающего набора данных, а затем сгенерировать новый набор данных с этими моделями. Затем этот новый набор данных используется в качестве входных данных для алгоритма машинного обучения объединителя.
Псевдокод процедуры стекирования резюмируется следующим образом:
base_algorithms = [logistic_regression, decision_tree_classification, ...] #for classification stacking_train_dataset = matrix(row_length=len(target), column_length=len(algorithms)) stacking_test_dataset = matrix(row_length=len(test), column_length=len(algorithms)) for i,base_algorithm in enumerate(base_algorithms): stacking_train_dataset[,i] = base_algorithm.fit(train, target).predict(train) stacking_test_dataset[,i] = base_algorithm.predict(test) final_predictions = combiner_algorithm.fit(stacking_train_dataset, target).predict(stacking_test_dataset)
Как вы можете видеть в приведенном выше псевдокоде, обучающий набор данных для алгоритма объединителя генерируется с использованием выходных данных базовых алгоритмов. В псевдокоде базовый алгоритм генерируется с использованием обучающего набора данных, а затем тот же набор данных снова используется для прогнозирования. Но, как мы знаем, в реальном мире мы не используем один и тот же набор обучающих данных для прогнозирования, поэтому для решения этой проблемы вы можете увидеть некоторые реализации стекирования, в которых набор обучающих данных разделен. Ниже вы можете увидеть псевдокод, в котором обучающий набор данных разбивается перед обучением базовых алгоритмов:

base_algorithms = [logistic_regression, decision_tree_classification, ...] #for classification stacking_train_dataset = matrix(row_length=len(target), column_length=len(algorithms)) stacking_test_dataset = matrix(row_length=len(test), column_length=len(algorithms)) for i,base_algorithm in enumerate(base_algorithms): for trainix, testix in split(train, k=10): #you may use sklearn.cross_validation.KFold of sklearn library stacking_train_dataset[testcv,i] = base_algorithm.fit(train[trainix], target[trainix]).predict(train[testix]) stacking_test_dataset[,i] = base_algorithm.fit(train).predict(test) final_predictions = combiner_algorithm.fit(stacking_train_dataset, target).predict(stacking_test_dataset)
Bootstrap Агрегация
Название Bootstrap Aggregation, также известное как «Bagging», обобщает ключевые элементы этой стратегии. В алгоритме бэггинга первый шаг включает создание нескольких моделей. Эти модели генерируются с использованием одного и того же алгоритма со случайными подвыборками набора данных, которые случайным образом извлекаются из исходного набора данных методом начальной выборки. При начальной загрузке некоторые исходные примеры появляются более одного раза, а некоторые исходные примеры отсутствуют в выборке. Если вы хотите создать поднабор данных с m элементами, вы должны выбрать случайный элемент из исходного набора данных m раз. И если целью является создание n наборов данных, вы выполняете этот шаг n раз.
В конце у нас есть n наборов данных, где количество элементов в каждом наборе данных равно m. Следующий псевдокод в стиле Python демонстрирует загрузочную выборку:
def bootstrap_sample(original_dataset, m): sub_dataset = [] for i in range(m): sub_dataset.append( random_one_element(original_dataset) ) return sub_dataset
Второй шаг в пакетировании — это объединение сгенерированных моделей. Для этого используются хорошо известные методы, такие как голосование и усреднение.
Общий псевдокод выглядит так:
def bagging(n, m, base_algorithm, train_dataset, target, test_dataset): predictions = matrix(row_length=len(target), column_length=n) for i in range(n): sub_dataset = bootstrap_sample(train_dataset, m) predictions[,i] = base_algorithm.fit(original_dataset, target).predict(test_dataset) final_predictions = voting(predictions) # for classification final_predictions = averaging(predictions) # for regression return final_predictions
При бэггинге каждая подвыборка может генерироваться независимо друг от друга. Таким образом, генерация и обучение могут выполняться параллельно.
Вы также можете найти реализацию стратегии упаковки в некоторых алгоритмах. Например, алгоритм Random Forest использует технику мешков с некоторыми отличиями. Random Forest использует случайный выбор признаков, а базовым алгоритмом является алгоритм дерева решений.
Повышение: преобразование слабых моделей в сильные
Термин «повышение» используется для описания семейства алгоритмов, способных преобразовывать слабые модели в сильные. Модель является слабой, если она имеет значительную частоту ошибок, но производительность не является случайной (что приводит к частоте ошибок 0,5 для двоичной классификации). Повышение постепенно строит ансамбль путем обучения каждой модели с одним и тем же набором данных, но где веса экземпляров корректируются в соответствии с ошибкой последнего прогноза. Основная идея заключается в том, чтобы заставить модели сосредоточиться на сложных экземплярах. В отличие от бэггинга, бустинг — это последовательный метод, поэтому здесь нельзя использовать параллельные операции.
Общая процедура алгоритма бустинга определяется следующим образом:
def adjust_dataset(_train, errors): #create a new dataset by using the hardest instances ix = get_highest_errors_index(train) return concat(_train[ix], random_select(train)) models = [] _train = random_select(train) for i in range(n): #n rounds model = base_algorithm.fit(_train) predictions = model.predict(_train) models.append(model) errors = calculate_error(predictions) _train = adjust_dataset(_train, errors) final_predictions = combine(models, test)
Функция Adjust_dataset возвращает новый набор данных, содержащий самые сложные экземпляры, которые затем можно использовать для обучения базового алгоритма.
Adaboost — это широко известный алгоритм, который представляет собой метод повышения. Основатели Adaboost получили за свою работу премию Геделя. В основном алгоритм дерева решений предпочтительнее в качестве базового алгоритма для Adaboost, а в библиотеке sklearn базовым алгоритмом по умолчанию для Adaboost является дерево решений (AdaBoostRegressor и AdaBoostClassifier). Как мы уже обсуждали в предыдущем абзаце, для Adaboost применяется тот же добавочный метод. Информация, собранная на каждом этапе алгоритма AdaBoost о «жесткости» каждой обучающей выборки, передается в модель. Этап «корректировки набора данных» отличается от описанного выше, а этап «объединения моделей» рассчитывается с использованием взвешенного голосования.
Заключение
Хотя ансамблевые методы могут помочь вам выиграть соревнования по машинному обучению за счет разработки сложных алгоритмов и получения результатов с высокой точностью, они часто не предпочтительны в отраслях, где более важна интерпретируемость. Тем не менее, эффективность этих методов неоспорима, а их преимущества в соответствующих приложениях могут быть огромными. В таких областях, как здравоохранение, даже минимальное повышение точности алгоритмов машинного обучения может оказаться действительно ценным.
- Введение в теорию машинного обучения и ее приложения: наглядное пособие с примерами
- Машины и доверие: как смягчить предвзятость ИИ