Jak mogę wdrożyć szkolenie przyrostowe dla xgboost?

Problem polega na tym, że moje dane pociągu nie mogą być umieszczone 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 pozostałości zbudować inne drzewo i tak dalej (jak gradient boosted tree zrobić). Oczywiście jeśli wywołam model = xgb.train(param, batch_dtrain, 2) w jakiejś pętli - to nie pomoże, bo w takim przypadku po prostu przebudowuje cały model dla każdej partii.

Author: Alain, 2016-06-28

6 answers

Spróbuj zapisać swój model po treningu na pierwszej partii. Następnie, przy kolejnych uruchomieniach, podaj xgb.metoda pociągu z ścieżką pliku zapisanego modelu.

Oto mały eksperyment, który przeprowadziłem, aby przekonać siebie, że działa:

Najpierw podziel zestaw danych z Bostonu na zestawy treningowe i testowe. Następnie podziel zestaw treningowy na pół. Dopasuj model do pierwszej połowy i uzyskaj wynik, który posłuży jako punkt odniesienia. Następnie dopasować dwa modele z drugiej połowy; jeden model będzie miał dodatkowy parametr xgb_model . Jeśli podanie dodatkowego parametru nie robi różnicy, spodziewamy 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

Odniesienie: https://github.com/dmlc/xgboost/blob/master/python-package/xgboost/training.py

 42
Author: Alain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-02-07 08:54:19

Jest już (Wersja 0.6?) parametr process_update, który 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ście:

full train   17.8364309709
model 1      24.2542132108
model 2      25.6967017352
model 1+2    22.8846455135
model 1+update2  14.2816257268
 16
Author: paulperry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-17 10:09:10

Stworzyłemgist notebooka jupyter , aby zademonstrować, że model xgboost można trenować stopniowo. Użyłem boston dataset do trenowania modelu. Zrobiłem 3 eksperymenty-one shot learning, iterative one shot learning, iterative incremental learning. Podczas szkolenia przyrostowego przekazałem dane z Bostonu do modelu w partiach o rozmiarze 50.

Istotą gist jest to, że będziesz musiał wielokrotnie powtarzać dane, aby Model zbiegł się z dokładnością osiągniętą przez jeden shot (wszystkie dane) nauka.

Oto odpowiedni kod do robienia iteracyjnego przyrostowego uczenia się z 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 itr@{}: {}'.format(int(start/batch_size), sklearn.metrics.mean_squared_error(y_te, y_pr)))
    print('MSE itr@{}: {}'.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)))

Wersja XGBoost: 0.6

 12
Author: Shubham Chaudhary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-03 10:31:06

Wygląda na to, że nie potrzebujesz niczego innego niż wywołać xgb.train(....) ponownie, ale podaj wynik modelu z poprzedniej partii:

# python
params = {} # your params here
ith_batch = 0
n_batches = 100
model = None
while ith_batch < n_batches:
    d_train = getBatchData(ith_batch)
    model = xgb.train(params, d_train, xgb_model=model)
    ith_batch += 1

Jest to oparte na https://xgboost.readthedocs.io/en/latest/python/python_api.html Tutaj wpisz opis obrazka

 8
Author: Mobigital,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-09 04:23:06

Jeśli twój problem dotyczy rozmiaru zbioru danych i tak naprawdę nie potrzebujesz Nauki przyrostowej (na przykład nie masz do czynienia z aplikacją do przesyłania strumieniowego), powinieneś sprawdzić Spark lub Flink.

Te dwie struktury mogą trenować na bardzo dużych zestawach danych z małą pamięcią RAM, wykorzystując pamięć dyskową. Oba frameworki zajmują się wewnętrznie problemami z pamięcią. Chociaż Flink miał to rozwiązać pierwszy, Spark dogonił w ostatnich wydaniach.

Spójrz na:

 3
Author: Alberto Castelo Becerra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-27 17:16:13

Do kodu paulperry 'ego, jeśli Zmień jedną linię z" train_split = round(len(train_idx) / 2)" na "train_split = len (train_idx) - 50". model 1 + update2 zmieni się z 14.2816257268 na 45.60806270012028. I wiele "leaf=0" powoduje zrzut pliku.

Zaktualizowany model nie jest dobry, gdy zestaw próbek aktualizacji jest stosunkowo mały. W przypadku binary: logistic zaktualizowany model jest bezużyteczny, gdy zestaw próbek aktualizacji ma tylko jedną klasę.

 0
Author: Tao Cheng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-06 02:57:21