Проблема в том, что данные моего поезда не могут быть помещены в ОЗУ из-за размера данных поезда. Так что мне нужен метод, который сначала строит одно дерево на весь набор данных поезда, вычисляет остатки, строит другое дерево и т. Д. (Например, градиентное усиление дерева). Очевидно, если я позвоню model = xgb.train(param, batch_dtrain, 2)
в какой-то цикл - это не поможет, потому что в этом случае он просто перестраивает всю модель для каждой партии.Как я могу реализовать инкрементное обучение для xgboost?
ответ
Отказ от ответственности: Я новичок в xgboost, но, думаю, я понял это.
Попробуйте сохранить свою модель после тренировки в первой партии. Затем, при последовательных запусках, предоставляйте метод xgb.train путь к файлу сохраненной модели.
Вот небольшой эксперимент, который я пытался убедить себя, что это работает:
Во-первых, разделить набор данных бостон в обучение и тестирование наборов. Затем разделите тренировочный комплект на половины. Установите модель с первой половиной и получите оценку, которая будет служить эталоном. Затем установите две модели со второй половиной; одна модель будет иметь дополнительный параметр xgb_model. Если бы прохождение дополнительного параметра не имело никакого значения, тогда мы ожидали бы, что их оценки будут похожими. Но, к счастью, новая модель работает намного лучше, чем первая.
import xgboost as xgb
from sklearn.cross_validation import train_test_split as ttsplit
from sklearn.datasets import load_boston
from sklearn.metrics import mean_squared_error as mse
X = load_boston()['data']
y = load_boston()['target']
# split data into training and testing sets
# then split training set in half
X_train, X_test, y_train, y_test = ttsplit(X, y, test_size=0.1, random_state=0)
X_train_1, X_train_2, y_train_1, y_train_2 = ttsplit(X_train,
y_train,
test_size=0.5,
random_state=0)
xg_train_1 = xgb.DMatrix(X_train_1, label=y_train_1)
xg_train_2 = xgb.DMatrix(X_train_2, label=y_train_2)
xg_test = xgb.DMatrix(X_test, label=y_test)
params = {'objective': 'reg:linear', 'verbose': False}
model_1 = xgb.train(params, xg_train_1, 30)
model_1.save_model('model_1.model')
# ================= train two versions of the model =====================#
model_2_v1 = xgb.train(params, xg_train_2, 30)
model_2_v2 = xgb.train(params, xg_train_2, 30, xgb_model='model_1.model')
print(mse(model_1.predict(xg_test), y_test)) # benchmark
print(mse(model_2_v1.predict(xg_test), y_test)) # "before"
print(mse(model_2_v2.predict(xg_test), y_test)) # "after"
# 23.0475232194
# 39.6776876084
# 27.2053239482
Сообщите мне, если что-то непонятное!
ссылка: https://github.com/dmlc/xgboost/blob/master/python-package/xgboost/training.py
Я бы понял, что model_2_v2 выполняет хуже, чем модель, которая использовала оба набора дат одновременно. Но model_2_v2 хуже, чем model_1, что довольно странно, потому что мы даем новый набор данных, который model_1 не видел, но в конце model_2_v2 он делал хуже ... Кажется, что усиленные деревья - это не лучший способ выполнить постепенное обучение. @pikachau Вы пытались использовать model_1 вместо 'experiment.model'? –
Возможно, это связано с тем, что набор данных довольно маленький (размер выборки = 150). С большим набором данных, я думаю, model_2_v2 должен превзойти модель_1. О, эксперимент.model == model_1; Я должен был сделать это более явным! – Alain
Существует в настоящее время (версия 0.6?) Параметр process_update, который может помочь. Вот эксперимент с ним:
import pandas as pd
import xgboost as xgb
from sklearn.model_selection import ShuffleSplit
from sklearn.datasets import load_boston
from sklearn.metrics import mean_squared_error as mse
boston = load_boston()
features = boston.feature_names
X = boston.data
y = boston.target
X=pd.DataFrame(X,columns=features)
y = pd.Series(y,index=X.index)
# split data into training and testing sets
rs = ShuffleSplit(test_size=0.3, n_splits=1, random_state=0)
for train_idx,test_idx in rs.split(X): # this looks silly
pass
train_split = round(len(train_idx)/2)
train1_idx = train_idx[:train_split]
train2_idx = train_idx[train_split:]
X_train = X.loc[train_idx]
X_train_1 = X.loc[train1_idx]
X_train_2 = X.loc[train2_idx]
X_test = X.loc[test_idx]
y_train = y.loc[train_idx]
y_train_1 = y.loc[train1_idx]
y_train_2 = y.loc[train2_idx]
y_test = y.loc[test_idx]
xg_train_0 = xgb.DMatrix(X_train, label=y_train)
xg_train_1 = xgb.DMatrix(X_train_1, label=y_train_1)
xg_train_2 = xgb.DMatrix(X_train_2, label=y_train_2)
xg_test = xgb.DMatrix(X_test, label=y_test)
params = {'objective': 'reg:linear', 'verbose': False}
model_0 = xgb.train(params, xg_train_0, 30)
model_1 = xgb.train(params, xg_train_1, 30)
model_1.save_model('model_1.model')
model_2_v1 = xgb.train(params, xg_train_2, 30)
model_2_v2 = xgb.train(params, xg_train_2, 30, xgb_model=model_1)
params.update({'process_type': 'update',
'updater' : 'refresh',
'refresh_leaf': True})
model_2_v2_update = xgb.train(params, xg_train_2, 30, xgb_model=model_1)
print('full train\t',mse(model_0.predict(xg_test), y_test)) # benchmark
print('model 1 \t',mse(model_1.predict(xg_test), y_test))
print('model 2 \t',mse(model_2_v1.predict(xg_test), y_test)) # "before"
print('model 1+2\t',mse(model_2_v2.predict(xg_test), y_test)) # "after"
print('model 1+update2\t',mse(model_2_v2_update.predict(xg_test), y_test)) # "after"
Выход:
full train 17.8364309709
model 1 24.8
model 2 25.6967017352
model 1+2 22.8846455135
model 1+update2 14.2816257268
Какой из них является последней моделью или той, которую я должен использовать? – tumbleweed
Вам нужна модель с самым низким MSE. Но обратите внимание, как 1 + update2 ниже, чем полный поезд! Мне непонятно, почему так должно быть, поэтому я был бы подозрителен к этому результату и запустил CV с большим количеством складок. – paulperry
a gist of jupyter notebook Я создал, чтобы продемонстрировать, что модель xgboost могут быть обучены постепенно. Я использовал boston dataset для обучения модели. Я сделал 3 эксперимента - однократное обучение, итеративное однократное обучение, итеративное инкрементное обучение. При инкрементальном обучении я передавал данные бостона в модель партиями размером 50.
Суть всего в том, что вам придется перебирать данные несколько раз, чтобы модель сходилась к точности, достигаемой один выстрел (все данные) обучения.
Вот соответствующий код для итеративного инкрементного обучения с помощью xgboost. версия
batch_size = 50
iterations = 25
model = None
for i in range(iterations):
for start in range(0, len(x_tr), batch_size):
model = xgb.train({
'learning_rate': 0.007,
'update':'refresh',
'process_type': 'update',
'refresh_leaf': True,
#'reg_lambda': 3, # L2
'reg_alpha': 3, # L1
'silent': False,
}, dtrain=xgb.DMatrix(x_tr[start:start+batch_size], y_tr[start:start+batch_size]), xgb_model=model)
y_pr = model.predict(xgb.DMatrix(x_te))
#print(' MSE [email protected]{}: {}'.format(int(start/batch_size), sklearn.metrics.mean_squared_error(y_te, y_pr)))
print('MSE [email protected]{}: {}'.format(i, sklearn.metrics.mean_squared_error(y_te, y_pr)))
y_pr = model.predict(xgb.DMatrix(x_te))
print('MSE at the end: {}'.format(sklearn.metrics.mean_squared_error(y_te, y_pr)))
XGBoost: 0,6
Примеры из 'xgboost' репо: https://github.com/dmlc/xgboost/blob/master/tests/python/test_training_continuation.py –