参数调优是机器学习中的一门黑艺术,一个模型的最优参数可能取决于许多情境。因此,要为此提供全面的指南是不可能的。
了解偏差-方差权衡Bias-Variance Tradeoff
当能允许模型变得更加复杂(例如更深),模型具有更好的拟合训练数据的能力,从而产生一个偏差较小的模型。然而,这样复杂的模型需要更多的数据来进行拟合。
XGBoost 中的大多数参数都涉及到偏差方差的权衡。最佳模型应该仔细权衡模型复杂性与其预测能力。参数文档告诉了每个参数是否会使模型更保守。这可以帮助我们在复杂模型和简单模型之间找到平衡点。
控制过拟合Overfitting
当观察到高的训练准确性但低的测试准确性时,很可能遇到了过拟合问题。
通常有两种方式可以控制 XGBoost 中的过拟合:
-
第一种方式是直接控制模型的复杂性
- 包括
max_depth
、min_child_weight
和gamma
- 包括
-
第二种方式是增加随机性以使训练对噪声更加稳健。
-
包括
subsample
和colsample_bytree
-
可以减小步长
eta
,这样做时增加num_round
-
处理不平衡数据
对于一些常见情况,比如广告点击日志,数据集可能极度不平衡。这可能会影响 XGBoost 模型的训练,有两种方式可以改善它。
-
如果只关心预测的整体性能指标(AUC)
-
通过
scale_pos_weight
平衡正负权重 -
使用 AUC 进行评估
-
-
如果关心准确预测概率
-
在这种情况下,不能重新平衡数据集
-
设置参数
max_delta_step
为一个有限的数(比如1)以帮助收敛
-
减少内存使用
如果正在使用像 sklearn.model_selection.GridSearchCV
这样的 HPO(超参数优化)库,请控制可以使用的线程数。最好让 XGBoost 并行运行,而不是要求 GridSearchCV 同时运行多个实验。例如,为交叉验证创建数据折叠可能会消耗大量内存:
# 这将创建数据集的副本。X 和 X_train 同时存在于内存中。如果使用 `n_jobs` 大于 1 运行 `GridSearchCV`,则每个线程都会同时执行此操作
X_train, X_test, y_train, y_test = train_test_split(X, y)
df = pd.DataFrame()
# 即使指定 inplace 参数,这也会创建数据框的新副本
new_df = df.drop(...)
array = np.array(...)
# 这可能会根据数据类型而决定是否复制数据
array.astype(np.float32)
# np 默认使用双精度, 真的需要吗?
array = np.array(...)
可以在文档中找到更多分散的降低内存使用的实践,比如:Dask 中的分布式 XGBoost,以及 XGBoost 的 GPU 支持。然而,在深入了解这些之前,有意识地减少数据副本是一个很好的起点。通常情况下,它所消耗的内存比人们预期的要多得多。