Problem polega na tym, że danych mojego pociągu nie można umieścić w pamięci RAM ze względu na rozmiar danych pociągu. Potrzebuję więc metody, która najpierw zbuduje jedno drzewo na całym zestawie danych pociągu, obliczy resztę, zbuduje kolejne drzewo itd. (Jak zrobione z gradientem drzewo). Oczywiście, jeśli zadzwonię pod model = xgb.train(param, batch_dtrain, 2)
w jakiejś pętli - to nie pomoże, ponieważ w takim przypadku po prostu przebudowuje cały model dla każdej partii.Jak mogę wdrożyć szkolenie przyrostowe dla xgboost?
Odpowiedz
Nota prawna: Jestem nowy w Xgboost, ale myślę, że to wymyśliłem.
Spróbuj zapisać swój model po treningu na pierwszej partii. Następnie, w kolejnych seriach, podaj metodę xgb.train z ścieżką do pliku zapisanego modelu.
Oto mały eksperyment, który wpadłem, aby przekonać się, że to działa:
pierwsze, podzielić zbiór danych boston do szkoleń i zestawów testowych. Następnie podziel zestaw treningowy na połówki. Dopasuj model z pierwszą połową i uzyskaj wynik, który posłuży jako punkt odniesienia. Następnie dopasuj dwa modele z drugą połową; jeden model będzie miał dodatkowy parametr xgb_model. Jeśli podanie dodatkowego parametru nie miało znaczenia, to spodziewalibyśmy się, że ich wyniki będą podobne. Ale na szczęście nowy model wydaje się działać znacznie lepiej niż pierwszy.
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
Daj mi znać, jeśli coś jest niejasne!
referencyjny: https://github.com/dmlc/xgboost/blob/master/python-package/xgboost/training.py
Chciałbym zrozumieć, że model_2_v2 działa gorzej niż model, który używał obu zestawów danych naraz. Ale model_2_v2 jest gorszy niż model_1, co jest dość dziwne, ponieważ dajemy nowy zestaw danych, którego model_1 nie widział, ale na końcu model_2_v2 działał gorzej ... Wydaje się, że wzmocnione drzewa nie są najlepszym sposobem na stopniowe uczenie się. @pikachau próbowałeś użyć mode_1 zamiast "experiment.model"? –
Może to być spowodowane tym, że zbiór danych jest dość mały (wielkość próbki = 150). W przypadku większego zbioru danych uważam, że model_2_v2 powinien wyprzedzać model_1. Och, eksperymentuj.model == model_1; Powinienem to sprecyzować! – Alain
Obecnie (wersja 0.6?) Parametr process_update że może pomóc. Oto eksperyment z nim:
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"
wyjściowa:
full train 17.8364309709
model 1 24.8
model 2 25.6967017352
model 1+2 22.8846455135
model 1+update2 14.2816257268
Który z nich jest ostatnim modelem lub z którego powinienem skorzystać? – tumbleweed
Chcesz model o najniższym MSE. Ale zauważ, że aktualizacja 1 + 2 jest niższa niż pełny pociąg! Nie jest dla mnie jasne, dlaczego tak powinno być, więc podejrzewałbym o ten wynik i prowadziłbym CV z większą liczbą fałd. – paulperry
stworzyłem a gist of jupyter notebook wykazać, że wzór xgboost może być przeszkoleni stopniowo. Użyłem zestawu danych Bostona do szkolenia modelu. Zrobiłem 3 eksperymenty - nauka jednego strzału, powtarzające się jednorazowe uczenie się, powtarzające się uczenie inkrementalne. Podczas szkolenia przyrostowego przekazałem dane bostonu do modelu w partiach o rozmiarze 50.
Istotą jest to, że trzeba wielokrotnie powtarzać dane, aby model zszedł do dokładności uzyskanej przez jedno ujęcie (wszystkie dane).
Oto odpowiedni kod do robienia iteratywnej nauki przyrostowej z xgboost. Wersja
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
Przykłady z 'xgboost' repo: https://github.com/dmlc/xgboost/blob/master/tests/python/test_training_continuation.py –