如何为xgboost实施增量培训?

时间:2016-06-28 15:05:09

标签: python machine-learning xgboost

问题是由于列车数据大小,我的列车数据无法放入RAM。所以我需要一种方法,首先在整列火车数据集上构建一棵树,计算残差构建另一棵树等等(如渐变提升树那样)。显然,如果我在某个循环中调用model = xgb.train(param, batch_dtrain, 2) - 它将无济于事,因为在这种情况下它只是为每个批次重建整个模型。

6 个答案:

答案 0 :(得分:26)

免责声明:我也是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

答案 1 :(得分:11)

现在(版本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.2542132108
model 2      25.6967017352
model 1+2    22.8846455135
model 1+update2  14.2816257268

答案 2 :(得分:5)

我创建了a gist of jupyter notebook来证明可以逐步训练xgboost模型。我使用波士顿数据集来训练模型。我做了3个实验 - 一次学习,迭代一次学习,迭代增量学习。在增量训练中,我将波士顿数据分批传递给模型50。

要点的要点是,您必须多次迭代数据才能使模型收敛到一次性(所有数据)学习所达到的精度。

以下是使用xgboost进行迭代增量学习的相应代码。

[]
[]
['AB']
['AB', 'BC', 'CA']
['AB', 'BC', 'CD', 'DA', 'AC', 'BD']
['AB', 'BC', 'CD', 'DE', 'EA', 'AC', 'BD', 'CE', 'DA', 'EB']
['AB', 'BC', 'CD', 'DE', 'EF', 'FA', 'AC', 'BD', 'CE', 'DF', 'EA', 'FB', 'AD', 'BE', 'CF']

XGBoost版本:0.6

答案 3 :(得分:2)

如果您的问题与数据集大小相关并且您并不真正需要增量学习(例如,您没有处理Streaming应用程序),那么您应该查看Spark或Flink。

这两个框架可以在具有较小RAM的非常大的数据集上进行训练,利用磁盘内存。两个框架都在内部处理内存问题。虽然Flink首先解决了这个问题,但Spark已经赶上了最近的版本。

看看:

答案 4 :(得分:1)

看起来您不需要什么,只需要再次致电.,而是提供上一批的模型结果:

xgb.train(....)

这是基于https://xgboost.readthedocs.io/en/latest/python/python_api.html enter image description here

答案 5 :(得分:0)

对于包装厂的代码,如果将一行从“ train_split = round(len(train_idx)/ 2)”更改为“ train_split = len(train_idx)-50”。型号1 + update2将从14.2816257268更改为45.60806270012028。并且大量“ leaf = 0”会导致转储文件。

当更新样本集相对较小时,更新的模型不好。 对于binary:logistic,当更新样本集只有一个类时,更新的模型将不可用。