Традиционное ансамблевое обучение

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

Штабелирование

Стекирование, называемое мета-ансамблем, - это метод объединения моделей, используемый для объединения информации из нескольких прогнозных моделей для создания новой. Часто составная модель также называется моделями 2-го уровня, чтобы превзойти каждую из отдельных моделей из-за ее природы выделения каждому базовому учащемуся, где он работает лучше, а где хуже. Итак, модель стекирования используется там, где базовые учащиеся разные.

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

Проблема с использованием моделей штабелирования:

Стратегия, которой мы следовали:

• Построить модель для прогнозирования количества покупок клиентов по различным продуктам, которая поможет им создать персонализированное предложение для клиентов по разным продуктам.

• Объем данных огромен, примерно полмиллиона строк. Сложенная модель содержала комбинацию из 4 моделей XGBoost, 3 моделей ExtraTreeRegressor и 3 моделей RandomForestRegressor.

  • Все эти подмодели были объединены с помощью NumPy concatenate () и vstack (), чтобы сформировать окончательный обучающий набор данных, в котором была обучена новая модель XGBoost. Подобный трюк моделирования стекирования был применен к тестовым данным, где эта новая модель XGBoost использовалась для прогнозирования.
import numpy as np
import pandas as pd
import xgboost as xgb
from sklearn import linear_model
from sklearn import preprocessing
from sklearn.metrics import mean_squared_error
train=pd.read_csv('train.csv')
test=pd.read_csv('test.csv')
train.head()

Объединение тестовых и обучающих данных:

frames = [train, test]
input = pd.concat(frames)
print (input.shape)
print (test.shape)
(783667, 12)
(233599, 11)

Заполните все пропущенные значения большим числом 999.

input.fillna(999, inplace=True)

Установить целевой столбец

target = input.Purchase
target = np.array(target)
target = np.array(target)

Преобразуйте все столбцы в строку

input = input.applymap(str)
input.dtypes

# Have a copy of the pandas dataframe. Will be useful later on input_pd = input.copy()

Преобразование категориальных переменных в числовые с помощью LabelEncoder

input = np.array(input)

for i in range(input.shape[1]):
    lbl = preprocessing.LabelEncoder()
    lbl.fit(list(input[:,i]))
    input[:, i] = lbl.transform(input[:, i])
input = input.astype(int)
submission=pd.read_csv('Sample_Submission_Tm9Lura.csv')

Применение модели XGBoost:

i) Параметр «min_child_weight» используется для контроля переобучения. Более высокие значения не позволяют модели изучать отношения, которые могут быть очень специфичными для конкретной выборки, выбранной для дерева. Определяет минимальную сумму весов всех наблюдений, необходимых для поля.

ii) Параметр «подвыборка» обозначает долю наблюдений, которые должны выбираться случайным образом для каждого дерева. Меньшие значения делают алгоритм более консервативным и предотвращают переоснащение, но слишком маленькое может привести к недостаточному подбору. Типичные значения 0,5–1.

iii) Параметр «colsample_bytree» обозначает долю столбцов, из которых будет произведена случайная выборка для каждого дерева.

iv) Параметр «silent» равен 1, поэтому текущие сообщения не выводятся.

v) Параметр «nthread» используется для параллельной обработки и количества печатаемых ядер в системе.

vi) Параметр «объективный» здесь reg: linear.

vii) Параметр «эта» аналогичен скорости обучения и делает модель более устойчивой за счет уменьшения веса на каждом шаге.

viii) Здесь задан параметр eval_metric.

ix) Параметр «seed» можно использовать для получения воспроизводимых результатов, а также для настройки параметров.

x) Параметр «max_depth», используемый для контроля чрезмерной подгонки, поскольку более высокая глубина позволит модели изучать отношения, очень специфичные для конкретного образца.

params = {}
params["min_child_weight"] = 10
params["subsample"] = 0.7
params["colsample_bytree"] = 0.7
params["scale_pos_weight"] = 0.8
params["silent"] = 1
params["max_depth"] = 6
params["nthread"] = 6
#params["gamma"] = 1
params["objective"] = "reg:linear"
params["eta"] = 0.1
params["base_score"] = 1800
params["eval_metric"] = "rmse"
params["seed"] = 0
plst = list(params.items())
num_rounds = 3000
xgtrain = xgb.DMatrix(input[:train.shape[0],:], label=target[:train.shape[0]]) watchlist = [(xgtrain, 'train')] model_1_xgboost = xgb.train(plst, xgtrain, num_rounds)
model_1_predict = model_1_xgboost.predict(xgb.DMatrix(input[train.shape[0]:,:]))
model_1_predict[model_1_predict<0] = 25
submission.Purchase = model_1_predict
submission.User_ID=test.User_ID
submission.Product_ID=test.Product_ID
submission.to_csv("sub1.csv", index=False)

Печать файла представленных материалов:

submission.head()

Укладка начинается

Подготовка данных для наложения модели:
Разделение набора данных на две равные части: train_fs и train_ss
Модели первого уровня для создания мета-функций для передачи в модель второго уровня.

first_stage_rows = np.random.randint(train.shape[0], size = np.int(train.shape[0]/2))
train_np   = input[:train.shape[0], :]
target_np  = target[:train.shape[0]]
train_fs   = train_np[first_stage_rows, :]
target_fs  = target_np[first_stage_rows]
train_ss   = train_np[-first_stage_rows, :]
target_ss  = target_np[-first_stage_rows]
print (train_fs.shape, target_fs.shape, train_ss.shape, target_ss.shape)

(275034, 11) (275034,) (275034, 11) (275034,)

Построение различных моделей и их обучение на наборе данных первой половины (train_fs)

xgtrain = xgb.DMatrix(train_fs, label=target_fs)
watchlist = [(xgtrain, 'train')]
# Model 1: 6/3000
params = {}
params["min_child_weight"] = 10
params["subsample"] = 0.7
params["colsample_bytree"] = 0.7
params["scale_pos_weight"] = 0.8
params["silent"] = 1
params["max_depth"] = 6
params["nthread"] = 6
#params["gamma"] = 1
params["objective"] = "reg:linear"
params["eta"] = 0.1
params["base_score"] = 1800
params["eval_metric"] = "rmse"
params["seed"] = 0
plst = list(params.items())
num_rounds = 3000
model_1 = xgb.train(plst, xgtrain, num_rounds)
# Model 2: 8/1420
params = {}
params["min_child_weight"] = 10
params["subsample"] = 0.7
params["colsample_bytree"] = 0.7
params["scale_pos_weight"] = 0.8
params["silent"] = 1
params["max_depth"] = 8
params["nthread"] = 6
#params["gamma"] = 1
params["objective"] = "reg:linear"
params["eta"] = 0.1
params["base_score"] = 1800
params["eval_metric"] = "rmse"
params["seed"] = 0
plst = list(params.items())
num_rounds = 1420
model_2 = xgb.train(plst, xgtrain, num_rounds)
# Model 3: 10/1200
params = {}
params["min_child_weight"] = 10
params["subsample"] = 0.7
params["colsample_bytree"] = 0.7
params["scale_pos_weight"] = 0.8
params["silent"] = 1
params["max_depth"] = 10
params["nthread"] = 6
#params["gamma"] = 1
params["objective"] = "reg:linear"
params["eta"] = 0.1
params["base_score"] = 1800
params["eval_metric"] = "rmse"
params["seed"] = 0
plst = list(params.items())
num_rounds = 1200
model_3 = xgb.train(plst, xgtrain, num_rounds)
# Model 4: 12/800
params = {}
params["min_child_weight"] = 10
params["subsample"] = 0.7
params["colsample_bytree"] = 0.7
params["scale_pos_weight"] = 0.8
params["silent"] = 1
params["max_depth"] = 12
params["nthread"] = 6
#params["gamma"] = 1
params["objective"] = "reg:linear"
params["eta"] = 0.1
params["base_score"] = 1800
params["eval_metric"] = "rmse"
params["seed"] = 0
plst = list(params.items())
num_rounds = 800
model_4 = xgb.train(plst, xgtrain, num_rounds)

Вот еще 3 модели, обученные на наборе данных первой половины (train_fs)

# This set of models will be ExtraTrees
# Model 5: 8/1450
model_5 = ExtraTreesRegressor(n_estimators=1450, max_depth=8, min_samples_split=10, min_samples_leaf=10, oob_score=True, n_jobs=6, random_state=123, verbose=1, bootstrap=True)
model_5.fit(train_fs, target_fs)
# Model 6: 6/3000
model_6 = ExtraTreesRegressor(n_estimators=3000, max_depth=6, min_samples_split=10, min_samples_leaf=10, oob_score=True, n_jobs=6, random_state=123, verbose=1, bootstrap=True)
model_6.fit(train_fs, target_fs)
# Model 7: 12/800
model_7 = ExtraTreesRegressor(n_estimators=800, max_depth=12, min_samples_split=10, min_samples_leaf=10, oob_score=True, n_jobs=6, random_state=123, bootstrap=True)
model_7.fit(train_fs, target_fs)

Еще 3 модели, в результате чего 10 базовых учеников обучены / соответствуют набору данных первой половины (train_fs)

# This set of models will be RandomForest
# Model 8: 6/3000
model_8 = RandomForestRegressor(n_estimators=3000, max_depth=6, oob_score=True, n_jobs=6, random_state=123, min_samples_split=10, min_samples_leaf=10)
model_8.fit(train_fs, target_fs)
# Model 9: 8/1500
model_9 = RandomForestRegressor(n_estimators=1500, max_depth=8, oob_score=True, n_jobs=6, random_state=123, min_samples_split=10, min_samples_leaf=10)
model_9.fit(train_fs, target_fs)
# Model 10: 12/800
model_10 = RandomForestRegressor(n_estimators=800, max_depth=12, oob_score=True, n_jobs=6, random_state=123, min_samples_split=10, min_samples_leaf=10)
model_10.fit(train_fs, target_fs)

Наконец, прогнозирование этих 10 независимых учеников первого уровня в следующем и последнем наборе данных train_ss один за другим.

model_1_predict = model_1.predict(xgb.DMatrix(train_ss))
model_2_predict = model_2.predict(xgb.DMatrix(train_ss))
model_3_predict = model_3.predict(xgb.DMatrix(train_ss))
model_4_predict = model_4.predict(xgb.DMatrix(train_ss))
model_5_predict = model_5.predict(train_ss)
model_6_predict = model_6.predict(train_ss)
model_7_predict = model_7.predict(train_ss)
model_8_predict = model_8.predict(train_ss)
model_9_predict = model_9.predict(train_ss)
model_10_predict = model_10.predict(train_ss)

Выходные данные этих классификаторов 1-го уровня объединяются для формирования окончательных данных обучения как train_ss_u_meta

train_ss_w_meta = np.concatenate((train_ss, np.vstack((model_1_predict, model_2_predict, model_3_predict, model_4_predict, model_5_predict, model_6_predict, model_7_predict, model_8_predict, model_9_predict, model_10_predict)).T), axis=1)

Обучение нового классификатора, который является классификатором 2-го уровня, на недавно созданных обучающих данных «train_ss_w_meta»

params = {}
params["min_child_weight"] = 10
params["subsample"] = 0.7
params["colsample_bytree"] = 0.7
params["scale_pos_weight"] = 0.8
params["silent"] = 1
params["max_depth"] = 8
params["nthread"] = 6
#params["gamma"] = 1
params["objective"] = "reg:linear"
params["eta"] = 0.1
params["base_score"] = 1800
params["eval_metric"] = "rmse"
params["seed"] = 0
plst = list(params.items())
num_rounds = 1400
xgtrain = xgb.DMatrix(train_ss_w_meta, label=target_ss)
watchlist = [(xgtrain, 'train')]
model_ss_xgboost = xgb.train(plst, xgtrain, num_rounds)

Аналогичным образом применяем 10 моделей к тестовым данным.

model_1_predict = model_1.predict(xgb.DMatrix(input[train.shape[0]:, :]))
model_2_predict = model_2.predict(xgb.DMatrix(input[train.shape[0]:, :]))
model_3_predict = model_3.predict(xgb.DMatrix(input[train.shape[0]:, :]))
model_4_predict = model_4.predict(xgb.DMatrix(input[train.shape[0]:, :]))
model_5_predict = model_5.predict(input[train.shape[0]:, :])
model_6_predict = model_6.predict(input[train.shape[0]:, :])
model_7_predict = model_7.predict(input[train.shape[0]:, :])
model_8_predict = model_8.predict(input[train.shape[0]:, :])
model_9_predict = model_9.predict(input[train.shape[0]:, :])
model_10_predict = model_10.predict(input[train.shape[0]:, :])
test_ss_w_meta = np.concatenate((input[train.shape[0]:, :], np.vstack((model_1_predict, model_2_predict, model_3_predict, model_4_predict, model_5_predict, model_6_predict, model_7_predict, model_8_predict, model_9_predict, model_10_predict)).T), axis=1)

Поскольку до сих пор я строил модель стекирования на своих обучающих данных, и окончательный прогноз будет применен к тестовым данным, базовые учащиеся уровня 1 на основе данных половинного обучения (train_fs) теперь прогнозируются на тестовых данных, и мы получили новые тестовые данные ' test_ss_w_meta 'путем объединения выходных данных классификаторов уровня 1. Теперь модель 2-го уровня (здесь XGBoost), которая уже обучена на объединенных обучающих данных (train_ss_w_meta), теперь прогнозируется на этих объединенных тестовых данных (test_ss_w_meta)

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

model_ss_predict = model_ss_xgboost.predict(xgb.DMatrix(test_ss_w_meta))
submission.Purchase = model_ss_predict
submission.to_csv("sub2.csv", index=False)

Укладка в действии

В заключение давайте поговорим о том, как, когда, почему и где мы должны использовать стекинг в реальном мире.
Лично я видел множество людей, использующих стекинг-моделирование на соревнованиях Kaggle и других платформах.
На самом деле , суммирование дает небольшой выигрыш с большим количеством дополнительных сложностей. Стекинг действительно эффективен, когда у вас есть группа людей, создающих прогнозное моделирование для решения одной общей проблемы. Выбирается единый набор складок, и затем каждый член команды строит свою собственную модель на этой складке. Затем каждую модель можно объединить с помощью сценария укладки модели. Это здорово, потому что не дает членам команды наступать друг другу на пятки.

Не стесняйтесь комментировать свои сомнения, если таковые имеются. Удачного обучения! : D