2016-06-28 18 views
13

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?

+0

Przykłady z 'xgboost' repo: https://github.com/dmlc/xgboost/blob/master/tests/python/test_training_continuation.py –

Odpowiedz

16

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

+1

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"? –

+0

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

4

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 
+0

Który z nich jest ostatnim modelem lub z którego powinienem skorzystać? – tumbleweed

+2

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

2

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