引用:Datawhale

XGBoost算法

XGBoost是陈天奇等人开发的一个开源机器学习项目,高效地实现了GBDT算法并进行了算法和工程上的许多改进,被广泛应用在Kaggle竞赛及其他许多机器学习竞赛中并取得了不错的成绩。XGBoost本质上还是一个GBDT,但是力争把速度和效率发挥到极致,所以叫X (Extreme) GBoosted,包括前面说过,两者都是boosting方法。XGBoost是一个优化的分布式梯度增强库,旨在实现高效,灵活和便携。 它在Gradient Boosting框架下实现机器学习算法。 XGBoost提供了并行树提升(也称为GBDT,GBM),可以快速准确地解决许多数据科学问题。 相同的代码在主要的分布式环境(Hadoop,SGE,MPI)上运行,并且可以解决超过数十亿个样例的问题。XGBoost利用了核外计算并且能够使数据科学家在一个主机上处理数亿的样本数据。最终,将这些技术进行结合来做一个端到端的系统以最少的集群系统来扩展到更大的数据集上。Xgboost以CART决策树为子模型,通过Gradient Tree Boosting实现多棵CART树的集成学习,得到最终模型。下面我们来看看XGBoost的最终模型构建:
引用陈天奇的论文,我们的数据为:D={(xi,yi)}(∣D∣=n,xi∈Rm,yi∈R)\mathcal{D}=\left\{\left(\mathbf{x}_{i}, y_{i}\right)\right\}\left(|\mathcal{D}|=n, \mathbf{x}_{i} \in \mathbb{R}^{m}, y_{i} \in \mathbb{R}\right)D={(xi​,yi​)}(∣D∣=n,xi​∈Rm,yi​∈R)
(1) 构造目标函数:
假设有K棵树,则第i个样本的输出为y^i=ϕ(xi)=∑k=1Kfk(xi),fk∈F\hat{y}_{i}=\phi\left(\mathrm{x}_{i}\right)=\sum_{k=1}^{K} f_{k}\left(\mathrm{x}_{i}\right), \quad f_{k} \in \mathcal{F}y^​i​=ϕ(xi​)=∑k=1K​fk​(xi​),fk​∈F,其中,F={f(x)=wq(x)}(q:Rm→T,w∈RT)\mathcal{F}=\left\{f(\mathbf{x})=w_{q(\mathbf{x})}\right\}\left(q: \mathbb{R}^{m} \rightarrow T, w \in \mathbb{R}^{T}\right)F={f(x)=wq(x)​}(q:Rm→T,w∈RT)
因此,目标函数的构建为:
L(ϕ)=∑il(y^i,yi)+∑kΩ(fk)\mathcal{L}(\phi)=\sum_{i} l\left(\hat{y}_{i}, y_{i}\right)+\sum_{k} \Omega\left(f_{k}\right) L(ϕ)=i∑​l(y^​i​,yi​)+k∑​Ω(fk​)
其中,∑il(y^i,yi)\sum_{i} l\left(\hat{y}_{i}, y_{i}\right)∑i​l(y^​i​,yi​)为loss function,∑kΩ(fk)\sum_{k} \Omega\left(f_{k}\right)∑k​Ω(fk​)为正则化项。
(2) 叠加式的训练(Additive Training):
给定样本xix_ixi​,y^i(0)=0\hat{y}_i^{(0)} = 0y^​i(0)​=0(初始预测),y^i(1)=y^i(0)+f1(xi)\hat{y}_i^{(1)} = \hat{y}_i^{(0)} + f_1(x_i)y^​i(1)​=y^​i(0)​+f1​(xi​),y^i(2)=y^i(0)+f1(xi)+f2(xi)=y^i(1)+f2(xi)\hat{y}_i^{(2)} = \hat{y}_i^{(0)} + f_1(x_i) + f_2(x_i) = \hat{y}_i^{(1)} + f_2(x_i)y^​i(2)​=y^​i(0)​+f1​(xi​)+f2​(xi​)=y^​i(1)​+f2​(xi​)…以此类推,可以得到:$ \hat{y}_i^{(K)} = \hat{y}_i^{(K-1)} + f_K(x_i)$ ,其中,$ \hat{y}_i^{(K-1)} $ 为前K-1棵树的预测结果,$ f_K(x_i)$ 为第K棵树的预测结果。
因此,目标函数可以分解为:
L(K)=∑i=1nl(yi,y^i(K−1)+fK(xi))+∑kΩ(fk)\mathcal{L}^{(K)}=\sum_{i=1}^{n} l\left(y_{i}, \hat{y}_{i}^{(K-1)}+f_{K}\left(\mathrm{x}_{i}\right)\right)+\sum_{k} \Omega\left(f_{k}\right) L(K)=i=1∑n​l(yi​,y^​i(K−1)​+fK​(xi​))+k∑​Ω(fk​)
由于正则化项也可以分解为前K-1棵树的复杂度加第K棵树的复杂度,因此:L(K)=∑i=1nl(yi,y^i(K−1)+fK(xi))+∑k=1K−1Ω(fk)+Ω(fK)\mathcal{L}^{(K)}=\sum_{i=1}^{n} l\left(y_{i}, \hat{y}_{i}^{(K-1)}+f_{K}\left(\mathrm{x}_{i}\right)\right)+\sum_{k=1} ^{K-1}\Omega\left(f_{k}\right)+\Omega\left(f_{K}\right)L(K)=∑i=1n​l(yi​,y^​i(K−1)​+fK​(xi​))+∑k=1K−1​Ω(fk​)+Ω(fK​),由于∑k=1K−1Ω(fk)\sum_{k=1} ^{K-1}\Omega\left(f_{k}\right)∑k=1K−1​Ω(fk​)在模型构建到第K棵树的时候已经固定,无法改变,因此是一个已知的常数,可以在最优化的时候省去,故:
L(K)=∑i=1nl(yi,y^i(K−1)+fK(xi))+Ω(fK)\mathcal{L}^{(K)}=\sum_{i=1}^{n} l\left(y_{i}, \hat{y}_{i}^{(K-1)}+f_{K}\left(\mathrm{x}_{i}\right)\right)+\Omega\left(f_{K}\right) L(K)=i=1∑n​l(yi​,y^​i(K−1)​+fK​(xi​))+Ω(fK​)
(3) 使用泰勒级数近似目标函数:
L(K)≃∑i=1n[l(yi,y^(K−1))+gifK(xi)+12hifK2(xi)]+Ω(fK)\mathcal{L}^{(K)} \simeq \sum_{i=1}^{n}\left[l\left(y_{i}, \hat{y}^{(K-1)}\right)+g_{i} f_{K}\left(\mathrm{x}_{i}\right)+\frac{1}{2} h_{i} f_{K}^{2}\left(\mathrm{x}_{i}\right)\right]+\Omega\left(f_{K}\right) L(K)≃i=1∑n​[l(yi​,y^​(K−1))+gi​fK​(xi​)+21​hi​fK2​(xi​)]+Ω(fK​)
其中,gi=∂y^(t−1)l(yi,y^(t−1))g_{i}=\partial_{\hat{y}(t-1)} l\left(y_{i}, \hat{y}^{(t-1)}\right)gi​=∂y^​(t−1)​l(yi​,y^​(t−1))和hi=∂y^(t−1)2l(yi,y^(t−1))h_{i}=\partial_{\hat{y}^{(t-1)}}^{2} l\left(y_{i}, \hat{y}^{(t-1)}\right)hi​=∂y^​(t−1)2​l(yi​,y^​(t−1))
在这里,我们补充下泰勒级数的相关知识:
在数学中,泰勒级数(英语:Taylor series)用无限项连加式——级数来表示一个函数,这些相加的项由函数在某一点的导数求得。具体的形式如下:
f(x)=f(x0)0!+f′(x0)1!(x−x0)+f′′(x0)2!(x−x0)2+…+f(n)(x0)n!(x−x0)n+......f(x)=\frac{f\left(x_{0}\right)}{0 !}+\frac{f^{\prime}\left(x_{0}\right)}{1 !}\left(x-x_{0}\right)+\frac{f^{\prime \prime}\left(x_{0}\right)}{2 !}\left(x-x_{0}\right)^{2}+\ldots+\frac{f^{(n)}\left(x_{0}\right)}{n !}\left(x-x_{0}\right)^{n}+...... f(x)=0!f(x0​)​+1!f′(x0​)​(x−x0​)+2!f′′(x0​)​(x−x0​)2+…+n!f(n)(x0​)​(x−x0​)n+......
由于∑i=1nl(yi,y^(K−1))\sum_{i=1}^{n}l\left(y_{i}, \hat{y}^{(K-1)}\right)∑i=1n​l(yi​,y^​(K−1))在模型构建到第K棵树的时候已经固定,无法改变,因此是一个已知的常数,可以在最优化的时候省去,故:
L~(K)=∑i=1n[gifK(xi)+12hifK2(xi)]+Ω(fK)\tilde{\mathcal{L}}^{(K)}=\sum_{i=1}^{n}\left[g_{i} f_{K}\left(\mathbf{x}_{i}\right)+\frac{1}{2} h_{i} f_{K}^{2}\left(\mathbf{x}_{i}\right)\right]+\Omega\left(f_{K}\right) L~(K)=i=1∑n​[gi​fK​(xi​)+21​hi​fK2​(xi​)]+Ω(fK​)
(4) 如何定义一棵树:
为了说明如何定义一棵树的问题,我们需要定义几个概念:第一个概念是样本所在的节点位置q(x)q(x)q(x),第二个概念是有哪些样本落在节点j上Ij={i∣q(xi)=j}I_{j}=\left\{i \mid q\left(\mathbf{x}_{i}\right)=j\right\}Ij​={i∣q(xi​)=j},第三个概念是每个结点的预测值wq(x)w_{q(x)}wq(x)​,第四个概念是模型复杂度Ω(fK)\Omega\left(f_{K}\right)Ω(fK​),它可以由叶子节点的个数以及节点函数值来构建,则:Ω(fK)=γT+12λ∑j=1Twj2\Omega\left(f_{K}\right) = \gamma T+\frac{1}{2} \lambda \sum_{j=1}^{T} w_{j}^{2}Ω(fK​)=γT+21​λ∑j=1T​wj2​。如下图的例子:

q(x1)=1,q(x2)=3,q(x3)=1,q(x4)=2,q(x5)=3q(x_1) = 1,q(x_2) = 3,q(x_3) = 1,q(x_4) = 2,q(x_5) = 3q(x1​)=1,q(x2​)=3,q(x3​)=1,q(x4​)=2,q(x5​)=3,I1={1,3},I2={4},I3={2,5}I_1 = \{1,3\},I_2 = \{4\},I_3 = \{2,5\}I1​={1,3},I2​={4},I3​={2,5},w=(15,12,20)w = (15,12,20)w=(15,12,20)
因此,目标函数用以上符号替代后:
L~(K)=∑i=1n[gifK(xi)+12hifK2(xi)]+γT+12λ∑j=1Twj2=∑j=1T[(∑i∈Ijgi)wj+12(∑i∈Ijhi+λ)wj2]+γT\begin{aligned} \tilde{\mathcal{L}}^{(K)} &=\sum_{i=1}^{n}\left[g_{i} f_{K}\left(\mathrm{x}_{i}\right)+\frac{1}{2} h_{i} f_{K}^{2}\left(\mathrm{x}_{i}\right)\right]+\gamma T+\frac{1}{2} \lambda \sum_{j=1}^{T} w_{j}^{2} \\ &=\sum_{j=1}^{T}\left[\left(\sum_{i \in I_{j}} g_{i}\right) w_{j}+\frac{1}{2}\left(\sum_{i \in I_{j}} h_{i}+\lambda\right) w_{j}^{2}\right]+\gamma T \end{aligned} L~(K)​=i=1∑n​[gi​fK​(xi​)+21​hi​fK2​(xi​)]+γT+21​λj=1∑T​wj2​=j=1∑T​⎣⎡​⎝⎛​i∈Ij​∑​gi​⎠⎞​wj​+21​⎝⎛​i∈Ij​∑​hi​+λ⎠⎞​wj2​⎦⎤​+γT​
由于我们的目标就是最小化目标函数,现在的目标函数化简为一个关于w的二次函数:L~(K)=∑j=1T[(∑i∈Ijgi)wj+12(∑i∈Ijhi+λ)wj2]+γT\tilde{\mathcal{L}}^{(K)}=\sum_{j=1}^{T}\left[\left(\sum_{i \in I_{j}} g_{i}\right) w_{j}+\frac{1}{2}\left(\sum_{i \in I_{j}} h_{i}+\lambda\right) w_{j}^{2}\right]+\gamma TL~(K)=∑j=1T​[(∑i∈Ij​​gi​)wj​+21​(∑i∈Ij​​hi​+λ)wj2​]+γT,根据二次函数求极值的公式:y=ax2bxcy=ax^2 bx cy=ax2bxc求极值,对称轴在x=−b2ax=-\frac{b}{2 a}x=−2ab​,极值为y=4ac−b24ay=\frac{4 a c-b^{2}}{4 a}y=4a4ac−b2​,因此:
wj∗=−∑i∈Ijgi∑i∈Ijhi+λw_{j}^{*}=-\frac{\sum_{i \in I_{j}} g_{i}}{\sum_{i \in I_{j}} h_{i}+\lambda} wj∗​=−∑i∈Ij​​hi​+λ∑i∈Ij​​gi​​
以及
L~(K)(q)=−12∑j=1T(∑i∈Ijgi)2∑i∈Ijhi+λ+γT\tilde{\mathcal{L}}^{(K)}(q)=-\frac{1}{2} \sum_{j=1}^{T} \frac{\left(\sum_{i \in I_{j}} g_{i}\right)^{2}}{\sum_{i \in I_{j}} h_{i}+\lambda}+\gamma T L~(K)(q)=−21​j=1∑T​∑i∈Ij​​hi​+λ(∑i∈Ij​​gi​)2​+γT
(5) 如何寻找树的形状:
不难发现,刚刚的讨论都是基于树的形状已经确定了计算www和LLL,但是实际上我们需要像学习决策树一样找到树的形状。因此,我们借助决策树学习的方式,使用目标函数的变化来作为分裂节点的标准。我们使用一个例子来说明:

例子中有8个样本,分裂方式如下,因此:
L~(old)=−12[(g7+g8)2H7+H8+λ+(g1+...+g6)2H1+...+H6+λ]+2γL~(new)=−12[(g7+g8)2H7+H8+λ+(g1+...+g3)2H1+...+H3+λ+(g4+...+g6)2H4+...+H6+λ]+3γL~(old)−L~(new)=12[(g1+...+g3)2H1+...+H3+λ+(g4+...+g6)2H4+...+H6+λ−(g1+...+g6)2h1+...+h6+λ]−γ\tilde{\mathcal{L}}^{(old)} = -\frac{1}{2}[\frac{(g_7 + g_8)^2}{H_7+H_8 + \lambda} + \frac{(g_1 +...+ g_6)^2}{H_1+...+H_6 + \lambda}] + 2\gamma \\ \tilde{\mathcal{L}}^{(new)} = -\frac{1}{2}[\frac{(g_7 + g_8)^2}{H_7+H_8 + \lambda} + \frac{(g_1 +...+ g_3)^2}{H_1+...+H_3 + \lambda} + \frac{(g_4 +...+ g_6)^2}{H_4+...+H_6 + \lambda}] + 3\gamma\\ \tilde{\mathcal{L}}^{(old)} - \tilde{\mathcal{L}}^{(new)} = \frac{1}{2}[ \frac{(g_1 +...+ g_3)^2}{H_1+...+H_3 + \lambda} + \frac{(g_4 +...+ g_6)^2}{H_4+...+H_6 + \lambda} - \frac{(g_1+...+g_6)^2}{h_1+...+h_6+\lambda}] - \gamma L~(old)=−21​[H7​+H8​+λ(g7​+g8​)2​+H1​+...+H6​+λ(g1​+...+g6​)2​]+2γL~(new)=−21​[H7​+H8​+λ(g7​+g8​)2​+H1​+...+H3​+λ(g1​+...+g3​)2​+H4​+...+H6​+λ(g4​+...+g6​)2​]+3γL~(old)−L~(new)=21​[H1​+...+H3​+λ(g1​+...+g3​)2​+H4​+...+H6​+λ(g4​+...+g6​)2​−h1​+...+h6​+λ(g1​+...+g6​)2​]−γ
因此,从上面的例子看出:分割节点的标准为max{L~(old)−L~(new)}max\{\tilde{\mathcal{L}}^{(old)} - \tilde{\mathcal{L}}^{(new)} \}max{L~(old)−L~(new)},即:
Lsplit =12[(∑i∈ILgi)2∑i∈ILhi+λ+(∑i∈IRgi)2∑i∈IRhi+λ−(∑i∈Igi)2∑i∈Ihi+λ]−γ\mathcal{L}_{\text {split }}=\frac{1}{2}\left[\frac{\left(\sum_{i \in I_{L}} g_{i}\right)^{2}}{\sum_{i \in I_{L}} h_{i}+\lambda}+\frac{\left(\sum_{i \in I_{R}} g_{i}\right)^{2}}{\sum_{i \in I_{R}} h_{i}+\lambda}-\frac{\left(\sum_{i \in I} g_{i}\right)^{2}}{\sum_{i \in I} h_{i}+\lambda}\right]-\gamma Lsplit ​=21​[∑i∈IL​​hi​+λ(∑i∈IL​​gi​)2​+∑i∈IR​​hi​+λ(∑i∈IR​​gi​)2​−∑i∈I​hi​+λ(∑i∈I​gi​)2​]−γ
精确贪心分裂算法:
XGBoost在生成新树的过程中,最基本的操作是节点分裂。节点分裂中最重 要的环节是找到最优特征及最优切分点, 然后将叶子节点按照最优特征和最优切 分点进行分裂。选取最优特征和最优切分点的一种思路如下:首先找到所有的候 选特征及所有的候选切分点, 一一求得其 Lsplit \mathcal{L}_{\text {split }}Lsplit ​, 然后选择Lsplit\mathcal{L}_{\mathrm{split}}Lsplit​ 最大的特征及 对应切分点作为最优特征和最优切分点。我们称此种方法为精确贪心算法。该算法是一种启发式算法, 因为在节点分裂时只选择当前最优的分裂策略, 而非全局最优的分裂策略。精确贪心算法的计算过程如下所示:

基于直方图的近似算法:
精确贪心算法在选择最优特征和最优切分点时是一种十分有效的方法。它计算了所有特征、所有切分点的收益, 并从中选择了最优的, 从而保证模型能比较好地拟合了训练数据。但是当数据不能完全加载到内存时,精确贪心算法会变得 非常低效,算法在计算过程中需要不断在内存与磁盘之间进行数据交换,这是个非常耗时的过程, 并且在分布式环境中面临同样的问题。为了能够更高效地选 择最优特征及切分点, XGBoost提出一种近似算法来解决该问题。 基于直方图的近似算法的主要思想是:对某一特征寻找最优切分点时,首先对该特征的所有切分点按分位数 (如百分位) 分桶, 得到一个候选切分点集。特征的每一个切分点都可以分到对应的分桶; 然后,对每个桶计算特征统计G和H得到直方图, G为该桶内所有样本一阶特征统计g之和, H为该桶内所有样本二阶特征统计h之和; 最后,选择所有候选特征及候选切分点中对应桶的特征统计收益最大的作为最优特征及最优切分点。基于直方图的近似算法的计算过程如下所示:

  1. 对于每个特征 k=1,2,⋯,m,k=1,2, \cdots, m,k=1,2,⋯,m, 按分位数对特征 kkk 分桶 Θ,\Theta,Θ, 可得候选切分点, Sk={Sk1,Sk2,⋯,Skl}1S_{k}=\left\{S_{k 1}, S_{k 2}, \cdots, S_{k l}\right\}^{1}Sk​={Sk1​,Sk2​,⋯,Skl​}1
  2. 对于每个特征 k=1,2,⋯,m,k=1,2, \cdots, m,k=1,2,⋯,m, 有:
    Gkv←=∑j∈{j∣sk,v≥xjk>sk,v−1}gjHkv←=∑j∈{j∣sk,v≥xjk>sk,v−1}hj\begin{array}{l} G_{k v} \leftarrow=\sum_{j \in\left\{j \mid s_{k, v} \geq \mathbf{x}_{j k}>s_{k, v-1\;}\right\}} g_{j} \\ H_{k v} \leftarrow=\sum_{j \in\left\{j \mid s_{k, v} \geq \mathbf{x}_{j k}>s_{k, v-1\;}\right\}} h_{j} \end{array} Gkv​←=∑j∈{j∣sk,v​≥xjk​>sk,v−1​}​gj​Hkv​←=∑j∈{j∣sk,v​≥xjk​>sk,v−1​}​hj​​
  3. 类似精确贪心算法,依据梯度统计找到最大增益的候选切分点。
    下面用一个例子说明基于直方图的近似算法:
    假设有一个年龄特征,其特征的取值为18、19、21、31、36、37、55、57,我们需要使用近似算法找到年龄这个特征的最佳分裂点:

    近似算法实现了两种候选切分点的构建策略:全局策略和本地策略。全局策略是在树构建的初始阶段对每一个特征确定一个候选切分点的集合, 并在该树每一层的节点分裂中均采用此集合计算收益, 整个过程候选切分点集合不改变。本地策略则是在每一次节点分裂时均重新确定候选切分点。全局策略需要更细的分桶才能达到本地策略的精确度, 但全局策略在选取候选切分点集合时比本地策略更简单。在XGBoost系统中, 用户可以根据需求自由选择使用精确贪心算法、近似算法全局策略、近似算法本地策略, 算法均可通过参数进行配置。

以上是XGBoost的理论部分,下面我们对XGBoost系统进行详细的讲解:
官方文档
大佬的总结

数据准备

数据集下载地址:mushroom
数据转换
agaricus-lepiota.names 文件内容

1. Title: Mushroom Database2. Sources: (a) Mushroom records drawn from The Audubon Society Field Guide to NorthAmerican Mushrooms (1981). G. H. Lincoff (Pres.), New York: AlfredA. Knopf(b) Donor: Jeff Schlimmer (Jeffrey.Schlimmer@a.gp.cs.cmu.edu)(c) Date: 27 April 19873. Past Usage:1. Schlimmer,J.S. (1987). Concept Acquisition Through RepresentationalAdjustment (Technical Report 87-19).  Doctoral disseration, Departmentof Information and Computer Science, University of California, Irvine.--- STAGGER: asymptoted to 95% classification accuracy after reviewing1000 instances.2. Iba,W., Wogulis,J., & Langley,P. (1988).  Trading off Simplicityand Coverage in Incremental Concept Learning. In Proceedings of the 5th International Conference on Machine Learning, 73-79.Ann Arbor, Michigan: Morgan Kaufmann.  -- approximately the same results with their HILLARY algorithm    3. In the following references a set of rules (given below) werelearned for this data set which may serve as a point ofcomparison for other researchers.Duch W, Adamczak R, Grabczewski K (1996) Extraction of logical rulesfrom training data using backpropagation networks, in: Proc. of theThe 1st Online Workshop on Soft Computing, 19-30.Aug.1996, pp. 25-30,available on-line at: http://www.bioele.nuee.nagoya-u.ac.jp/wsc1/Duch W, Adamczak R, Grabczewski K, Ishikawa M, Ueda H, Extraction ofcrisp logical rules using constrained backpropagation networks -comparison of two new approaches, in: Proc. of the European Symposiumon Artificial Neural Networks (ESANN'97), Bruge, Belgium 16-18.4.1997,pp. xx-xxWlodzislaw Duch, Department of Computer Methods, Nicholas CopernicusUniversity, 87-100 Torun, Grudziadzka 5, Polande-mail: duch@phys.uni.torun.plWWW     http://www.phys.uni.torun.pl/kmk/Date: Mon, 17 Feb 1997 13:47:40 +0100From: Wlodzislaw Duch <duch@phys.uni.torun.pl>Organization: Dept. of Computer Methods, UMKI have attached a file containing logical rules for mushrooms.It should be helpful for other people since only in the last year Ihave seen about 10 papers analyzing this dataset and obtaining quitecomplex rules. We will try to contribute other results later.With best regards, Wlodek Duch________________________________________________________________Logical rules for the mushroom data sets.Logical rules given below seem to be the simplest possible for themushroom dataset and therefore should be treated as benchmark results.Disjunctive rules for poisonous mushrooms, from most generalto most specific:P_1) odor=NOT(almond.OR.anise.OR.none)120 poisonous cases missed, 98.52% accuracyP_2) spore-print-color=green48 cases missed, 99.41% accuracyP_3) odor=none.AND.stalk-surface-below-ring=scaly.AND.(stalk-color-above-ring=NOT.brown) 8 cases missed, 99.90% accuracyP_4) habitat=leaves.AND.cap-color=white100% accuracy     Rule P_4) may also beP_4') population=clustered.AND.cap_color=whiteThese rule involve 6 attributes (out of 22). Rules for ediblemushrooms are obtained as negation of the rules given above, forexample the rule:odor=(almond.OR.anise.OR.none).AND.spore-print-color=NOT.greengives 48 errors, or 99.41% accuracy on the whole dataset.Several slightly more complex variations on these rules exist,involving other attributes, such as gill_size, gill_spacing,stalk_surface_above_ring, but the rules given above are the simplestwe have found.4. Relevant Information:This data set includes descriptions of hypothetical samplescorresponding to 23 species of gilled mushrooms in the Agaricus andLepiota Family (pp. 500-525).  Each species is identified asdefinitely edible, definitely poisonous, or of unknown edibility andnot recommended.  This latter class was combined with the poisonousone.  The Guide clearly states that there is no simple rule fordetermining the edibility of a mushroom; no rule like ``leafletsthree, let it be'' for Poisonous Oak and Ivy.5. Number of Instances: 81246. Number of Attributes: 22 (all nominally valued)7. Attribute Information: (classes: edible=e, poisonous=p)1. cap-shape:                bell=b,conical=c,convex=x,flat=f,knobbed=k,sunken=s2. cap-surface:              fibrous=f,grooves=g,scaly=y,smooth=s3. cap-color:                brown=n,buff=b,cinnamon=c,gray=g,green=r,pink=p,purple=u,red=e,white=w,yellow=y4. bruises?:                 bruises=t,no=f5. odor:                     almond=a,anise=l,creosote=c,fishy=y,foul=f,musty=m,none=n,pungent=p,spicy=s6. gill-attachment:          attached=a,descending=d,free=f,notched=n7. gill-spacing:             close=c,crowded=w,distant=d8. gill-size:                broad=b,narrow=n9. gill-color:               black=k,brown=n,buff=b,chocolate=h,gray=g,green=r,orange=o,pink=p,purple=u,red=e,white=w,yellow=y10. stalk-shape:              enlarging=e,tapering=t11. stalk-root:               bulbous=b,club=c,cup=u,equal=e,rhizomorphs=z,rooted=r,missing=?12. stalk-surface-above-ring: fibrous=f,scaly=y,silky=k,smooth=s13. stalk-surface-below-ring: fibrous=f,scaly=y,silky=k,smooth=s14. stalk-color-above-ring:   brown=n,buff=b,cinnamon=c,gray=g,orange=o,pink=p,red=e,white=w,yellow=y15. stalk-color-below-ring:   brown=n,buff=b,cinnamon=c,gray=g,orange=o,pink=p,red=e,white=w,yellow=y16. veil-type:                partial=p,universal=u17. veil-color:               brown=n,orange=o,white=w,yellow=y18. ring-number:              none=n,one=o,two=t19. ring-type:                cobwebby=c,evanescent=e,flaring=f,large=l,none=n,pendant=p,sheathing=s,zone=z20. spore-print-color:        black=k,brown=n,buff=b,chocolate=h,green=r,orange=o,purple=u,white=w,yellow=y21. population:               abundant=a,clustered=c,numerous=n,scattered=s,several=v,solitary=y22. habitat:                  grasses=g,leaves=l,meadows=m,paths=p,urban=u,waste=w,woods=d8. Missing Attribute Values: 2480 of them (denoted by "?"), all forattribute #11.9. Class Distribution: --    edible: 4208 (51.8%)-- poisonous: 3916 (48.2%)--     total: 8124 instances
#!/usr/bin/python
def loadfmap( fname ):fmap = {}nmap = {}for l in open( fname ):arr = l.split()if arr[0].find('.') != -1:idx = int( arr[0].strip('.') )assert idx not in fmapfmap[ idx ] = {}ftype = arr[1].strip(':')content = arr[2]else:content = arr[0]for it in content.split(','):if it.strip() == '':continuek , v = it.split('=')fmap[ idx ][ v ] = len(nmap)nmap[ len(nmap) ] = ftype+'='+kreturn fmap, nmapdef write_nmap( fo, nmap ):for i in range( len(nmap) ):fo.write('%d\t%s\ti\n' % (i, nmap[i]) )
# start here
fmap, nmap = loadfmap( 'agaricus-lepiota.fmap' )
fo = open( 'featmap.txt', 'w' )
write_nmap( fo, nmap )
fo.close()
fo = open( 'agaricus.txt', 'w' )
for l in open( 'agaricus-lepiota.data' ):arr = l.split(',')if arr[0] == 'p':fo.write('1')else:assert arr[0] == 'e'fo.write('0')for i in range( 1,len(arr) ):fo.write( ' %d:1' % fmap[i][arr[i].strip()] )fo.write('\n')
fo.close()
#!/usr/bin/python
import sys
import random
random.seed( 10 )
k = 1
nfold = 5
fi = open( 'agaricus.txt', 'r' )
ftr = open( 'agaricus.txt'+'.train', 'w' )
fte = open( 'agaricus.txt'+'.test', 'w' )
for l in fi:if random.randint( 1 , nfold ) == k:fte.write( l )else:ftr.write( l )
fi.close()
ftr.close()
fte.close()
# XGBoost原生工具库的上手:
import xgboost as xgb  # 引入工具库
# read in data
dtrain = xgb.DMatrix('agaricus.txt.train')   # XGBoost的专属数据格式,但是也可以用dataframe或者ndarray
dtest = xgb.DMatrix('agaricus.txt.test')  # # XGBoost的专属数据格式,但是也可以用dataframe或者ndarray
# specify parameters via map
param = {'max_depth':2, 'eta':1, 'objective':'binary:logistic' }    # 设置XGB的参数,使用字典形式传入
num_round = 2     # 使用线程数
bst = xgb.train(param, dtrain, num_round)   # 训练
# make prediction
preds = bst.predict(dtest)   # 预测

运行结果:
[18:36:54] 6541x126 matrix with 143902 entries loaded from agaricus.txt.train
[18:36:54] 1583x126 matrix with 34826 entries loaded from agaricus.txt.test
[18:36:54] /workspace/src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 6 extra nodes, 0 pruned nodes, max_depth=2
[18:36:54] /workspace/src/tree/updater_prune.cc:74: tree pruning end, 1 roots, 4 extra nodes, 0 pruned nodes, max_depth=2

XGBoost的参数设置(括号内的名称为sklearn接口对应的参数名字):
推荐博客
推荐官方文档

XGBoost的参数分为三种:

  • 通用参数:(两种类型的booster,因为tree的性能比线性回归好得多,因此我们很少用线性回归。)

    • booster:使用哪个弱学习器训练,默认gbtree,可选gbtree,gblinear 或dart
    • nthread:用于运行XGBoost的并行线程数,默认为最大可用线程数
    • verbosity:打印消息的详细程度。有效值为0(静默),1(警告),2(信息),3(调试)。
    • Tree Booster的参数:
      • eta(learning_rate):learning_rate,在更新中使用步长收缩以防止过度拟合,默认= 0.3,范围:[0,1];典型值一般设置为:0.01-0.2
      • gamma(min_split_loss):默认= 0,分裂节点时,损失函数减小值只有大于等于gamma节点才分裂,gamma值越大,算法越保守,越不容易过拟合,但性能就不一定能保证,需要平衡。范围:[0,∞]
      • max_depth:默认= 6,一棵树的最大深度。增加此值将使模型更复杂,并且更可能过度拟合。范围:[0,∞]
      • min_child_weight:默认值= 1,如果新分裂的节点的样本权重和小于min_child_weight则停止分裂 。这个可以用来减少过拟合,但是也不能太高,会导致欠拟合。范围:[0,∞]
      • max_delta_step:默认= 0,允许每个叶子输出的最大增量步长。如果将该值设置为0,则表示没有约束。如果将其设置为正值,则可以帮助使更新步骤更加保守。通常不需要此参数,但是当类极度不平衡时,它可能有助于逻辑回归。将其设置为1-10的值可能有助于控制更新。范围:[0,∞]
      • subsample:默认值= 1,构建每棵树对样本的采样率,如果设置成0.5,XGBoost会随机选择一半的样本作为训练集。范围:(0,1]
      • sampling_method:默认= uniform,用于对训练实例进行采样的方法。
        • uniform:每个训练实例的选择概率均等。通常将subsample> = 0.5 设置 为良好的效果。
        • gradient_based:每个训练实例的选择概率与规则化的梯度绝对值成正比,具体来说就是g2+λh2\sqrt{g^2+\lambda h^2}g2+λh2​,subsample可以设置为低至0.1,而不会损失模型精度。
      • colsample_bytree:默认= 1,列采样率,也就是特征采样率。范围为(0,1]
      • lambda(reg_lambda):默认=1,L2正则化权重项。增加此值将使模型更加保守。
      • alpha(reg_alpha):默认= 0,权重的L1正则化项。增加此值将使模型更加保守。
      • tree_method:默认=auto,XGBoost中使用的树构建算法。
        • auto:使用启发式选择最快的方法。

          • 对于小型数据集,exact将使用精确贪婪()。
          • 对于较大的数据集,approx将选择近似算法()。它建议尝试hist,gpu_hist,用大量的数据可能更高的性能。(gpu_hist)支持。external memory外部存储器。
        • exact:精确的贪婪算法。枚举所有拆分的候选点。
        • approx:使用分位数和梯度直方图的近似贪婪算法。
        • hist:更快的直方图优化的近似贪婪算法。(LightGBM也是使用直方图算法)
        • gpu_hist:GPU hist算法的实现。
      • scale_pos_weight:控制正负权重的平衡,这对于不平衡的类别很有用。Kaggle竞赛一般设置sum(negative instances) / sum(positive instances),在类别高度不平衡的情况下,将参数设置大于0,可以加快收敛。
      • num_parallel_tree:默认=1,每次迭代期间构造的并行树的数量。此选项用于支持增强型随机森林。
      • monotone_constraints:可变单调性的约束,在某些情况下,如果有非常强烈的先验信念认为真实的关系具有一定的质量,则可以使用约束条件来提高模型的预测性能。(例如params_constrained[‘monotone_constraints’] = “(1,-1)”,(1,-1)我们告诉XGBoost对第一个预测变量施加增加的约束,对第二个预测变量施加减小的约束。)
    • Linear Booster的参数:
      • lambda(reg_lambda):默认= 0,L2正则化权重项。增加此值将使模型更加保守。归一化为训练示例数。
      • alpha(reg_alpha):默认= 0,权重的L1正则化项。增加此值将使模型更加保守。归一化为训练示例数。
      • updater:默认= shotgun。
        • shotgun:基于shotgun算法的平行坐标下降算法。使用“ hogwild”并行性,因此每次运行都产生不确定的解决方案。
        • coord_descent:普通坐标下降算法。同样是多线程的,但仍会产生确定性的解决方案。
      • feature_selector:默认= cyclic。特征选择和排序方法
        • cyclic:通过每次循环一个特征来实现的。
        • shuffle:类似于cyclic,但是在每次更新之前都有随机的特征变换。
        • random:一个随机(有放回)特征选择器。
        • greedy:选择梯度最大的特征。(贪婪选择)
        • thrifty:近似贪婪特征选择(近似于greedy)
      • top_k:要选择的最重要特征数(在greedy和thrifty内)
  • 任务参数(这个参数用来控制理想的优化目标和每一步结果的度量方法。)

    • objective:默认=reg:squarederror,表示最小平方误差。

      • reg:squarederror,最小平方误差。
      • reg:squaredlogerror,对数平方损失。12[log(pred+1)−log(label+1)]2\frac{1}{2}[log(pred+1)-log(label+1)]^221​[log(pred+1)−log(label+1)]2
      • reg:logistic,逻辑回归
      • reg:pseudohubererror,使用伪Huber损失进行回归,这是绝对损失的两倍可微选择。
      • binary:logistic,二元分类的逻辑回归,输出概率。
      • binary:logitraw:用于二进制分类的逻辑回归,逻辑转换之前的输出得分。
      • binary:hinge:二进制分类的铰链损失。这使预测为0或1,而不是产生概率。(SVM就是铰链损失函数)
      • count:poisson –计数数据的泊松回归,泊松分布的输出平均值。
      • survival:cox:针对正确的生存时间数据进行Cox回归(负值被视为正确的生存时间)。
      • survival:aft:用于检查生存时间数据的加速故障时间模型。
      • aft_loss_distribution:survival:aft和aft-nloglik度量标准使用的概率密度函数。
      • multi:softmax:设置XGBoost以使用softmax目标进行多类分类,还需要设置num_class(类数)
      • multi:softprob:与softmax相同,但输出向量,可以进一步重整为矩阵。结果包含属于每个类别的每个数据点的预测概率。
      • rank:pairwise:使用LambdaMART进行成对排名,从而使成对损失最小化。
      • rank:ndcg:使用LambdaMART进行列表式排名,使标准化折让累积收益(NDCG)最大化。
      • rank:map:使用LambdaMART进行列表平均排名,使平均平均精度(MAP)最大化。
      • reg:gamma:使用对数链接进行伽马回归。输出是伽马分布的平均值。
      • reg:tweedie:使用对数链接进行Tweedie回归。
      • 自定义损失函数和评价指标:https://xgboost.readthedocs.io/en/latest/tutorials/custom_metric_obj.html
    • eval_metric:验证数据的评估指标,将根据目标分配默认指标(回归均方根,分类误差,排名的平均平均精度),用户可以添加多个评估指标
      • rmse,均方根误差; rmsle:均方根对数误差; mae:平均绝对误差;mphe:平均伪Huber错误;logloss:负对数似然; error:二进制分类错误率;
      • merror:多类分类错误率; mlogloss:多类logloss; auc:曲线下面积; aucpr:PR曲线下的面积;ndcg:归一化累计折扣;map:平均精度;
    • seed :随机数种子,[默认= 0]。
  • 命令行参数(这里不说了,因为很少用命令行控制台版本)

XGBoost的调参说明:
参数调优的一般步骤

    1. 确定学习速率和提升参数调优的初始值
    1. max_depth 和 min_child_weight 参数调优
    1. gamma参数调优
    1. subsample 和 colsample_bytree 参数优
    1. 正则化参数alpha调优
    1. 降低学习速率和使用更多的决策树
      XGBoost详细攻略:
      具体的api
      推荐github

安装XGBoost:

pip install xgboost

数据接口(XGBoost可处理的数据格式DMatrix)

# 1.LibSVM文本格式文件
dtrain = xgb.DMatrix('train.svm.txt')
dtest = xgb.DMatrix('test.svm.buffer')
# 2.CSV文件(不能含类别文本变量,如果存在文本变量请做特征处理如one-hot)
dtrain = xgb.DMatrix('train.csv?format=csv&label_column=0')
dtest = xgb.DMatrix('test.csv?format=csv&label_column=0')
# 3.NumPy数组
data = np.random.rand(5, 10)  # 5 entities, each contains 10 features
label = np.random.randint(2, size=5)  # binary target
dtrain = xgb.DMatrix(data, label=label)
# 4.scipy.sparse数组
csr = scipy.sparse.csr_matrix((dat, (row, col)))
dtrain = xgb.DMatrix(csr)
# pandas数据框dataframe
data = pandas.DataFrame(np.arange(12).reshape((4,3)), columns=['a', 'b', 'c'])
label = pandas.DataFrame(np.random.randint(2, size=4))
dtrain = xgb.DMatrix(data, label=label)

笔者推荐:先保存到XGBoost二进制文件中将使加载速度更快,然后再加载进来

# 1.保存DMatrix到XGBoost二进制文件中
dtrain = xgb.DMatrix('train.svm.txt')
dtrain.save_binary('train.buffer')
# 2. 缺少的值可以用DMatrix构造函数中的默认值替换:
dtrain = xgb.DMatrix(data, label=label, missing=-999.0)
# 3.可以在需要时设置权重:
w = np.random.rand(5, 1)
dtrain = xgb.DMatrix(data, label=label, missing=-999.0, weight=w)

参数的设置方式:

import pandas as pd
# 加载并处理数据
df_wine = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data',header=None)
df_wine.columns = ['Class label', 'Alcohol','Malic acid', 'Ash','Alcalinity of ash','Magnesium', 'Total phenols','Flavanoids', 'Nonflavanoid phenols','Proanthocyanins','Color intensity', 'Hue','OD280/OD315 of diluted wines','Proline']
df_wine = df_wine[df_wine['Class label'] != 1]  # drop 1 class
y = df_wine['Class label'].values
X = df_wine[['Alcohol','OD280/OD315 of diluted wines']].values
from sklearn.model_selection import train_test_split  # 切分训练集与测试集
from sklearn.preprocessing import LabelEncoder   # 标签化分类变量
le = LabelEncoder()
y = le.fit_transform(y)
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=1,stratify=y)
dtrain = xgb.DMatrix(X_train, label=y_train)
dtest = xgb.DMatrix(X_test)
# 1.Booster 参数
params = {'booster': 'gbtree','objective': 'multi:softmax',  # 多分类的问题'num_class': 10,               # 类别数,与 multisoftmax 并用'gamma': 0.1,                  # 用于控制是否后剪枝的参数,越大越保守,一般0.1、0.2这样子。'max_depth': 12,               # 构建树的深度,越大越容易过拟合'lambda': 2,                   # 控制模型复杂度的权重值的L2正则化项参数,参数越大,模型越不容易过拟合。'subsample': 0.7,              # 随机采样训练样本'colsample_bytree': 0.7,       # 生成树时进行的列采样'min_child_weight': 3,'silent': 1,                   # 设置成1则没有运行信息输出,最好是设置为0.'eta': 0.007,                  # 如同学习率'seed': 1000,'nthread': 4,                  # cpu 线程数'eval_metric':'auc'
}
plst = params.items()
# evallist = [(dtest, 'eval'), (dtrain, 'train')]   # 指定验证集

训练:

# 2.训练
num_round = 10
bst = xgb.train( plst, dtrain, num_round)
#bst = xgb.train( plst, dtrain, num_round, evallist )

保存模型:

# 3.保存模型
bst.save_model('0001.model')
# dump model
bst.dump_model('dump.raw.txt')
# dump model with feature map
#bst.dump_model('dump.raw.txt', 'featmap.txt')

加载保存的模型:

# 4.加载保存的模型:
bst = xgb.Booster({'nthread': 4})  # init model
bst.load_model('0001.model')  # load data

设置早停机制:

# 5.也可以设置早停机制(需要设置验证集)
train(..., evals=evals, early_stopping_rounds=10)

预测:

# 6.预测
ypred = bst.predict(dtest)

绘制重要性特征图:

# 1.绘制重要性
xgb.plot_importance(bst)
# 2.绘制输出树
#xgb.plot_tree(bst, num_trees=2)
# 3.使用xgboost.to_graphviz()将目标树转换为graphviz
#xgb.to_graphviz(bst, num_trees=2)

Xgboost算法案例

分类案例

from sklearn.datasets import load_iris
import xgboost as xgb
from xgboost import plot_importance
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score   # 准确率
# 加载样本数据集
iris = load_iris()
X,y = iris.data,iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1234565) # 数据集分割# 算法参数
params = {'booster': 'gbtree','objective': 'multi:softmax','num_class': 3,'gamma': 0.1,'max_depth': 6,'lambda': 2,'subsample': 0.7,'colsample_bytree': 0.75,'min_child_weight': 3,'silent': 0,'eta': 0.1,'seed': 1,'nthread': 4,
}plst = params.items()dtrain = xgb.DMatrix(X_train, y_train) # 生成数据集格式
num_rounds = 500
model = xgb.train(plst, dtrain, num_rounds) # xgboost模型训练# 对测试集进行预测
dtest = xgb.DMatrix(X_test)
y_pred = model.predict(dtest)# 计算准确率
accuracy = accuracy_score(y_test,y_pred)
print("accuarcy: %.2f%%" % (accuracy*100.0))# 显示重要特征
plot_importance(model)
plt.show()

回归案例

import xgboost as xgb
from xgboost import plot_importance
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_boston
from sklearn.metrics import mean_squared_error# 加载数据集
boston = load_boston()
X,y = boston.data,boston.target# XGBoost训练过程
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)params = {'booster': 'gbtree','objective': 'reg:squarederror','gamma': 0.1,'max_depth': 5,'lambda': 3,'subsample': 0.7,'colsample_bytree': 0.7,'min_child_weight': 3,'silent': 1,'eta': 0.1,'seed': 1000,'nthread': 4,
}dtrain = xgb.DMatrix(X_train, y_train)
num_rounds = 300
plst = params.items()
model = xgb.train(plst, dtrain, num_rounds)# 对测试集进行预测
dtest = xgb.DMatrix(X_test)
ans = model.predict(dtest)# 显示重要特征
plot_importance(model)
plt.show()

XGBoost调参(结合sklearn网格搜索)

import xgboost as xgb
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import roc_auc_scoreiris = load_iris()
X,y = iris.data,iris.target
col = iris.target_names
train_x, valid_x, train_y, valid_y = train_test_split(X, y, test_size=0.3, random_state=1)   # 分训练集和验证集
parameters = {'max_depth': [5, 10, 15, 20, 25],'learning_rate': [0.01, 0.02, 0.05, 0.1, 0.15],'n_estimators': [500, 1000, 2000, 3000, 5000],'min_child_weight': [0, 2, 5, 10, 20],'max_delta_step': [0, 0.2, 0.6, 1, 2],'subsample': [0.6, 0.7, 0.8, 0.85, 0.95],'colsample_bytree': [0.5, 0.6, 0.7, 0.8, 0.9],'reg_alpha': [0, 0.25, 0.5, 0.75, 1],'reg_lambda': [0.2, 0.4, 0.6, 0.8, 1],'scale_pos_weight': [0.2, 0.4, 0.6, 0.8, 1]}xlf = xgb.XGBClassifier(max_depth=10,learning_rate=0.01,n_estimators=2000,silent=True,objective='multi:softmax',num_class=3 ,          nthread=-1,gamma=0,min_child_weight=1,max_delta_step=0,subsample=0.85,colsample_bytree=0.7,colsample_bylevel=1,reg_alpha=0,reg_lambda=1,scale_pos_weight=1,seed=0,missing=None)gs = GridSearchCV(xlf, param_grid=parameters, scoring='accuracy', cv=3)
gs.fit(train_x, train_y)print("Best score: %0.3f" % gs.best_score_)
print("Best parameters set: %s" % gs.best_params_ )

Best score: 0.933
Best parameters set: {‘max_depth’: 5}

LightGBM算法

LightGBM也是像XGBoost一样,是一类集成算法,他跟XGBoost总体来说是一样的,算法本质上与Xgboost没有出入,只是在XGBoost的基础上进行了优化,因此就不对原理进行重复介绍,在这里我们来看看几种算法的差别:

  • 优化速度和内存使用

    • 降低了计算每个分割增益的成本。
    • 使用直方图减法进一步提高速度。
    • 减少内存使用。
    • 减少并行学习的计算成本。
  • 稀疏优化
    • 用离散的bin替换连续的值。如果#bins较小,则可以使用较小的数据类型(例如uint8_t)来存储训练数据 。
    • 无需存储其他信息即可对特征数值进行预排序 。
  • 精度优化
    • 使用叶子数为导向的决策树建立算法而不是树的深度导向。
    • 分类特征的编码方式的优化
    • 通信网络的优化
    • 并行学习的优化
    • GPU支持

LightGBM的优点:

1)更快的训练效率

2)低内存使用

3)更高的准确率

4)支持并行化学习

5)可以处理大规模数据

1.速度对比:

2.准确率对比:

3.内存使用量对比:

LightGBM参数说明:
推荐文档1:https://lightgbm.apachecn.org/#/docs/6
推荐文档2:https://lightgbm.readthedocs.io/en/latest/Parameters.html

1.核心参数:(括号内名称是别名)

  • objective(objective,app ,application):默认regression,用于设置损失函数

    • 回归问题:

      • L2损失:regression(regression_l2,l2,mean_squared_error,mse,l2_root,root_mean_squared_error,rmse)
      • L1损失:regression_l1(l1, mean_absolute_error, mae)
      • 其他损失:huber,fair,poisson,quantile,mape,gamma,tweedie
    • 二分类问题:二进制对数损失分类(或逻辑回归):binary
    • 多类别分类:
      • softmax目标函数: multiclass(softmax)
      • One-vs-All 目标函数:multiclassova(multiclass_ova,ova,ovr)
    • 交叉熵:
      • 用于交叉熵的目标函数(具有可选的线性权重):cross_entropy(xentropy)
      • 交叉熵的替代参数化:cross_entropy_lambda(xentlambda)
  • boosting :默认gbdt,设置提升类型,选项有gbdt,rf,dart,goss,别名:boosting_type,boost
    • gbdt(gbrt):传统的梯度提升决策树
    • rf(random_forest):随机森林
    • dart:多个加性回归树的DROPOUT方法 Dropouts meet Multiple Additive Regression Trees,参见:https://arxiv.org/abs/1505.01866
    • goss:基于梯度的单边采样 Gradient-based One-Side Sampling
  • data(train,train_data,train_data_file,data_filename):用于训练的数据或数据file
  • valid (test,valid_data,valid_data_file,test_data,test_data_file,valid_filenames):验证/测试数据的路径,LightGBM将输出这些数据的指标
  • num_iterations:默认=100,类型= INT
  • n_estimators:提升迭代次数,LightGBM构造用于多类分类问题的树num_class * num_iterations
  • learning_rate(shrinkage_rate,eta) :收缩率,默认=0.1
  • num_leaves(num_leaf,max_leaves,max_leaf) :默认=31,一棵树上的最大叶子数
  • tree_learner (tree,tree_type,tree_learner_type):默认=serial,可选:serial,feature,data,voting
    • serial:单台机器的 tree learner
    • feature:特征并行的 tree learner
    • data:数据并行的 tree learner
    • voting:投票并行的 tree learner
  • num_threads(num_thread, nthread):LightGBM 的线程数,为了更快的速度, 将此设置为真正的 CPU 内核数, 而不是线程的数量 (大多数 CPU 使用超线程来使每个 CPU 内核生成 2 个线程),当你的数据集小的时候不要将它设置的过大 (比如, 当数据集有 10,000 行时不要使用 64 线程),对于并行学习, 不应该使用全部的 CPU 内核, 因为这会导致网络性能不佳。
  • device(device_type):默认cpu,为树学习选择设备, 你可以使用 GPU 来获得更快的学习速度,可选cpu, gpu。
  • seed (random_seed,random_state):与其他种子相比,该种子具有较低的优先级,这意味着如果您明确设置其他种子,它将被覆盖。

2.用于控制模型学习过程的参数:

  • max_depth:限制树模型的最大深度. 这可以在 #data 小的情况下防止过拟合. 树仍然可以通过 leaf-wise 生长。
  • min_data_in_leaf: 默认=20,一个叶子上数据的最小数量. 可以用来处理过拟合。
  • min_sum_hessian_in_leaf(min_sum_hessian_per_leaf, min_sum_hessian, min_hessian):默认=1e-3,一个叶子上的最小 hessian 和. 类似于 min_data_in_leaf, 可以用来处理过拟合.
  • feature_fraction:default=1.0,如果 feature_fraction 小于 1.0, LightGBM 将会在每次迭代中随机选择部分特征. 例如, 如果设置为 0.8, 将会在每棵树训练之前选择 80% 的特征,可以用来加速训练,可以用来处理过拟合。
  • feature_fraction_seed:默认=2,feature_fraction 的随机数种子。
  • bagging_fraction(sub_row, subsample):默认=1,不进行重采样的情况下随机选择部分数据
  • bagging_freq(subsample_freq):bagging 的频率, 0 意味着禁用 bagging. k 意味着每 k 次迭代执行bagging
  • bagging_seed(bagging_fraction_seed) :默认=3,bagging 随机数种子。
  • early_stopping_round(early_stopping_rounds, early_stopping):默认=0,如果一个验证集的度量在 early_stopping_round 循环中没有提升, 将停止训练
  • lambda_l1(reg_alpha):L1正则化系数
  • lambda_l2(reg_lambda):L2正则化系数
  • min_split_gain(min_gain_to_split):执行切分的最小增益,默认=0.
  • cat_smooth:默认=10,用于分类特征,可以降低噪声在分类特征中的影响, 尤其是对数据很少的类别

3.度量参数:

  • metric:default={l2 for regression}, {binary_logloss for binary classification}, {ndcg for lambdarank}, type=multi-enum, options=l1, l2, ndcg, auc, binary_logloss, binary_error …

    • l1, absolute loss, alias=mean_absolute_error, mae
    • l2, square loss, alias=mean_squared_error, mse
    • l2_root, root square loss, alias=root_mean_squared_error, rmse
    • quantile, Quantile regression
    • huber, Huber loss
    • fair, Fair loss
    • poisson, Poisson regression
    • ndcg, NDCG
    • map, MAP
    • auc, AUC
    • binary_logloss, log loss
    • binary_error, 样本: 0 的正确分类, 1 错误分类
    • multi_logloss, mulit-class 损失日志分类
    • multi_error, error rate for mulit-class 出错率分类
    • xentropy, cross-entropy (与可选的线性权重), alias=cross_entropy
    • xentlambda, “intensity-weighted” 交叉熵, alias=cross_entropy_lambda
    • kldiv, Kullback-Leibler divergence, alias=kullback_leibler
    • 支持多指标, 使用 , 分隔
  • train_metric(training_metric, is_training_metric):默认=False,如果你需要输出训练的度量结果则设置 true

4.GPU 参数:

  • gpu_device_id:default为-1, 这个default意味着选定平台上的设备。

LightGBM与网格搜索结合调参:
参考代码:https://blog.csdn.net/u012735708/article/details/83749703

import lightgbm as lgb
from sklearn import metrics
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_splitcanceData=load_breast_cancer()
X=canceData.data
y=canceData.target
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0,test_size=0.2)### 数据转换
print('数据转换')
lgb_train = lgb.Dataset(X_train, y_train, free_raw_data=False)
lgb_eval = lgb.Dataset(X_test, y_test, reference=lgb_train,free_raw_data=False)### 设置初始参数--不含交叉验证参数
print('设置参数')
params = {'boosting_type': 'gbdt','objective': 'binary','metric': 'auc','nthread':4,'learning_rate':0.1}### 交叉验证(调参)
print('交叉验证')
max_auc = float('0')
best_params = {}# 准确率
print("调参1:提高准确率")
for num_leaves in range(5,100,5):for max_depth in range(3,8,1):params['num_leaves'] = num_leavesparams['max_depth'] = max_depthcv_results = lgb.cv(params,lgb_train,seed=1,nfold=5,metrics=['auc'],early_stopping_rounds=10,verbose_eval=True)mean_auc = pd.Series(cv_results['auc-mean']).max()boost_rounds = pd.Series(cv_results['auc-mean']).idxmax()if mean_auc >= max_auc:max_auc = mean_aucbest_params['num_leaves'] = num_leavesbest_params['max_depth'] = max_depth
if 'num_leaves' and 'max_depth' in best_params.keys():          params['num_leaves'] = best_params['num_leaves']params['max_depth'] = best_params['max_depth']# 过拟合
print("调参2:降低过拟合")
for max_bin in range(5,256,10):for min_data_in_leaf in range(1,102,10):params['max_bin'] = max_binparams['min_data_in_leaf'] = min_data_in_leafcv_results = lgb.cv(params,lgb_train,seed=1,nfold=5,metrics=['auc'],early_stopping_rounds=10,verbose_eval=True)mean_auc = pd.Series(cv_results['auc-mean']).max()boost_rounds = pd.Series(cv_results['auc-mean']).idxmax()if mean_auc >= max_auc:max_auc = mean_aucbest_params['max_bin']= max_binbest_params['min_data_in_leaf'] = min_data_in_leaf
if 'max_bin' and 'min_data_in_leaf' in best_params.keys():params['min_data_in_leaf'] = best_params['min_data_in_leaf']params['max_bin'] = best_params['max_bin']print("调参3:降低过拟合")
for feature_fraction in [0.6,0.7,0.8,0.9,1.0]:for bagging_fraction in [0.6,0.7,0.8,0.9,1.0]:for bagging_freq in range(0,50,5):params['feature_fraction'] = feature_fractionparams['bagging_fraction'] = bagging_fractionparams['bagging_freq'] = bagging_freqcv_results = lgb.cv(params,lgb_train,seed=1,nfold=5,metrics=['auc'],early_stopping_rounds=10,verbose_eval=True)mean_auc = pd.Series(cv_results['auc-mean']).max()boost_rounds = pd.Series(cv_results['auc-mean']).idxmax()if mean_auc >= max_auc:max_auc=mean_aucbest_params['feature_fraction'] = feature_fractionbest_params['bagging_fraction'] = bagging_fractionbest_params['bagging_freq'] = bagging_freqif 'feature_fraction' and 'bagging_fraction' and 'bagging_freq' in best_params.keys():params['feature_fraction'] = best_params['feature_fraction']params['bagging_fraction'] = best_params['bagging_fraction']params['bagging_freq'] = best_params['bagging_freq']print("调参4:降低过拟合")
for lambda_l1 in [1e-5,1e-3,1e-1,0.0,0.1,0.3,0.5,0.7,0.9,1.0]:for lambda_l2 in [1e-5,1e-3,1e-1,0.0,0.1,0.4,0.6,0.7,0.9,1.0]:params['lambda_l1'] = lambda_l1params['lambda_l2'] = lambda_l2cv_results = lgb.cv(params,lgb_train,seed=1,nfold=5,metrics=['auc'],early_stopping_rounds=10,verbose_eval=True)mean_auc = pd.Series(cv_results['auc-mean']).max()boost_rounds = pd.Series(cv_results['auc-mean']).idxmax()if mean_auc >= max_auc:max_auc=mean_aucbest_params['lambda_l1'] = lambda_l1best_params['lambda_l2'] = lambda_l2
if 'lambda_l1' and 'lambda_l2' in best_params.keys():params['lambda_l1'] = best_params['lambda_l1']params['lambda_l2'] = best_params['lambda_l2']print("调参5:降低过拟合2")
for min_split_gain in [0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]:params['min_split_gain'] = min_split_gaincv_results = lgb.cv(params,lgb_train,seed=1,nfold=5,metrics=['auc'],early_stopping_rounds=10,verbose_eval=True)mean_auc = pd.Series(cv_results['auc-mean']).max()boost_rounds = pd.Series(cv_results['auc-mean']).idxmax()if mean_auc >= max_auc:max_auc=mean_aucbest_params['min_split_gain'] = min_split_gain
if 'min_split_gain' in best_params.keys():params['min_split_gain'] = best_params['min_split_gain']print(best_params)

运行结果
{‘bagging_fraction’: 0.7,
‘bagging_freq’: 30,
‘feature_fraction’: 0.8,
‘lambda_l1’: 0.1,
‘lambda_l2’: 0.0,
‘max_bin’: 255,
‘max_depth’: 4,
‘min_data_in_leaf’: 81,
‘min_split_gain’: 0.1,
‘num_leaves’: 10}

结束语

本章中,我们主要探讨了基于Boosting方式的集成方法,其中主要讲解了基于错误率驱动的Adaboost,基于残差改进的提升树,基于梯度提升的GBDT,基于泰勒二阶近似的Xgboost以及LightGBM。在实际的比赛或者工程中,基于Boosting的集成学习方式是非常有效且应用非常广泛的。更多的学习有待读者更深入阅读文献,包括原作者论文以及论文复现等。下一章我们即将探讨另一种集成学习方式:Stacking集成学习方式,这种集成方式虽然没有Boosting应用广泛,但是在比赛中或许能让你的模型更加出众。

Datawhale集成学习笔记:XGBOOST算法相关推荐

  1. Datawhale集成学习:Stacking 算法与实战

    前言 Stacking核心思想 stacking严格来说并不是一种算法,而是精美而又复杂的,对模型集成的一种策略. Stacking集成算法可以理解为一个两层的集成,第一层含有多个基础分类器,把预测的 ...

  2. 机器学习集成学习进阶Xgboost算法案例分析

    目录 1 xgboost算法api介绍 1.1 xgboost的安装 2 xgboost参数介绍 2.1 通用参数(general parameters) 2.2 Booster 参数(booster ...

  3. SKlearn学习笔记——XGBoost

    SKlearn学习笔记--XGBoost 1. 概述 1.1 xgboost库与XGB的sklearn API 1.2 XGBoost的三大板块 2. 梯度提升树 2.1 提升集成算法:重要参数 n_ ...

  4. 【组队学习】【23期】Datawhale集成学习(上)

    集成学习(上) 开源内容:https://github.com/datawhalechina/team-learning-data-mining/tree/master/IntegratedLearn ...

  5. 04 集成学习 - Boosting - AdaBoost算法构建

    03 集成学习 - Boosting - AdaBoost算法原理 十.AdaBoost算法构建 上一章最后说明了每个基模型的权值α是如何求得的,于是我就可以对模型进行更新操作了. 构建过程一 1.假 ...

  6. 集成学习、Bagging算法、Bagging+Pasting、随机森林、极端随机树集成(Extra-trees)、特征重要度、包外评估

    集成学习.Bagging算法.Bagging+Pasting.随机森林.极端随机树集成(Extra-trees).特征重要度.包外评估 目录

  7. EL之AdaBoost:集成学习之AdaBoost算法的简介、应用、经典案例之详细攻略

    EL之AdaBoost:集成学习之AdaBoost算法的简介.应用.经典案例之详细攻略 目录 AdaBoost算法的简介 1.理解AdaBoost算法 1.1.从前向逐步递增角度来看理解AdaBoos ...

  8. Jenkins持续集成学习笔记(2020.11.22)

    Jenkins持续集成学习笔记(2020.11.22) 前言: (官网) 以前很久学习过Jenkins持续集成进行快速部署项目进行测试, 最近换工作了, 发现新公司有用到, 现在来复习一下 官网介绍: ...

  9. 【统计学习方法】学习笔记——EM算法及其推广

    统计学习方法学习笔记--EM算法及其推广 1. EM算法的引入 1.1 EM算法 1.2 EM算法的导出 1.3 EM算法在非监督学习中的应用 2. EM算法的收敛性 3. EM算法在高斯混合模型学习 ...

最新文章

  1. rref--计算行阶梯矩阵
  2. python序列化模块struct_python的struct模块
  3. 2019年度年中回顾总结_我的2019年回顾和我的2020年目标(包括数量和收入)
  4. 获取硬盘总容量,柱面数,磁道数,扇区数
  5. 64位Windows2003 Enterprise sp2 上64位Oracle10.2.0.1升级到Oracle10.2.0.3具体步骤
  6. 《深入浅出DPDK》读书笔记(十二):DPDK虚拟化技术篇(半虚拟化Virtio)
  7. flask导入flask-sqlalchemy的一个问题记录
  8. 「人物特写」国产手机操作系统突围任重而道远,创新才是关键
  9. linux 文件句柄 sock,linux socket句柄
  10. 通用快速检测邮件故障思路方法(二)
  11. winformlabel自动换行
  12. JavaWeb SSM酒店信息管理系统
  13. dw做html电邮,DreamWeaver中表单的使用和电子邮件表单的制作
  14. 数字信号与模拟信号的区别是什么?
  15. Selenium PO模式实现
  16. vuex中strict严格模式
  17. macbook pro 700自己换SSD 开启AHC
  18. 一文了解什么是财务RPA机器人
  19. 嵌入式linux s5pv210,嵌入式Linux软硬件开发详解 基于S5PV210处理器 P
  20. 计算机专业校企合作的论文,【计算机专业论文】计算机专业校企合作教学模式2篇(共3673字)...

热门文章

  1. 对可口可乐瓶进行图像识别
  2. 你为何没有成为领导者
  3. MBR分区的恢复 - 数据恢复
  4. @Value(${}) 与@Value(#{}) 区别
  5. 实时分析数据库 Druid,Mark 一下
  6. 教育云盘在数字校园中的应用
  7. Chef 安装教程【系列教程一】
  8. 2021春哈工大计算机系统大作业
  9. 前端面试题汇总 - 基础
  10. ODCC开放数据中心峰会即将召开 十道“技术大餐”提前揭秘