Il problema è che i dati del treno non possono essere inseriti nella RAM a causa della dimensione dei dati del treno. Quindi ho bisogno di un metodo che prima costruisca un albero su tutto il set di dati del treno, calcoli i residui costruisca un altro albero e così via (come l'albero con gradiente aumentato). Ovviamente se chiamo model = xgb.train(param, batch_dtrain, 2)
in qualche ciclo - non sarà d'aiuto, perché in tal caso ricostruisce solo l'intero modello per ogni lotto.Come posso implementare la formazione incrementale per xgboost?
risposta
Disclaimer: Sono nuovo anche per xgboost, ma penso di averlo capito.
Provare a salvare il modello dopo l'allenamento del primo lotto. Quindi, nelle esecuzioni successive, fornire il metodo xgb.train con il percorso file del modello salvato.
Ecco un piccolo esperimento che mi sono imbattuto di convincermi che funziona:
In primo luogo, dividere il set di dati Boston nella formazione e set di test. Quindi dividere il set di allenamento a metà. Adatta un modello con il primo tempo e ottieni un punteggio che servirà da punto di riferimento. Quindi montare due modelli con la seconda metà; un modello avrà il parametro aggiuntivo xgb_model. Se passare il parametro extra non ha fatto la differenza, allora ci aspettiamo che i loro punteggi siano simili .. Ma, fortunatamente, il nuovo modello sembra funzionare molto meglio del primo.
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
Fatemi sapere se qualcosa non è chiaro!
di riferimento: https://github.com/dmlc/xgboost/blob/master/python-package/xgboost/training.py
Vorrei capire che model_2_v2 ha prestazioni peggiori rispetto al modello che utilizzava entrambi i set di dati contemporaneamente. Ma model_2_v2 è peggio di model_1 che è piuttosto strano perché diamo un nuovo set di dati che model_1 non ha visto, ma alla fine model_2_v2 si è comportato peggio ... Sembra che gli alberi potenziati non siano il modo migliore per eseguire l'apprendimento incrementale. @pikachau hai provato a usare model_1 invece di 'experiment.model'? –
Potrebbe essere perché il set di dati è piuttosto piccolo (dimensione del campione = 150). Con un set di dati più grande, penso che model_2_v2 dovrebbe superare il modello_1. Oh, esperimento.model == model_1; Avrei dovuto renderlo più esplicito! – Alain
ora c'è (versione 0.6?) Un parametro process_update che potrebbe aiutare. Ecco un esperimento con esso:
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"
uscita:
full train 17.8364309709
model 1 24.8
model 2 25.6967017352
model 1+2 22.8846455135
model 1+update2 14.2816257268
Qual è il modello finale o quello che dovrei usare? – tumbleweed
Si desidera il modello con l'MSE più basso. Ma nota come 1 + update2 è inferiore al treno completo! Non mi è chiaro il motivo per cui dovrebbe essere così, quindi sarei sospettoso di questo risultato e gestirò un CV con più pieghe. – paulperry
ho creato a gist of jupyter notebook di dimostrare che il modello xgboost può essere addestrato in modo incrementale. Ho usato il set di dati di Boston per addestrare la modella. Ho fatto 3 esperimenti: apprendimento one shot, apprendimento one-iterativo, apprendimento incrementale iterativo. In formazione incrementale, ho passato i dati di Boston al modello in lotti di 50.
Il nocciolo della questione è che dovrete scorrere più volte i dati per far convergere il modello alla precisione raggiunta da un solo colpo (tutti i dati) di apprendimento.
Ecco il codice corrispondente per l'esecuzione dell'apprendimento incrementale iterativo con xgboost. Versione
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
Esempi dal repo 'xgboost': https://github.com/dmlc/xgboost/blob/master/tests/python/test_training_continuation.py –