处理可索引元素
XGBoost 中有许多功能涉及到可数集合中的可索引元素,例如模型中的提升轮次/迭代/树(可以通过编号引用)、类别、分类特征中的类别/级别等。
XGBoost 是用 C++ 编写的,使用基于 0 的索引,并认为范围 / 序列包含左端但不包含右端 - 例如,范围 (0, 3) 将包含编号为 0、1 和 2 的前三个元素。
Python 接口使用相同的逻辑,因为这也是 Python 中索引的工作方式,但其他语言如 R 有不同的逻辑。在 R 中,索引是基于 1 的,范围/序列包含两端 - 例如,要引用序列中的前三个元素,区间应写为 (1, 3),元素编号为 1、2 和 3。
为了提供更符合R语言习惯的接口,XGBoost调整了其面向用户的R接口以遵循这种和类似的R惯例,但在内部,它需要将所有这些数字转换为C接口使用的格式。由于模型旨在在其他接口中可序列化和可加载,而这些接口将具有不同的索引逻辑,这使得问题变得更加复杂。
在R接口中进行了以下调整:
DMatrix 的分片方法,它接受一个整数数组,通过从每个元素中减去 1 转换为基于 0 的索引。请注意,这与所有其他在传递给 C 之前在 R 中完成的转换不同,这是在 R 的 C 级包装函数中完成的。
Booster 的切片方法采用由 start、end 和 step 定义的序列。R 接口旨在从用户的角度与 R 的
seq
以相同的方式工作,因此它总是通过减去一来调整左端,并且根据步长是否在右端精确结束,也会调整右端以在 C 索引中不包含右端。在
predict
中的参数iterationrange
也被设计成与 R 的seq
行为相同。由于它没有步长,只需通过减去 1 来调整左端即可。best_iteration
根据上下文,可能同时存储为 C 级别的增强器属性和 R 属性。由于 C 级别的属性在接口之间共享并在预测方法中使用,为了提高兼容性,它保留了基于 0 索引的 C 级别属性,但如果存在 R 属性,则将调整为基于 1 索引。请注意,R 和其他接口中的predict
方法只会查看 C 级别的属性。其他引用迭代次数或提升轮次的地方,例如在打印指标或保存模型快照时,也遵循基于1的索引。这些其他引用完全用R编写,因为C级别的函数不处理这些功能。
终端叶/节点编号以基于0的索引方式返回,就像它们来自C接口一样。
图表中的树编号遵循基于1的索引。请注意,这些编号仅在使用R接口处理DiagrammeR对象生成这些图表时显示,而在使用C级GraphViz ‘dot’格式生成图表时不显示。
在生成特征重要性、JSON、树到表转换以及SHAP时,所有特征编号都遵循基于0的索引。
分类特征在 R 中被定义为
factor
类型,该类型使用基于 1 的索引进行编码。当分类特征作为 R 的factor
类型传递时,会自动转换为基于 0 的索引,但如果用户希望手动提供已经编码为整数的分类特征,那么这些整数需要已经是基于 0 的编码。输出中的分类级别(类别),如图表、JSON和树到表,也使用基于0的索引进行引用,无论它们是作为整数还是作为
factor
类型的列输入模型的。DMatrices 的分类标签不会进行任何额外处理 - 用户必须提供基于 0 编码的标签。
在使用线性系数历史回调时,获取特定类系数的函数需要一个类索引参数,该参数也不进行任何转换(即用户必须传递一个基于0的索引),以便与标签逻辑匹配——也就是说,相同的类索引将引用在DMatrix
label
字段中用该数字编码的类。
R 接口的新增功能应考虑到这些约定,并尽可能模仿 R 的行为。