XGBoost如何避免过拟合

过拟合是复杂非线性算法中的一类问题,这篇文章将会介绍如何使用early stopping去避免XGBoost 中的过拟合问题。

通过阅读这篇文章你将会了解到:

early stopping是一种避免training data过拟合的方式。

如何在训练过程中监控XGBoost模型的性能,并绘制学习曲线。

如何使用early stopping在一个最佳的时间提前停止一个XGBoost模型的训练。

early stopping是一种避免training data过拟合的方式。

它的工作原理是监控在一个单独的测试数据集上训练的模型的性能,并在经过固定次数的训练迭代后,测试数据集上的性能没有改善时停止训练过程。

它试图通过自动选择拐点来避免过度拟合,在拐点处,随着模型开始过度拟合,测试数据集上的性能开始下降,而训练数据集上的性能继续提高。

性能度量可以是为训练模型而优化的损失函数(如对数损失),也可以是外部度量指标(如分类精度)。

使用XGBoost监控训练性能

XGBoost模型可以在训练过程中评估和报告模型在测试集上的性能

它通过训练模型并指定详细输出时,在调用model.fit()时指定测试数据集和评估度量来支持这种功能。

扫描二维码关注公众号,回复: 5869169 查看本文章

例如,我们可以在训练XGBoost模型时,输出一个独立测试集(eval_set)的二分类错误率(“error”),如下:

eval_set = [(X_test, y_test)]
model.fit(X_train, y_train, eval_metric="error", eval_set=eval_set, verbose=True)

XGBoost支持一套评估指标,不限于:

“rmse” 表示均方根误差。
“mae” 表示平均绝对误差.
“logloss” 用于二进制对数损失和“mlogloss”用于多类日志损失(交叉熵)
“error” 表示分类错误率
“auc” 表示ROC曲线下的面积

了解完整参数点这里

例如,我们可以演示如何在UCI机器学习存储库提供的Pima Indians onset of diabetes数据集上跟踪XGBoost模型的训练性能。

完整的例子如下:

# monitor training performance

from numpy import loadtxt
from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# load data
dataset = loadtxt('pima-indians-diabetes.csv', delimiter=",")

# split data into X and y
X = dataset[:,0:8]
Y = dataset[:,8]

# split data into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.33, random_state=7)

# fit model no training data
model = XGBClassifier()
eval_set = [(X_test, y_test)]
model.fit(X_train, y_train, eval_metric="error", eval_set=eval_set, verbose=True)

# make predictions for test data
y_pred = model.predict(X_test)
predictions = [round(value) for value in y_pred]

# evaluate predictions
accuracy = accuracy_score(y_test, predictions)
print("Accuracy: %.2f%%" % (accuracy * 100.0))

运行此示例将在67%的数据上训练模型,并在33%的测试数据集上评估模型。

每次迭代都报告分类错误,最后报告分类精度。

下面提供了输出,为了简洁起见进行了截断。我们可以看到,在每次训练迭代中都会报告分类错误(在每个增强树被添加到模型之后)。

...
[89]	validation_0-error:0.204724
[90]	validation_0-error:0.208661
[91]	validation_0-error:0.208661
[92]	validation_0-error:0.208661
[93]	validation_0-error:0.208661
[94]	validation_0-error:0.208661
[95]	validation_0-error:0.212598
[96]	validation_0-error:0.204724
[97]	validation_0-error:0.212598
[98]	validation_0-error:0.216535
[99]	validation_0-error:0.220472
Accuracy: 77.95%

回顾所有的输出,我们可以看到测试集上的模型性能保持不变,甚至在训练结束时变得更糟。

使用学习曲线评估XGBoost模型

我们可以在评估数据集上评估模型的性能,并将其绘制成图,从而深入了解学习是如何在训练中展开的。

在拟合XGBoost模型时,我们为eval_metric参数提供了一个X和y对数组。除了测试集,我们还可以提供训练数据集。这将提供一个关于模型在训练期间在train_data和test_data上的表现。

例如:

eval_set = [(X_train, y_train), (X_test, y_test)]
model.fit(X_train, y_train, eval_metric="error", eval_set=eval_set, verbose=True)

此外,通过调用model.evals_result()函数,将模型在每个评估集上的性能存储起来,并在训练之后由模型提供。这返回一个字典的评估数据集和分数,例如:

results = model.evals_result()
print(results)

打印如下结果(为简洁起见,进行了截短):

{
	'validation_0': {'error': [0.259843, 0.26378, 0.26378, ...]},
	'validation_1': {'error': [0.22179, 0.202335, 0.196498, ...]}
}

每个’ validation_0 ‘和’ validation_1 '都对应于在调用to fit()时向eval_set参数提供数据集的顺序。

访问一个特定的结果数组,如第一个数据集和误差度量,可以如下:

results['validation_0']['error']

此外,我们还可以为fit()函数的eval_metric参数提供一个度量数组,从而指定更多的评估度量,以便评估和收集。

然后,我们可以使用这些收集的性能度量来创建一个线图,并进一步了解模型在训练期间在训练和测试数据集中的表现。

下面是完整的代码示例,展示了如何将收集到的结果可视化到行图中。

# plot learning curve(学习曲线)

from numpy import loadtxt
from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from matplotlib import pyplot

# load data
dataset = loadtxt('pima-indians-diabetes.csv', delimiter=",")

# split data into X and y
X = dataset[:,0:8]
Y = dataset[:,8]

# split data into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.33, random_state=7)

# fit model no training data
model = XGBClassifier()
eval_set = [(X_train, y_train), (X_test, y_test)]
model.fit(X_train, y_train, eval_metric=["error", "logloss"], eval_set=eval_set, verbose=True)

# make predictions for test data
y_pred = model.predict(X_test)
predictions = [round(value) for value in y_pred]

# evaluate predictions
accuracy = accuracy_score(y_test, predictions)
print("Accuracy: %.2f%%" % (accuracy * 100.0))

# retrieve performance metrics
results = model.evals_result()
epochs = len(results['validation_0']['error'])
x_axis = range(0, epochs)

# plot log loss
fig, ax = pyplot.subplots()
ax.plot(x_axis, results['validation_0']['logloss'], label='Train')
ax.plot(x_axis, results['validation_1']['logloss'], label='Test')
ax.legend()
pyplot.ylabel('Log Loss')
pyplot.title('XGBoost Log Loss')
pyplot.show()

# plot classification error
fig, ax = pyplot.subplots()
ax.plot(x_axis, results['validation_0']['error'], label='Train')
ax.plot(x_axis, results['validation_1']['error'], label='Test')
ax.legend()
pyplot.ylabel('Classification Error')
pyplot.title('XGBoost Classification Error')
pyplot.show()

运行此代码将在每个单元上report训练和测试数据集上的分类错误。我们可以通过在对fit()函数的调用中设置verbose=False(缺省值)来关闭此功能。

创建了两个图。第一个显示了训练和测试数据集中每个单元的XGBoost模型的对数损失。

在这里插入图片描述
第二幅图显示了XGBoost模型在训练和测试数据集中对每个单元的分类误差。

在这里插入图片描述
从logloss的表现来看,似乎有机会尽早停止学习,也许是在epoch 20到epoch 40左右。

我们在分类错误中也看到了类似的情况,在epoch 40左右,错误又升高了。

例如,我们可以检查在10个周期内对数损失没有改善,如下:

eval_set = [(X_test, y_test)]
model.fit(X_train, y_train, early_stopping_rounds=10, eval_metric="logloss", eval_set=eval_set, verbose=True)

如果提供了多个评估数据集或多个评估指标,那么early stop将使用列表中的最后一个。

下面提供了关于early stopping的完整性的完整示例。

# early stopping
from numpy import loadtxt
from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# load data
dataset = loadtxt('pima-indians-diabetes.csv', delimiter=",")

# split data into X and y
X = dataset[:,0:8]
Y = dataset[:,8]

# split data into train and test sets
seed = 7
test_size = 0.33
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=test_size, random_state=seed)

# fit model no training data
model = XGBClassifier()
eval_set = [(X_test, y_test)]
model.fit(X_train, y_train, early_stopping_rounds=10, eval_metric="logloss", eval_set=eval_set, verbose=True)

# make predictions for test data
y_pred = model.predict(X_test)
predictions = [round(value) for value in y_pred]

# evaluate predictions
accuracy = accuracy_score(y_test, predictions)
print("Accuracy: %.2f%%" % (accuracy * 100.0))

运行这个例子提供了以下输出,为了简洁起见,进行了截断:

...
[35]	validation_0-logloss:0.487962
[36]	validation_0-logloss:0.488218
[37]	validation_0-logloss:0.489582
[38]	validation_0-logloss:0.489334
[39]	validation_0-logloss:0.490969
[40]	validation_0-logloss:0.48978
[41]	validation_0-logloss:0.490704
[42]	validation_0-logloss:0.492369
Stopping. Best iteration:
[32]	validation_0-logloss:0.487297

我们可以看到模型在epoch 42停止训练(接近我们手工判断学习曲线所期望的),损失最大的模型在epoch 32观察到。

一般来说,选择early_stopping_round作为训练周期总数(本例中为10%)的合理函数,或者尝试与学习曲线图中可能观察到的拐点周期相对应,这是一个好主意。

总结

在本文中,您了解了有关监视性能和early stopping的内容。

您学习了:

在模型与训练数据过拟合之前,采用early stopping技术停止模型训练。
如何在训练过程中监控XGBoost模型的性能,并绘制学习曲线。
如何配置训练XGBoost模型时的early stopping。

文章原出处https://machinelearningmastery.com/avoid-overfitting-by-early-stopping-with-xgboost-in-python/

猜你喜欢

转载自blog.csdn.net/liuzonghao88/article/details/88808408
今日推荐