最近、データマイニング競争のアーティファクトであるXGBoostのアルゴリズム原理とモデルデータ構造を深く研究しました。

この記事は、「新人クリエーションセレモニー」イベントに参加し、一緒にゴールドクリエーションの道を歩み始めました。

はじめに:データマイニング関連の作業に従事する人は、XGBoostアルゴリズムを知っている必要があります。データマイニングの競争でかつて輝いていたこの世代のアーティファクトは、2016年にChenTianqiによって提案された古典的なアルゴリズムです。本質的に、XGBoostはGBDTアルゴリズムの最適化された実装と見なされますが、統合されたアルゴリズムの概念の継承に加えて、特定の設計の詳細は実際にはまったく異なります。私は最近深く研究し、基礎となる設計のデータ構造を簡単に調べました。アルゴリズムの微妙さを感じずにはいられません。将来の参考のために要約を作成するためにチャットしてください!

写真

2016年、ChenTianqiはXGBoostに関する共有セッションに招待されました

XGBoostは、機械学習のアンサンブルアルゴリズムであり、3つのアンサンブルのジャンルに分けられ、ブースティングのジャンルに属しています。Boostingのジャンルは、統合アルゴリズムの中で最もアクティブで強力なジャンルでもあります。XGBoostに加えて、前面にAdaboostとGBDTがあり、背面にLightGBMとCatBoostがあります。もちろん、LightGBMとCatBoostおよびXGBoostは、一般に、GBDTの改善および最適化された実装と見なされています。

XGBoostアルゴリズムの原理は実際には非常に成熟していて完全であり、インターネット上でこの側面について無数の共有が行われているため、この記事では前の作業を繰り返したくはありませんが、次の書き込み目的に焦点を当てています。式を説明する観点からXGBoostアルゴリズムの原理の個人的な理解。2つ目は、XGBoostの基礎となるデータ構造設計を簡単に調査することです。後者は前のツイート「データサイエンス:Sklearnのディシジョンツリー」と似ていますが、最下層はどのように設計および保存されていますか?"位置。

01数式の導出を学び、原則を理解する

XGBoostのアルゴリズムの原理を理解するために、以下は主にアルゴリズムに関連する5つの主要な式の導出プロセスを共有しています。すべての数式は、主にXGBoostの公式ドキュメント(xgboost.readthedocs.io/en/latest )から派生しています…

式1-ブースティングアンサンブルアルゴリズムの加法モデル:

式は非常に単純ですが、次の式を理解することが重要です。ブースティングアルゴリズムとして、XGBoostの統合アイデアは、典型的な加法モデルに従います。つまり、統合アルゴリズムの出力は、各基本学習者の出力の合計に等しくなります(回帰問題は合計によってよく理解され、分類問題は次のようになります。実際にフィッティングする対数損失(後述のロジスティック回帰の手法と同様)、上記の式で、fk(x)は単一の基本学習者を表し、Kは基本学習者の数を表します。次の図の例として、2人の基本学習者を含むアンサンブルモデルを取り上げます。「son」のアンサンブルモデルの出力は、2人の基本学習者のそれぞれの出力の合計、つまり2 + 0.9=2.9です。 「祖父」のアンサンブルモデルの2つです。基本学習者の出力の合計、つまり-1-0.9=-1.9。

写真

式2-XGBoostの基本学習者の目的関数

機械学習には、モデル、ポリシー、アルゴリズムの3つの要素があります。この戦略には、モデルの品質を定義または評価する方法が含まれます。つまり、損失関数を定義する必要があります。GBDTの連続フィッティング残差とは異なり、XGBoostは、モデル学習のコストとして理解できるモデルの構造的損失を増加させます。残差は、ギャップと不足として理解できる経験損失に対応します。モデル学習能力の。

上記の目的関数(目的関数は損失関数よりも高レベルの項であり、一般に2つの部分が含まれます:目的関数=損失+通常の項、小さいほど良いです。目的関数と損失関数に加えて、また、関連する用語はコスト関数と呼ばれ、ある意味で、コスト関数は損失関数としてほぼ理解できます。)、合計の最初の部分は、現在のモデルトレーニング結果と真の値の間のギャップを定義します。経験的リスクと呼ばれ、具体的な測定方法は次のようになります。対応する損失関数が定義されます。一般的な損失関数は次のとおりです。回帰問題はMSE損失に対応し、分類問題は対数損失損失に対応します。合計の2番目の部分はモデルの構造的リスクであり、モデルの一般化能力に影響を与えます。基本学習者が決定木を選択した場合、ここでの構造的リスクは次のように定義されます。

其中,γ和λ均为正则项系数,T为决策树中叶子节点的个数。注意,这里是叶子节点的个数,而非决策树中节点的数量(CART决策树进行CCP后剪枝时,用到的正则项是计算所有节点个数)。另外,这是一般介绍XGBoost原理时的公式,也是陈天齐最早论文中的写法,在Python的xgboost工具包中,模型初始化参数中除了与这两个参数对应的gamma和reg_lambda之外,还有reg_alpha参数,表示的一阶正则项,此时可写作:

公式3——XGBoost中的****Taylor二阶展开近似

理解:这个Taylor二阶展开近似可谓是XGBoost的灵魂所在,也是最能体现其相较于GBDT的玄妙和强大之处。为了更好的解释上述近似,首先给出通常意义下的Taylor展开式:

当然,上述公式也只是展开近似到了二阶,只要f(x)无限可导,则可有更高阶的近似。在XGBoost中,应用Taylor二阶展开近似其实是只对模型的经验风险部分,也就是公式2中第一部分求和的每个子项。这里,再次给出单个的表达式:

在上式中,下标i对应的是训练集中的第i个样本,上角标t和t-1对应的集成算法中的第t轮和第t-1轮。那么进一步地,谁是f,谁是x,谁是△x呢?这里,f就是个函数记号,对应的是损失函数中的l,重点需要理解x和△x。

在模型训练时,训练数据集其实是确定的,在每个基学习器中都是那一套固定值,所以yi自然也不例外,在上述公式中就可看做是常数。在集成模型训练的第t轮,此时模型训练的目的是基于前t-1轮的训练结果(此时已经确定)来寻找最优的第t轮结果,以此来得到当前可能的最小损失。

实际上,在集成学习中,第一个基学习器往往已经能够拟合出大部分的结果出来,例如在惯用的拟合年龄的例子中,假设要拟合的是100这个结果,那么很可能第一个基学习器的拟合结果是90,而后面的N-1个学习器只是在不断的修正这个残差:10。举这个例子的目的是想表达:在上述公式中前t-1轮的拟合结果y_hat其实对应的就是f(x+△x)中的x,而第t轮的拟合值则可视作是浮动变量△x。至此,照着Taylor展开式的样式,上述目标函数可具体展开为:

其中gi和hi分别为一阶导和二阶导,分别写作如下:

进一步地,记y为真实值,y_hat为拟合值,则对于回归问题,适用最为常用的MSE损失,则其loss函数及相应的一阶导和二阶导分别为:

而对于分类问题,以二分类问题为例,XGBoost中默认的损失函数为logloss,相应的loss函数及对应一阶导和二阶导分别为:

公式4——决策树中的最优叶子权重求解

XGBoost理论上可以支持任何基学习器,但其实最为常用的还是使用决策树,Python中的xgboost工具库也是默认以gbtree作为基学习器。在决策树中,第t轮训练得到的最优决策树实际上就是寻求最优的叶子权重的过程,所以理解这个最优的叶子权重尤为重要。

好在上述两个公式的求解非常简单易懂,甚至说是初中的数学知识范畴,可比SVM中的拉格朗日对偶问题容易理解多了。首先看如下转换:

第一步的约等号当然是来源于公式3中的Taylor二阶展开近似,只不过此时将常数部分省略而已,需要注意的是此时的∑求解是以样本为粒度的求解,即此时i为样本序号,n为样本总数。而在第二步的等号转换中,则是以叶子节点为粒度,将落在同一叶子节点的多个样本进行了聚合,此时落在同一叶子节点上的所有样本预测结果均为其叶子权重ωj,各个叶子节点内部的求和对应为内部的∑。

有了以上的近似展开和各叶子节点的汇聚,则可以引出如下公式:

其中Gj和Hj分别为第j个叶子节点所有样本的一阶导和二阶导的求和,即:

上述目标公式可看做是T个一元二次表达式的求和,其中每个一元二次表达式中的变量为ωj。显然,求解形如f(x)=ax^2+bx+c的最小值问题是一个初中阶段的数学问题,进而容易得出最优的ωj及此时对应的损失函数最小取值结果为:

这里的一元二次函数一定存在最小值,因为其二次项的系数1/2(Hj+λ)一定是个正数!

公式5——决策树的分裂增益

公式4解决的是叶子节点的最优权重问题,那么实际上是绕过了一个前置问题:即决策树的内部节点如何进行分裂?内部节点如何进行分裂其实可进一步细分为两个子问题:

①选择哪个特征进行分裂?

②以什么阈值划分左右子树?

第一个问题很好解决,最简单也是一直沿用至今的做法都是对所有特征逐一遍历,对比哪个特征最带来增益最大。

而对于第二个问题,其实也是采用遍历寻优的方法来得到最优分裂阈值,至于如何遍历寻优,其实还可以进一步细分为两个问题:

i)选择哪些候选分裂阈值?

ii)如何度量哪个分裂阈值更优?

选择哪些候选分裂阈值就涉及到很多技巧,XGBoost和LightGBM都采用了直方图法来简化可能的最优分裂点候选值,这里涉及的细节还有很多,暂且不谈;而对于如何度量分裂阈值更优的问题,则刚好可以利用前面公式4中的结论——叶子节点在最优权重下的最小损失表达式。以此为基础,度量最优分裂阈值的流程是这样的:

  • 如果该节点不进行分裂,即将其视作一个叶子节点,可以得到当前的最小损失取值;

  • 对于选定的特征及阈值,将当前节点的所有样本切分为左右子树,进而可以得到左右子树对应的最小损失取值;

那么,从该节点直接作为叶子节点到将其分裂为左右两个子叶子节点是否会带来损失的降低呢?所以只需将分裂前后的损失相减即可!那么相减之后γT部分为什么变为-γ了呢?其实就是因为在分裂之前该部分的正则项对应1个叶子节点,而分裂之后则对应2个叶子节点,所以两部分的γT相减即为-γ。

以上,就是关于XGBoost中的几个核心公式推导环节的理解,相信理解了这5个公式就基本能够理解XGBoost是如何设计和实现的了。当然,XGBoost的强大和设计巧妙之处绝不止于上述算法原理,其实还有很多实用的技巧和优化,这也构成了XGBoost的scalable能力,具体可参考论文《XGBoost: A Scalable Tree Boosting System》。

02 查看源码,了解底层数据结构

第一部分主要介绍了XGBoost中的核心公式部分,下面简要分享一下XGBoost中的底层数据结构设计。之所以增加这部分工作,仍然是因为近期在做部分预研工作的需要,所以重点探究了一下XGBoost中底层是如何存储所有基学习器的,也就是各个决策树的训练结果。

为了了解XGBoost中是如何存储训练后的各个决策树,我们查看分类器的模型训练部分源码,经过简单查看就可以定位到如下代码:

写真

也就是说,XGBClassifer模型训练后的结果应该是保存在_Booster属性中。

当然,上述查看的xgboost提供的sklearn类型接口,在其原生训练方法中,实际上是调用xgboost.train函数来实现的模型训练,此时无论是回归任务还是分类任务,都是调用的这个函数,只是通过目标函数的不同来区分不同的任务类型而已。

为了进一步查看这个_Booster属性,我们实际训练一个XGBoost二分类模型,运用如下简单代码示例:

from sklearn.datasets import load_iris
from xgboost import XGBClassifier

X, y = load_iris(return_X_y=True)
# 原生鸢尾花数据集是三分类,对其进行采用为二分类
X = X[y<2]
y = y[y<2]

xgb = XGBClassifier(use_label_encoder=False)
xgb.fit(X, y, eval_metric='logloss')
复制代码

而后,通过dir属性查看一下这个_Booster的结果:

写真

实际上,这个_Booster属性是xgboost中定义的一个类,上述结果也可直接查看xgboost中关于Booster类的定义。在上述dir结果中,有几个函数值得重点关注:

  • save_model:用于将xgboost模型训练结果存储为文件,而且xgboost非常友好的是在1.0.0版本以后,直接支持存储为json格式,这可比pickle格式什么的方便多了,大大增强可读性

写真

  • load_model:有save_model就一定有load_model,二者是互逆操作,即load_model可将save_model的json文件结果读取为一个xgboost模型

  • dump_model:实际上,dump也有存储的含义,例如json中定义的读写函数就是load和dump。而在xgboost中,dump_model与save_model的区别在于:dump_model的存储结果是便于人类阅读,但该过程是单向的,即dump的结果不能再load回去;

  • get_dump:与dump_model类似,只不过不是存储为文件,而只是返回一个字符串;

  • trees_to_dataframe:含义非常明了,就是将训练后的所有树信息转化为一个dataframe。

这里,首先看下trees_to_dataframe的结果:

写真

似乎从列名来推断,除了最后的Cover和Category两个字段含义不甚明了之外,其他字段的含义都非常清楚,所以也不再做过多解释。

之后,再探索一下save_model和dump_model的结果。既然dump_model的结果便于人类阅读,那么就首先查看这个结果:

写真

这里截取了dump_model后的txt文件的三个决策树信息,可见dump_model的结果仅保留了各决策树的分裂相关信息,以booster[0]第一个决策树为例,该决策树有三个节点,节点的缩进关系表达了子节点对应关系,内部节点标号标识了所选分裂特征及对应阈值,但叶子节点后面的数值实际上并非是其权重。

而后,再探索一下save_model的json文件结果,首先查看整个json的结构关系:

写真

其中,trees部分是一个含有100个item的列表,对应了100个基学习器的信息,进一步查看,类似于sklearn中定义的Array-based Tree Representation形式,这里的决策树各个节点信息仍然是Array-based,即各属性的第i个取值表示了相应的第i个节点的对应属性。主要字段及含义如下:

写真

left_children、right_children、parentsの3つの属性の値を比較した後、xgboostのデシジョンツリーのノード番号は階層的なトラバーサルであり、以前とは異なることを簡単に推測できることを指摘しておく価値があります。 sklearnで使用される順序トラバーサル。

上記は、xgboostの基本的な学習者情報の簡単な説明にすぎません。興味がある場合は、xgboostの原理を理解するのに役立つことを期待して、さらに試して、対応するソースコードの設計を表示できます。

おすすめ

転載: juejin.im/post/7096111249175347213