Машинное обучение: ансамбль смешивания на Python

Смешивание — это ансамблевый алгоритм машинного обучения. Это разговорное название для стекового обобщения (stacked generalization) [далее будем использовать термин «пакетирование» вместо принятого в научных работах термина «стекинг»] или ансамбля пакетирования, где вместо того чтобы обучать метамодель на прогнозах вне групп, сделанных базовой моделью, модель обучается на прогнозах, сделанных на независимом наборе данных.

Термин «смешивание» использовался для описания моделей пакетирования, которые объединили многие сотни моделей в конкуренции на соревновании по машинному обучению от Netflix с призом в $1 000 000, и как таковое смешивание остаётся популярным методом и названием для пакетирования в конкурсах машинного обучения, например на Kaggle. Специально к старту нового потока курса «Машинное обучение» делимся туториалом, из которого вы узнаете, как разработать и оценить смешанный ансамбль на python. После завершения этого туториала вы будете знать:

  • Смешанные ансамбли — это тип пакетирования моделей, при котором метамодель обучается с использованием прогнозов на независимом тестовом наборе данных валидации вместо прогнозов во время k-кратной кросс-валидации.
  • Как разработать смешанный ансамбль, включая функции обучения модели и составления прогнозов на основе новых данных.
  • Как оценить смешанные ансамбли для задач классификации и регрессионного прогностического моделирования.



Обзор туториала


Этот туториал разделён на четыре части. Вот они:

  • Смешанный ансамбль.
  • Создание смешанного ансамбля.
  • Смешанный ансамбль в задаче классификации.
  • Смешанный ансамбль в задаче регрессии.

Смешанный ансамбль


Смешивание — это метод ансамблевого машинного обучения, который использует модель машинного обучения, чтобы узнать, как наилучшим образом объединить прогнозы из нескольких моделей — участников ансамбля.

Таким образом, смешивание — это то же самое, что и стековое обобщение, известное как стекинг. Часто смешивание и пакетирование взаимозаменяемы используются в одной и той же статье или в описании модели.

Многие практики машинного обучения добились успеха, используя пакетирование и связанные с ним методы для повышения точности прогнозирования в сравнении с любой из отдельных моделей. В некоторых контекстах пакетирование также называется смешиванием. Здесь мы также будем взаимозаменять термины.
Feature-Weighted Linear Stacking, 2009.

Архитектура пакетированной модели содержит две или более базовых моделей, часто называемых моделями нулевого уровня, а метамодель, которая объединяет прогнозы базовых моделей, — моделью первого уровня. Метамодель обучается на основе прогнозов, сделанных базовыми моделями на данных вне выборки.

  • Модели нулевого уровня (базовые модели) — это модели, обученные на тренировочных данных, прогнозы которых собираются.
  • Модель первого уровня (метамодель) — это модель, которая учится наилучшим образом комбинировать прогнозы базовых моделей.

Тем не менее смешивание имеет определённые коннотации для построения модели пакетированного ансамбля. Смешивание может предложить разработку стек-ансамбля, где базовые модели — это модели машинного обучения любого типа, а метамодель — это линейная модель, которая «смешивает» прогнозы базовых моделей. Например, модель линейной регрессии при прогнозировании числового значения или модель логистической регрессии при прогнозировании метки класса вычисляют взвешенную сумму прогнозов, сделанных базовыми моделями, и будут рассматриваться как смешение прогнозов.

  • Смешанный ансамбль: использование линейной модели, такой как линейная регрессия или логистическая регрессия, в качестве метамодели в ансамбле пакетированной модели.

Смешивание было термином, обычно используемым для пакетированного ансамбля во время конкурса Netflix в 2009 году. В соревновании участвовали команды в поиске прогнозных моделей, которые работали лучше родного алгоритма Netflix, приз в 1 000 000 долларов США был присуждён команде, достигшей 10-процентного улучшения производительности.

Наше решение с RMSE=0,8643^2 представляет собой линейное смешение из более чем 100 результатов. [… ] На протяжении всего описания методов мы выделяем конкретные предикторы, которые участвовали в окончательном смешанном решении.
The BellKor 2008 Solution to the Netflix Prize, 2008.

Таким образом, смешивание — это разговорный термин для ансамблевого обучения с модельной архитектурой типа пакетирования. Он редко, если вообще когда-нибудь, используется в учебниках или научных работах, кроме тех, которые связаны с машинным обучением на соревнованиях. Чаще всего термин «смешивание» используется для описания специфического применения пакетирования, когда метамодель обучается на прогнозах, сделанных базовыми моделями с независимым набором данных валидации. В этом контексте пакетирование зарезервировано для метамодели, обучаемой на прогнозах во время процедуры кросс-валидации.

  • Смешивание: ансамбль типа пакетирования, где метамодель обучается на прогнозах, сделанных на независимом наборе данных.
  • Пакетирование: ансамбль типа пакетирования, где метамодель обучается на прогнозах, сделанных во время k-кратной кросс-валидации.

Это различие распространено в сообществе соревнований по машинному обучению Kaggle.

Смешивание — это слово, введённое победителями Netflix. Оно очень близко к обобщению, но немного проще и риск утечки информации меньше. [… ] С помощью смешивания, вместо того чтобы создавать прогнозы во время кросс-валидации для тренировочного набора, вы создаёте небольшой независимый набор, скажем, 10% от тренировочного. Затем модель пакетирования тренируется только на этом небольшом наборе.
Kaggle Ensemble Guide, MLWave, 2015.

Мы используем последнее определение смешивания. Давайте посмотрим, как оно реализуется.

Разработка смешанного ансамбля


Библиотека scikit-learn не поддерживает смешивание из коробки на момент написания статьи. Но мы можем реализовать его самостоятельно, используя модели scikit-learn. Во-первых, нужно создать ряд базовых моделей. Это могут быть любые модели, которые нам нравятся в задаче регрессии или классификации. Мы можем определить функцию get_models(), которая возвращает список моделей, где каждая модель определяется как кортеж с названием и настроенным классификатором или объектом регрессии. Например, для задачи классификации мы могли бы использовать логистическую регрессию, kNN, дерево решений, SVM и наивную байесовскую модель.

# get a list of base models def get_models(): models = list() models.append(('lr', LogisticRegression())) models.append(('knn', KNeighborsClassifier())) models.append(('cart', DecisionTreeClassifier())) models.append(('svm', SVC(probability=True))) models.append(('bayes', GaussianNB())) return models

Далее нам нужно обучить смешивающую модель. Напомним, что базовые модели обучаются на тренировочном наборе данных. Метамодель обучается на прогнозах, сделанных каждой базовой моделью на независимом наборе данных.

Во-первых, мы можем в цикле перечислить модели в списке и обучить каждую из них по очереди на обучающем наборе данных. Кроме того, в этом цикле мы можем использовать обученную модель, чтобы сделать прогноз на независимом наборе данных (валидации) и сохранить прогнозы на будущее.

... # fit all models on the training set and predict on hold out set meta_X = list() for name, model in models: # fit in training set model.fit(X_train, y_train) # predict on hold out set yhat = model.predict(X_val) # reshape predictions into a matrix with one column yhat = yhat.reshape(len(yhat), 1) # store predictions as input for blending meta_X.append(yhat)

Теперь у нас есть «meta_X*», представляющий входные данные, которые могут использоваться для обучения метамодели. Каждый столбец или объект представляет выходные данные одной базовой модели. Каждая строка представляет собой один сэмпл из независимого набора данных. Мы можем применить функцию hstack() чтобы гарантировать, что этот набор данных представляет собой двумерный массив numpy, как и ожидалось моделью машинного обучения.

... # create 2d array from predictions, each set is an input feature meta_X = hstack(meta_X)

Теперь мы можем тренировать нашу метамодель. Это может быть любая модель машинного обучения, которая нам нравится, например логистическая регрессия для задачи классификации.

... # define blending model blender = LogisticRegression() # fit on predictions from base models blender.fit(meta_X, y_val)

Можно объединить всё это вместе в функцию с именем fit_ensemble(), которая обучает смешивающую модель с использованием обучающего и независимого набора данных валидации.

# fit the blending ensemble def fit_ensemble(models, X_train, X_val, y_train, y_val): # fit all models on the training set and predict on hold out set meta_X = list() for name, model in models: # fit in training set model.fit(X_train, y_train) # predict on hold out set yhat = model.predict(X_val) # reshape predictions into a matrix with one column yhat = yhat.reshape(len(yhat), 1) # store predictions as input for blending meta_X.append(yhat) # create 2d array from predictions, each set is an input feature meta_X = hstack(meta_X) # define blending model blender = LogisticRegression() # fit on predictions from base models blender.fit(meta_X, y_val) return blender

Следующий шаг — использование смешивающего ансамбля для прогнозирования новых данных. Это двухэтапный процесс. Первый шаг — использование каждой базовой модели для прогнозирования. Затем прогнозы собираются вместе и используются в качестве входных данных для модели смешивания, чтобы сделать окончательный прогноз.

Мы можем использовать тот же цикл, что и при обучении модели. То есть собрать прогнозы каждой базовой модели в обучающий набор данных, сложить прогнозы вместе и вызвать predict() в смешивающей модели с этим набором данных метауровня. Функция predict_ensemble() ниже реализует эти действия. Учитывая обучение списка базовых моделей, обучение смешивателя ансамбля и набор данных (например, тестовый набор данных или новые данные), для набора данных она вернёт набор прогнозов.

# make a prediction with the blending ensemble def predict_ensemble(models, blender, X_test): # make predictions with base models meta_X = list() for name, model in models: # predict with base model yhat = model.predict(X_test) # reshape predictions into a matrix with one column yhat = yhat.reshape(len(yhat), 1) # store prediction meta_X.append(yhat) # create 2d array from predictions, each set is an input feature meta_X = hstack(meta_X) # predict return blender.predict(meta_X)

Теперь у нас есть все элементы, необходимые для реализации смешанного ансамбля для задач классификации или регрессионного прогностического моделирования.

Смешанный ансамбль для задачи классификации


В этом разделе мы рассмотрим использование смешивания для задачи классификации. Во-первых, мы можем использовать функцию make_classification(), чтобы создать синтетическую задачу бинарной классификации с 10 000 примерами и 20 входными признаками. Весь пример приведён ниже.

# test classification dataset from sklearn.datasets import make_classification # define dataset X, y = make_classification(n_samples=10000, n_features=20, n_informative=15, n_redundant=5, random_state=7) # summarize the dataset print(X.shape, y.shape)

Запуск примера создаёт набор данных и резюмирует входные и выходные данные.

(10000, 20) (10000,)

Далее нам нужно разделить набор данных сначала на обучающие и тестовые наборы, а затем обучающий набор на подмножество, используемое для обучения базовых моделей, и подмножество, используемое для обучения метамодели. В этом случае мы будем использовать разделение 50-50 для тренировочного и тестового наборов, а затем — разделение 67-33 для тренировочного набора и набора валидации.

... # split dataset into train and test sets X_train_full, X_test, y_train_full, y_test = train_test_split(X, y, test_size=0.5, random_state=1) # split training set into train and validation sets X_train, X_val, y_train, y_val = train_test_split(X_train_full, y_train_full, test_size=0.33, random_state=1) # summarize data split print('Train: %s, Val: %s, Test: %s' % (X_train.shape, X_val.shape, X_test.shape))

Затем можно использовать функцию get_models() из предыдущего раздела для создания используемых в ансамбле классификационных моделей. После функция fit_ensemble() может быть вызвана для обучения смешанного ансамбля на этих наборах данных, а функция predict_ensemble() может использоваться для прогнозов на независимом наборе данных.

... # create the base models models = get_models() # train the blending ensemble blender = fit_ensemble(models, X_train, X_val, y_train, y_val) # make predictions on test set yhat = predict_ensemble(models, blender, X_test)

Наконец, мы можем оценить производительность модели смешивания, сообщив о точности классификации в тестовом наборе данных.

... # evaluate predictions score = accuracy_score(y_test, yhat) print('Blending Accuracy: %.3f' % score)

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

# blending ensemble for classification using hard voting from numpy import hstack from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score from sklearn.linear_model import LogisticRegression from sklearn.neighbors import KNeighborsClassifier from sklearn.tree import DecisionTreeClassifier from sklearn.svm import SVC from sklearn.naive_bayes import GaussianNB  # get the dataset def get_dataset(): X, y = make_classification(n_samples=10000, n_features=20, n_informative=15, n_redundant=5, random_state=7) return X, y  # get a list of base models def get_models(): models = list() models.append(('lr', LogisticRegression())) models.append(('knn', KNeighborsClassifier())) models.append(('cart', DecisionTreeClassifier())) models.append(('svm', SVC())) models.append(('bayes', GaussianNB())) return models  # fit the blending ensemble def fit_ensemble(models, X_train, X_val, y_train, y_val): # fit all models on the training set and predict on hold out set meta_X = list() for name, model in models: # fit in training set model.fit(X_train, y_train) # predict on hold out set yhat = model.predict(X_val) # reshape predictions into a matrix with one column yhat = yhat.reshape(len(yhat), 1) # store predictions as input for blending meta_X.append(yhat) # create 2d array from predictions, each set is an input feature meta_X = hstack(meta_X) # define blending model blender = LogisticRegression() # fit on predictions from base models blender.fit(meta_X, y_val) return blender  # make a prediction with the blending ensemble def predict_ensemble(models, blender, X_test): # make predictions with base models meta_X = list() for name, model in models: # predict with base model yhat = model.predict(X_test) # reshape predictions into a matrix with one column yhat = yhat.reshape(len(yhat), 1) # store prediction meta_X.append(yhat) # create 2d array from predictions, each set is an input feature meta_X = hstack(meta_X) # predict return blender.predict(meta_X)  # define dataset X, y = get_dataset() # split dataset into train and test sets X_train_full, X_test, y_train_full, y_test = train_test_split(X, y, test_size=0.5, random_state=1) # split training set into train and validation sets X_train, X_val, y_train, y_val = train_test_split(X_train_full, y_train_full, test_size=0.33, random_state=1) # summarize data split print('Train: %s, Val: %s, Test: %s' % (X_train.shape, X_val.shape, X_test.shape)) # create the base models models = get_models() # train the blending ensemble blender = fit_ensemble(models, X_train, X_val, y_train, y_val) # make predictions on test set yhat = predict_ensemble(models, blender, X_test) # evaluate predictions score = accuracy_score(y_test, yhat) print('Blending Accuracy: %.3f' % (score*100))

Запуск примера сначала сообщает резюме всех наборов данных, а затем точность ансамбля в тестовом наборе данных.

Примечание: ваши результаты могут различаться с учётом стохастического характера алгоритма или процедуры оценки, или различий в числовой точности. Подумайте о том, чтобы запустить пример несколько раз и сравнить средний результат.

Здесь мы видим, что смешанный ансамбль достиг точности классификации около 97,900%.

Train: (3350, 20), Val: (1650, 20), Test: (5000, 20) Blending Accuracy: 97.900

В предыдущем примере прогноз чётких меток классов был объединён с помощью модели смешивания. Это тип жёсткого голосования. Альтернатива — метод, когда каждая модель прогнозирует вероятности классов и использует метамодель для смешивания вероятностей. Это своего рода мягкое голосование, которое иногда может привести к повышению производительности. Во-первых, мы должны сконфигурировать модели, возвращающие вероятности, такие как модель SVM.

# get a list of base models def get_models(): models = list() models.append(('lr', LogisticRegression())) models.append(('knn', KNeighborsClassifier())) models.append(('cart', DecisionTreeClassifier())) models.append(('svm', SVC(probability=True))) models.append(('bayes', GaussianNB())) return models

Затем нужно изменить базовые модели, чтобы вместо чётких меток классов прогнозировать вероятности. Это может быть достигнуто вызовом функции predict_proba () внутри функции fit_ensemble() при обучении базовых моделей.

... # fit all models on the training set and predict on hold out set meta_X = list() for name, model in models: # fit in training set model.fit(X_train, y_train) # predict on hold out set yhat = model.predict_proba(X_val) # store predictions as input for blending meta_X.append(yhat)

Это означает, что мета-набор данных, используемый для обучения мета-модели, будет иметь n столбцов на классификатор, где n — количество классов в задаче прогнозирования, в нашем случае классов два. Нам также необходимо изменить прогнозы, сделанные базовыми моделями, при использовании смешивающей модели для прогнозирования новых данных.

... # make predictions with base models meta_X = list() for name, model in models: # predict with base model yhat = model.predict_proba(X_test) # store prediction meta_X.append(yhat)

Весь пример использования смешивания на спрогнозированных вероятностях классов для задачи синтетической бинарной классификации приведён ниже.

 # blending ensemble for classification using soft voting from numpy import hstack from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score from sklearn.linear_model import LogisticRegression from sklearn.neighbors import KNeighborsClassifier from sklearn.tree import DecisionTreeClassifier from sklearn.svm import SVC from sklearn.naive_bayes import GaussianNB  # get the dataset def get_dataset(): X, y = make_classification(n_samples=10000, n_features=20, n_informative=15, n_redundant=5, random_state=7) return X, y  # get a list of base models def get_models(): models = list() models.append(('lr', LogisticRegression())) models.append(('knn', KNeighborsClassifier())) models.append(('cart', DecisionTreeClassifier())) models.append(('svm', SVC(probability=True))) models.append(('bayes', GaussianNB())) return models  # fit the blending ensemble def fit_ensemble(models, X_train, X_val, y_train, y_val): # fit all models on the training set and predict on hold out set meta_X = list() for name, model in models: # fit in training set model.fit(X_train, y_train) # predict on hold out set yhat = model.predict_proba(X_val) # store predictions as input for blending meta_X.append(yhat) # create 2d array from predictions, each set is an input feature meta_X = hstack(meta_X) # define blending model blender = LogisticRegression() # fit on predictions from base models blender.fit(meta_X, y_val) return blender  # make a prediction with the blending ensemble def predict_ensemble(models, blender, X_test): # make predictions with base models meta_X = list() for name, model in models: # predict with base model yhat = model.predict_proba(X_test) # store prediction meta_X.append(yhat) # create 2d array from predictions, each set is an input feature meta_X = hstack(meta_X) # predict return blender.predict(meta_X)  # define dataset X, y = get_dataset() # split dataset into train and test sets X_train_full, X_test, y_train_full, y_test = train_test_split(X, y, test_size=0.5, random_state=1) # split training set into train and validation sets X_train, X_val, y_train, y_val = train_test_split(X_train_full, y_train_full, test_size=0.33, random_state=1) # summarize data split print('Train: %s, Val: %s, Test: %s' % (X_train.shape, X_val.shape, X_test.shape)) # create the base models models = get_models() # train the blending ensemble blender = fit_ensemble(models, X_train, X_val, y_train, y_val) # make predictions on test set yhat = predict_ensemble(models, blender, X_test) # evaluate predictions score = accuracy_score(y_test, yhat) print('Blending Accuracy: %.3f' % (score*100))

Запуск примера сначала сообщает резюме всех наборов данных, а затем точность ансамбля в тестовом наборе.

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

Здесь видим, что смешение вероятностей классов привело к повышению точности классификации примерно до 98,240 %.

Train: (3350, 20), Val: (1650, 20), Test: (5000, 20) Blending Accuracy: 98.240

Смешанный ансамбль эффективен только в том случае, если он способен превзойти любую из отдельных моделей в нём. Мы можем подтвердить это, оценив каждую из базовых моделей в отдельности. Каждая базовая модель может быть обучена на всём обучающем наборе данных (в отличие от ансамбля смешивания) и оценена на тестовом наборе данных (так же, как в ансамбле смешивания). Пример ниже демонстрирует это, оценивая каждую базовую модель в отдельности.

# evaluate base models on the entire training dataset from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score from sklearn.linear_model import LogisticRegression from sklearn.neighbors import KNeighborsClassifier from sklearn.tree import DecisionTreeClassifier from sklearn.svm import SVC from sklearn.naive_bayes import GaussianNB  # get the dataset def get_dataset(): X, y = make_classification(n_samples=10000, n_features=20, n_informative=15, n_redundant=5, random_state=7) return X, y  # get a list of base models def get_models(): models = list() models.append(('lr', LogisticRegression())) models.append(('knn', KNeighborsClassifier())) models.append(('cart', DecisionTreeClassifier())) models.append(('svm', SVC(probability=True))) models.append(('bayes', GaussianNB())) return models  # define dataset X, y = get_dataset() # split dataset into train and test sets X_train_full, X_test, y_train_full, y_test = train_test_split(X, y, test_size=0.5, random_state=1) # summarize data split print('Train: %s, Test: %s' % (X_train_full.shape, X_test.shape)) # create the base models models = get_models() # evaluate standalone model for name, model in models: # fit the model on the training dataset model.fit(X_train_full, y_train_full) # make a prediction on the test dataset yhat = model.predict(X_test) # evaluate the predictions score = accuracy_score(y_test, yhat) # report the score print('>%s Accuracy: %.3f' % (name, score*100))

Запуск примера сначала сообщает резюме всех трёх наборов данных, а затем точность каждой базовой модели в тестовом наборе.

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

В этом случае мы видим, что все модели работают хуже смешанного ансамбля. Интересно вот что: мы видим, что SVM очень близок к достижению точности 98,200 % по сравнению с точностью 98,240 %, достигнутой с помощью смешанного ансамбля.

Train: (5000, 20), Test: (5000, 20) >lr Accuracy: 87.800 >knn Accuracy: 97.380 >cart Accuracy: 88.200 >svm Accuracy: 98.200 >bayes Accuracy: 87.300

Мы можем выбрать смешанный ансамбль в качестве нашей окончательной модели. Это включает обучение ансамбля на всём тренировочном наборе данных и составление прогнозов на новых примерах. В частности, весь обучающий набор разбивается на обучающие и валидационные наборы для обучения базовой и метамодели соответственно, а затем ансамбль может использоваться в прогнозировании. Полный пример составления прогноза по новым данным с использованием смешанного ансамбля для классификации выглядит так:

# example of making a prediction with a blending ensemble for classification from numpy import hstack from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.neighbors import KNeighborsClassifier from sklearn.tree import DecisionTreeClassifier from sklearn.svm import SVC from sklearn.naive_bayes import GaussianNB  # get the dataset def get_dataset(): X, y = make_classification(n_samples=10000, n_features=20, n_informative=15, n_redundant=5, random_state=7) return X, y  # get a list of base models def get_models(): models = list() models.append(('lr', LogisticRegression())) models.append(('knn', KNeighborsClassifier())) models.append(('cart', DecisionTreeClassifier())) models.append(('svm', SVC(probability=True))) models.append(('bayes', GaussianNB())) return models  # fit the blending ensemble def fit_ensemble(models, X_train, X_val, y_train, y_val): # fit all models on the training set and predict on hold out set meta_X = list() for _, model in models: # fit in training set model.fit(X_train, y_train) # predict on hold out set yhat = model.predict_proba(X_val) # store predictions as input for blending meta_X.append(yhat) # create 2d array from predictions, each set is an input feature meta_X = hstack(meta_X) # define blending model blender = LogisticRegression() # fit on predictions from base models blender.fit(meta_X, y_val) return blender  # make a prediction with the blending ensemble def predict_ensemble(models, blender, X_test): # make predictions with base models meta_X = list() for _, model in models: # predict with base model yhat = model.predict_proba(X_test) # store prediction meta_X.append(yhat) # create 2d array from predictions, each set is an input feature meta_X = hstack(meta_X) # predict return blender.predict(meta_X)  # define dataset X, y = get_dataset() # split dataset set into train and validation sets X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.33, random_state=1) # summarize data split print('Train: %s, Val: %s' % (X_train.shape, X_val.shape)) # create the base models models = get_models() # train the blending ensemble blender = fit_ensemble(models, X_train, X_val, y_train, y_val) # make a prediction on a new row of data row = [-0.30335011, 2.68066314, 2.07794281, 1.15253537, -2.0583897, -2.51936601, 0.67513028, -3.20651939, -1.60345385, 3.68820714, 0.05370913, 1.35804433, 0.42011397, 1.4732839, 2.89997622, 1.61119399, 7.72630965, -2.84089477, -1.83977415, 1.34381989] yhat = predict_ensemble(models, blender, [row]) # summarize prediction print('Predicted Class: %d' % (yhat))

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

Train: (6700, 20), Val: (3300, 20) Predicted Class: 1

Давайте рассмотрим, как мы могли бы оценить смешанный ансамбль для регрессии.

Смешанный ансамбль для задачи регрессии


В этом разделе мы рассмотрим использование пакетирования для регрессионной задачи. Во-первых, мы можем использовать функцию make_regression(), чтобы создать синтетическую регрессионную задачу с 10 000 сэмплов и 20 входными признаками. Весь пример приведен ниже.

# test regression dataset from sklearn.datasets import make_regression # define dataset X, y = make_regression(n_samples=10000, n_features=20, n_informative=10, noise=0.3, random_state=7) # summarize the dataset print(X.shape, y.shape)

Запуск примера создаёт набор данных и резюмирует входные и выходные компоненты.

(10000, 20) (10000,)

Далее можно определить список регрессионных моделей для применения в качестве базовых. В этом случае используем линейную регрессию, kNN, дерево решений и модели SVM.

# get a list of base models def get_models(): models = list() models.append(('lr', LinearRegression())) models.append(('knn', KNeighborsRegressor())) models.append(('cart', DecisionTreeRegressor())) models.append(('svm', SVR())) return models

Функция fit_ensemble(), используемая для обучения ансамбля, не изменяется, за исключением того, что модель, используемая для смешивания, должна быть изменена на регрессионную. Здесь используем модель линейной регрессии.

... # define blending model blender = LinearRegression()

Учитывая, что это задача регрессии, мы будем оценивать производительность модели с помощью метрики ошибок, в данном случае средней абсолютной ошибки, или (сокращённо) MAE.

... # evaluate predictions score = mean_absolute_error(y_test, yhat) print('Blending MAE: %.3f' % score)

Весь пример смешанного ансамбля для задачи прогнозного моделирования синтетической регрессии приведён ниже:

# evaluate blending ensemble for regression from numpy import hstack from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split from sklearn.metrics import mean_absolute_error from sklearn.linear_model import LinearRegression from sklearn.neighbors import KNeighborsRegressor from sklearn.tree import DecisionTreeRegressor from sklearn.svm import SVR  # get the dataset def get_dataset(): X, y = make_regression(n_samples=10000, n_features=20, n_informative=10, noise=0.3, random_state=7) return X, y  # get a list of base models def get_models(): models = list() models.append(('lr', LinearRegression())) models.append(('knn', KNeighborsRegressor())) models.append(('cart', DecisionTreeRegressor())) models.append(('svm', SVR())) return models  # fit the blending ensemble def fit_ensemble(models, X_train, X_val, y_train, y_val): # fit all models on the training set and predict on hold out set meta_X = list() for name, model in models: # fit in training set model.fit(X_train, y_train) # predict on hold out set yhat = model.predict(X_val) # reshape predictions into a matrix with one column yhat = yhat.reshape(len(yhat), 1) # store predictions as input for blending meta_X.append(yhat) # create 2d array from predictions, each set is an input feature meta_X = hstack(meta_X) # define blending model blender = LinearRegression() # fit on predictions from base models blender.fit(meta_X, y_val) return blender  # make a prediction with the blending ensemble def predict_ensemble(models, blender, X_test): # make predictions with base models meta_X = list() for name, model in models: # predict with base model yhat = model.predict(X_test) # reshape predictions into a matrix with one column yhat = yhat.reshape(len(yhat), 1) # store prediction meta_X.append(yhat) # create 2d array from predictions, each set is an input feature meta_X = hstack(meta_X) # predict return blender.predict(meta_X)  # define dataset X, y = get_dataset() # split dataset into train and test sets X_train_full, X_test, y_train_full, y_test = train_test_split(X, y, test_size=0.5, random_state=1) # split training set into train and validation sets X_train, X_val, y_train, y_val = train_test_split(X_train_full, y_train_full, test_size=0.33, random_state=1) # summarize data split print('Train: %s, Val: %s, Test: %s' % (X_train.shape, X_val.shape, X_test.shape)) # create the base models models = get_models() # train the blending ensemble blender = fit_ensemble(models, X_train, X_val, y_train, y_val) # make predictions on test set yhat = predict_ensemble(models, blender, X_test) # evaluate predictions score = mean_absolute_error(y_test, yhat) print('Blending MAE: %.3f' % score)

Пример сначала выводит резюме трёх наборов данных, а затем MAE на тестовом наборе.

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

Здесь видим, что ансамбль достиг MAE около 0,237 на тестовом наборе данных.

Train: (3350, 20), Val: (1650, 20), Test: (5000, 20) Blending MAE: 0.237

Как и в случае с классификацией, смешанный ансамбль полезен только в том случае, если он работает лучше, чем любая из базовых моделей ансамбля.

Мы можем проверить это, оценив каждую базовую модель изолированно, сначала обучив ее на обучающем наборе целиком (в отличие от ансамбля) и сделав прогнозы на тестовом наборе данных (как в ансамбле). В приведённом ниже примере каждая из базовых моделей оценивается изолированно на основе набора данных синтетического регрессионного прогностического моделирования.

# evaluate base models in isolation on the regression dataset from numpy import hstack from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split from sklearn.metrics import mean_absolute_error from sklearn.linear_model import LinearRegression from sklearn.neighbors import KNeighborsRegressor from sklearn.tree import DecisionTreeRegressor from sklearn.svm import SVR  # get the dataset def get_dataset(): X, y = make_regression(n_samples=10000, n_features=20, n_informative=10, noise=0.3, random_state=7) return X, y  # get a list of base models def get_models(): models = list() models.append(('lr', LinearRegression())) models.append(('knn', KNeighborsRegressor())) models.append(('cart', DecisionTreeRegressor())) models.append(('svm', SVR())) return models  # define dataset X, y = get_dataset() # split dataset into train and test sets X_train_full, X_test, y_train_full, y_test = train_test_split(X, y, test_size=0.5, random_state=1) # summarize data split print('Train: %s, Test: %s' % (X_train_full.shape, X_test.shape)) # create the base models models = get_models() # evaluate standalone model for name, model in models: # fit the model on the training dataset model.fit(X_train_full, y_train_full) # make a prediction on the test dataset yhat = model.predict(X_test) # evaluate the predictions score = mean_absolute_error(y_test, yhat) # report the score print('>%s MAE: %.3f' % (name, score))

Запуск примера сначала резюмирует тренировочный и тестовый наборы, а затем MAE каждой базовой модели в тестовом наборе данных.

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

Здесь видно, что на самом деле линейная регрессионная модель показала себя немного лучше, чем смешанный ансамбль, достигнув MAE 0,236 по сравнению с 0,237. Это может быть связано с тем, как был построен синтетический набор данных.

Тем не менее в этом случае мы предпочли бы использовать линейную регрессионную модель именно для этой задачи. Ситуация подчёркивает важность проверки производительности вносящих вклад моделей, прежде чем принимать ансамблевую модель как окончательную.

Train: (5000, 20), Test: (5000, 20) >lr MAE: 0.236 >knn MAE: 100.169 >cart MAE: 133.744 >svm MAE: 138.195

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

# example of making a prediction with a blending ensemble for regression from numpy import hstack from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.neighbors import KNeighborsRegressor from sklearn.tree import DecisionTreeRegressor from sklearn.svm import SVR  # get the dataset def get_dataset(): X, y = make_regression(n_samples=10000, n_features=20, n_informative=10, noise=0.3, random_state=7) return X, y  # get a list of base models def get_models(): models = list() models.append(('lr', LinearRegression())) models.append(('knn', KNeighborsRegressor())) models.append(('cart', DecisionTreeRegressor())) models.append(('svm', SVR())) return models  # fit the blending ensemble def fit_ensemble(models, X_train, X_val, y_train, y_val): # fit all models on the training set and predict on hold out set meta_X = list() for _, model in models: # fit in training set model.fit(X_train, y_train) # predict on hold out set yhat = model.predict(X_val) # reshape predictions into a matrix with one column yhat = yhat.reshape(len(yhat), 1) # store predictions as input for blending meta_X.append(yhat) # create 2d array from predictions, each set is an input feature meta_X = hstack(meta_X) # define blending model blender = LinearRegression() # fit on predictions from base models blender.fit(meta_X, y_val) return blender  # make a prediction with the blending ensemble def predict_ensemble(models, blender, X_test): # make predictions with base models meta_X = list() for _, model in models: # predict with base model yhat = model.predict(X_test) # reshape predictions into a matrix with one column yhat = yhat.reshape(len(yhat), 1) # store prediction meta_X.append(yhat) # create 2d array from predictions, each set is an input feature meta_X = hstack(meta_X) # predict return blender.predict(meta_X)  # define dataset X, y = get_dataset() # split dataset set into train and validation sets X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.33, random_state=1) # summarize data split print('Train: %s, Val: %s' % (X_train.shape, X_val.shape)) # create the base models models = get_models() # train the blending ensemble blender = fit_ensemble(models, X_train, X_val, y_train, y_val) # make a prediction on a new row of data row = [-0.24038754, 0.55423865, -0.48979221, 1.56074459, -1.16007611, 1.10049103, 1.18385406, -1.57344162, 0.97862519, -0.03166643, 1.77099821, 1.98645499, 0.86780193, 2.01534177, 2.51509494, -1.04609004, -0.19428148, -0.05967386, -2.67168985, 1.07182911] yhat = predict_ensemble(models, blender, [row]) # summarize prediction print('Predicted: %.3f' % (yhat[0]))

Запуск примера обучает модели ансамбля на наборе данных и затем используется для прогнозирования новой строки данных, как это было бы при использовании модели в приложении.

Train: (6700, 20), Val: (3300, 20) Predicted: 359.986

Раздел содержит ресурсы по этой теме, если вы хотите в неё углубиться.

И не забывайте про промокод HABR, добавляющий 10% к скидке на баннере.

image

Рекомендуемые статьи

FavoriteLoadingДобавить в избранное
Posted in Без рубрики

Добавить комментарий