从CART到Xgboost - 原理及代码实践

CART (Classification and Regression Truee)

CART,即分类回归树。顾名思义,CART既可以用于分类任务,又可以用于回归任务.决策树的建模思想非常简单,将特征空间划分位互不相交的子空间,也就是将样本进行分组;然后位每一组样本分配一个预测值。在预测阶段,对一个新来的样本,位样本找到分组,然后给出预测值。

  • 分类任务:预测目标是离散值,分类树采用Gini值、entropy、information gain作为节点分裂的依据。采用叶子节点里概率最大的类别作为当前节点的预测类别
  • 回归任务: 预测目标是连续值,采用均方误差MSE作为节点分类的依据。则采用叶子节点的均值作为预测值

分类树和回归树的生成步骤主要有三步:

  1. 特征选择
  2. 树的生成
  3. 树的剪枝

分类树

样本集合 D D D的基尼指数 (值越大,不确定性越大):

G i n i ( D ) = 1 − ∑ k = 1 K ( ∣ C k ∣ ∣ D ∣ ) 2 Gini(D) = 1 - \sum_{k=1}^K (\frac{|C_k|}{|D|})^2 Gini(D)=1k=1K(DCk)2

其中, C k C_k Ck是属于第 k k k类的子集.
假定现在将样本集合 D D D按照最优切分特征 x j x_j xj进行划分,最优切分特征值为 s s s,划分为 x j > s x_j > s xj>s x j < s x_j < s xj<s两部分 D 1 D_1 D1, D 2 D_2 D2。计算划分之后的基尼系数:
G i n i ( D , x j ) = ∣ D 1 ∣ ∣ D ∣ G i n i ( D 1 ) + D 2 D G i n i ( D 2 ) Gini(D, x_j) = \frac{|D_1|}{|D|}Gini(D_1) + \frac{D_2}{D}Gini(D_2) Gini(D,xj)=DD1Gini(D1)+DD2Gini(D2)
对于每一个结点,遍历所有的特征和特征值,找到最小的 G i n i ( D , A ) Gini(D,A) Gini(D,A). 然后分治递归知道满足终止条件 (例如误差小于某阈值、样本个数小于某阈值、没有更多特征等)

回归树

回归树的预测值:
f ( x ) = ∑ m = 1 M I ( x ∈ R m ) f(x) = \sum_{m=1}^MI(x \in R_m) f(x)=m=1MI(xRm)
即输入空间划分为 M M M个单元, R 1 , . . . , R M R_1, ..., R_M R1,...,RM, 单元 R M R_M RM对应的输出为 c m c_m cm I I I是指示函数. 输出 c m c_m cm I ( x ∈ R m ) I(x \in R_m) I(xRm)输出的均值 :
c m = a v e ( y i ∣ x i ∈ R m ) c_m = ave(y_i|x_i \in R_m) cm=ave(yixiRm)

假定现在将样本集合 D D D按照最优切分特征 x j x_j xj进行划分,最优切分特征值为 s s s, 输入空间被划分为两部分:

R a ( j , s ) = { x ∣ x j ≤ s } R^a(j, s) = \{x|x^{j} \leq s \} Ra(j,s)={xxjs} R b ( j , s ) = { x ∣ x j > s } R^b(j, s) = \{x|x^{j} > s \} Rb(j,s)={xxj>s}

每个被划分的空间的输出是 c a c^a ca c b c^b cb。因此我们的优化目标是:
m i n j , s [ ∑ x i ∈ R a ( j , s ) ( y i − c a ) 2 + ∑ x i ∈ R b ( j , s ) ( y i − c b ) 2 ] \underset{j,s}{min}[\sum_{x_i \in R^a(j,s)} (y_i-c^a)^2 + \sum_{x_i \in R_b(j, s)} (y_i - c^b)^2 ] j,smin[xiRa(j,s)(yica)2+xiRb(j,s)(yicb)2]

遍历所有的特征 x j x_j xj和特征切分点 s s s。找到满足上式最优的 x j , s x_j, s xj,s。之后分治递归直到满足终止条件 (例如误差小于某阈值、样本个数小于某阈值、没有更多特征等)

树的剪枝

首先在生成完整的决策树之后,获取该决策树的所有子树序列。对于任意的一个子树都可以用如下方式计算其代价函数:
J λ ( T ) = J ( T ) + λ ∣ T ∣ J_{\lambda}(T) = J(T) + \lambda|T| Jλ(T)=J(T)+λT

式中的 T T T就是目标子树, J ( T ) J(T) J(T)是对训练数据的预测误差(平方误差或者基尼系数), ∣ T ∣ |T| T为子树的叶结点个数, λ \lambda λ 则是正则项系数。利用代价函数进行剪枝的具体过程如下:

  1. 首先对完整的生成树 T 0 T_0 T0进行剪枝,对其中任意一个内部结点 t t t都有:
    • t t t为根节点的子树(不剪枝)的代价函数为 J λ ( T t ) = J ( T t ) + λ ∣ T t ∣ J_{\lambda}(T_t) = J(T_t) + \lambda|T_t| Jλ(Tt)=J(Tt)+λTt
    • t t t为单节点的子树(不剪枝)的代价函数为 J λ ( t ) = J ( T ) + λ J_{\lambda}(t) = J(T) + \lambda Jλ(t)=J(T)+λ
  2. 随着 λ \lambda λ不断增大,一定有 J λ ( T t ) = J λ ( t ) J_{\lambda}(T_t) = J_{\lambda}(t) Jλ(Tt)=Jλ(t), 此时 λ = J ( t ) − J ( T t ) ∣ T t ∣ − 1 \lambda=\frac{J(t)-J(T_t)}{|T_t|-1} λ=Tt1J(t)J(Tt). 两种情况下代价函数值相等,而 t t t T t T_t Tt节点要少,复杂度更低,相应的泛化能力越强,所以此时对 T t T_t Tt进行剪枝
  3. 由上,对完全生成树 T 0 T_0 T0 的每一个中间结点都计算出这个 λ \lambda λ 值,选取该值最小的结点进行剪枝,得到一个子树 T 1 T_1 T1 ,并将该 值设为 λ 1 \lambda_1 λ1 。对该子树递归的使用上述步骤,直至剪枝至只剩根结点。此时,就有了子树序列 { T 0 , T 1 , . . . , T n } \{ T_0, T_1,...,T_n \} {T0,T1,...,Tn} 以及参数序列 { λ 0 , λ 1 , . . . , λ n } \{ \lambda_0, \lambda_1,...,\lambda_n \} {λ0,λ1,...,λn} 。此时,利用独立的一个验证用数据集,对序列中的所有子树进行测试,计算其平方误差或者基尼系数。取误差最小的子树为最优决策树,对应的参数值也就是最优参数值。至此CART的剪枝完成

XGboost (Extreme Gradient Boosting)

原文地址:https://arxiv.org/pdf/1603.02754.pdf

XGBoost是基于决策树的集成机器学习算法, 以梯度提升(Gradient Boost)为框架。
XGBoost是由由GBDT发展而来,同样是利用加法模型与前向分步算法实现学习的优化过程,但与GBDT是有区别的。主要区别包括以下几点:

  • 目标函数:XGBoost的损失函数添加了正则化项,使用正则用以控制模型的复杂度,正则项里包含了树的叶子节点个数、每个叶子节点权重(叶结点的socre值)的平方和。
  • 优化方法:GBDT在优化时只使用了一阶导数信息,XGBoost在优化时使用了一、二介导数信息。
  • 缺失值处理:XBGoost对缺失值进行了处理,通过学习模型自动选择最优的缺失值默认切分方向。
  • 防止过拟合: XGBoost除了增加了正则项来防止过拟合,还支持行列采样的方式来防止过拟合
  • 并行计算:Block存储可以并行计算等

XGboost数学原理

Xgboost使用 CART 作为基学习器,也可以使用线性分类器作为基学习器。以CART作为基学习器时,其决策规则和决策时时一样的,但CART的每个节点都具有一个权重,也就是叶节点的得分或者时预测值。

Regularized Learning Objective

给定数据集 D = { ( x i , y i ) } , ( ∣ D ∣ = n , x i ∈ R m , y i ∈ R ) D=\{(x_i, y_i)\}, (|D|=n, x_i \in R^m, y_i \in R) D={(xi,yi)},(D=n,xiRm,yiR),有 n n n个样本,每个样本 x i x_i xi m m m个特征。集成树模型使用 K K K个加法函数来预测输出:

y ^ = ∑ k = 1 K f k ( x i ) , f k ∈ F \hat{y} = \sum_{k=1}^K f_k(x_i), f_k \in \mathcal{F} y^=k=1Kfk(xi),fkF,

F = { f ( x ) = w q ( x ) } , ( q : R m − > T , w ∈ R T ) \mathcal{F} = \{ f(x) = w_{q(x)} \}, (q: R^m->T, w \in R^T) F={f(x)=wq(x)},(q:Rm>T,wRT)是回归树的空间, q q q函数将每一个样本映射到对应的叶子节点, T T T是叶子节点数量。 w w w T T T维向量,用 w i w_i wi代表第 i i i个叶子节点。对于一个给定的样本,将每一棵树的预测值叠加起来作为最终的预测值。

为了学习每一颗树的参数,定义如下目标函数
L = ∑ i l ( y i , y i ^ ) + ∑ k Ω ( f k ) L = \sum_il(y_i, \hat{y_i}) + \sum_k \Omega(f_k) L=il(yi,yi^)+kΩ(fk)

Ω ( f ) = γ T + 1 2 λ ∣ ∣ w ∣ ∣ 2 \Omega(f) = \gamma T + \frac{1}{2}\lambda ||w||^2 Ω(f)=γT+21λw2

l l l是衡量预测值 y i ^ \hat{y_i} yi^和真实值 y y y的误差。第二项 Ω \Omega Ω则表示对CART模型复杂度的惩罚,对于复杂度的衡量,考虑了每棵树的叶子结点数量以及叶子结点得分的平方和。

Gradient Boosting

上述的目标函数并不能使用传统的优化算法(例如Gradient descent). 我们使用贪心算法,累加的去优化每一颗树。举个例子, y i ^ ( t ) \hat{y_i}^{(t)} yi^(t)代表第 i i i个样本在第 t t t次迭代(第 t t t颗树)的预测值, 那么再加入 f t f_t ft之后要优化如下目标函数:

L ( t ) = ∑ i = 1 n l ( y i , y i ^ ( t − 1 ) + f t ( x i ) ) + Ω ( f t ) L^{(t)} = \sum_{i=1}^nl(y_i, \hat{y_i}^{(t-1)}+f_t(x_i)) + \Omega (f_t) L(t)=i=1nl(yi,yi^(t1)+ft(xi))+Ω(ft)

表示在第 t t t步,贪心的添加 f t f_t ft使得模型得目标函数减小最多。使用二阶泰勒展开对上式进行近似, 二阶泰勒展开:

f ( x + Δ x ) ≈ f ( x ) + f ′ ( x ) Δ x + 1 2 f ′ ′ ( x ) Δ x 2 f(x + \Delta x) \approx f(x) + f'(x)\Delta x + \frac{1}{2}f''(x) \Delta x^2 f(x+Δx)f(x)+f(x)Δx+21f(x)Δx2

对于第 t t t次迭代, l ( y i , y i ^ ( t − 1 ) + f t ( x i ) ) l(y_i, \hat{y_i}^{(t-1)}+f_t(x_i)) l(yi,yi^(t1)+ft(xi))中, y i , y i ^ ( t − 1 ) y_i, \hat{y_i}^{(t-1)} yi,yi^(t1)都是确定值,如果把 y i ^ ( t − 1 ) \hat{y_i}^{(t-1)} yi^(t1)看成 x x x f t ( x ) f_t(x) ft(x)看成 Δ x \Delta x Δx, 那么对目标函数得到如下近似:

L ( t ) = ∑ i = 1 n l ( y i , y i ^ ( t − 1 ) ) + g i f t ( x i ) + 1 2 h i f 2 ( x i ) + Ω ( f t ) L^{(t)} = \sum_{i=1}^nl(y_i, \hat{y_i}^{(t-1)}) +g_if_t(x_i) + \frac{1}{2}h_if^2(x_i) + \Omega (f_t) L(t)=i=1nl(yi,yi^(t1))+gift(xi)+21hif2(xi)+Ω(ft)

其中 g i = ∂ y i ^ ( t − 1 ) l ( y i , y i ^ ( t − 1 ) ) g_i = \partial_{\hat{y_i}^{(t-1)}} l(y_i, \hat{y_i}^{(t-1)}) gi=yi^(t1)l(yi,yi^(t1)), h i = ∂ y i ^ ( t − 1 ) 2 l ( y i , y i ^ ( t − 1 ) ) h_i = \partial^2_{\hat{y_i}^{(t-1)}} l(y_i, \hat{y_i}^{(t-1)}) hi=yi^(t1)2l(yi,yi^(t1)).
继续对上述目标函数进行推导。由于 l ( y i , y i ^ ( t − 1 ) ) l(y_i, \hat{y_i}^{(t-1)}) l(yi,yi^(t1))和第 t t t步的优化没有关系,所以可以去除。 设 I j = { i ∣ q ( x i ) = j } I_j=\{i |q(x_i)=j\} Ij={iq(xi)=j} 为第 j j j个叶子结点的样本集合,故我们的目标函数可以写成:
L ( t ) = ∑ i = 1 n [ g i f t ( x i ) + 1 2 h i f 2 ( x i ) ] + Ω ( f t ) = ∑ i = 1 n [ g i f t ( x i ) + 1 2 h i f 2 ( x i ) ] + γ T + 1 2 λ ∑ j = 1 T w j 2 = ∑ j = 1 T [ ∑ i ∈ I j g i w j + 1 2 h i w j 2 ] + γ T + 1 2 λ ∑ j = 1 T w j 2 = ∑ j = 1 T [ ∑ i ∈ I j g i w j + 1 2 ( ∑ i ∈ I j h i + λ ) w j 2 ] + γ T L^{(t)} = \sum_{i=1}^n[g_if_t(x_i) + \frac{1}{2}h_if^2(x_i)] + \Omega (f_t) \\ = \sum_{i=1}^n[g_if_t(x_i) + \frac{1}{2}h_if^2(x_i)] + \gamma T + \frac{1}{2}\lambda \sum_{j=1}^Tw_j^2 \\ = \sum_{j=1}^T [\sum_{i\in I_j}g_iw_j+\frac{1}{2}h_iw_j^2] + \gamma T + \frac{1}{2}\lambda \sum_{j=1}^Tw_j^2 \\ = \sum_{j=1}^T [\sum_{i\in I_j}g_iw_j+\frac{1}{2}(\sum_{i\in I_j}h_i + \lambda )w_j^2] + \gamma T L(t)=i=1n[gift(xi)+21hif2(xi)]+Ω(ft)=i=1n[gift(xi)+21hif2(xi)]+γT+21λj=1Twj2=j=1T[iIjgiwj+21hiwj2]+γT+21λj=1Twj2=j=1T[iIjgiwj+21(iIjhi+λ)wj2]+γT

遍历所有的样本后求每个样本的损失函数,但样本最终会落在叶子节点上,所以我们也可以遍历叶子节点,然后获取叶子节点上的样本集合,最后在求损失函数。即我们之前样本的集合,现在都改写成叶子结点的集合,由于一个叶子结点有多个样本存在,因此才有了 ∑ i ∈ I j g i \sum_{i\in I_j}g_i iIjgi ∑ i ∈ I j h i \sum_{i\in I_j}h_i iIjhi 这两项, w j w_j wj 为第 j j j个叶子节点取值.

为了简化表达式,定义 G j = ∑ i ∈ I j g i G_j = \sum_{i\in I_j}g_i Gj=iIjgi, H j = ∑ i ∈ I j h i H_j = \sum_{i\in I_j}h_i Hj=iIjhi , 得到简化的表达式如下:

L ( t ) = ∑ j = 1 T [ G j w j + 1 2 ( H i + λ ) w j 2 ] + γ T L^{(t)} = \sum_{j=1}^T [G_jw_j+\frac{1}{2}(H_i + \lambda )w_j^2] + \gamma T L(t)=j=1T[Gjwj+21(Hi+λ)wj2]+γT

需要注意的是 G j G_j Gj H j H_j Hj是前 t − 1 t-1 t1步得到的结果,其值可以视为常数, 只有最后一棵树的叶子结点 w j w_j wj不确定,将目标函数 L ( t ) L^{(t)} L(t) w j w_j wj求导,可以求得 w j w_j wj
w j ∗ = − G j H j + λ w_j^* = -\frac{G_j}{H_j + \lambda } wj=Hj+λGj

w j ∗ w_j^* wj带入目标函数 L ( t ) L^{(t)} L(t),可以得到:

L ( t ) = − 1 2 ∑ j = 1 T G j 2 H j + λ + γ T L^{(t)} = -\frac{1}{2} \sum_{j=1}^T \frac{G_j^2}{H_j + \lambda} + \gamma T L(t)=21j=1THj+λGj2+γT

只需要将每个叶子结点的所有样本的一阶导数 g j g_j gj和二阶导数 h j h_j hj求和得到 G j G_j Gj H j H_j Hj, 然后用上述公式就可以算出目标函数值(越小越好)

Shrinkage and Column Subsampling

Shrinkage指的是对于新加的每一颗树,都乘上一个因子 η \eta η. 类似于梯度下降中的学习率衰减。Shrinkage减小了每一颗新加树的影响从而提高模型得整体预测性能。
Column subsampling (feature subsampling)特征采样可以用于防止过拟合,在随机森林(random forest)中也有使用

Split finding algorithm

在决策树的生长过程中,一个非常关键的问题是如何找到叶子的节点的最优切分点,Xgboost支持两种分裂节点的方法——贪心算法(extrace greedy algorithm)和近似算法(approximate algorithm)。 首先要计算出每个特征分裂的收益. 假定在某一个结点上分裂,分裂前的目标函数可以写为:
L ( 1 ) = − 1 2 ( G L + G R ) 2 ( H L + H R ) + λ + γ L^{(1)} = -\frac{1}{2} \frac{(G_L+G_R)^2}{(H_L+H_R) + \lambda} + \gamma L(1)=21(HL+HR)+λ(GL+GR)2+γ
分裂后的目标函数可以写为:
L ( 2 ) = − 1 2 [ G L 2 H L + λ + G R 2 H R + λ ] + 2 γ L^{(2)} = -\frac{1}{2}[ \frac{G_L^2}{H_L + \lambda} + \frac{G_R^2}{H_R + \lambda} ]+ 2\gamma L(2)=21[HL+λGL2+HR+λGR2]+2γ
分裂后的收益为(目标函数越小越好):

G a i n = L ( 1 ) − L ( 2 ) = 1 2 [ G L 2 H L + λ + G R 2 H R + λ − ( G L + G R ) 2 ( H L + H R ) + λ ] − γ Gain = L^{(1)} - L^{(2)} = \frac{1}{2} [ \frac{G_L^2}{H_L + \lambda} + \frac{G_R^2}{H_R + \lambda} - \frac{(G_L+G_R)^2}{(H_L+H_R) + \lambda}] - \gamma Gain=L(1)L(2)=21[HL+λGL2+HR+λGR2(HL+HR)+λ(GL+GR)2]γ
该特征的分裂收益可以作为feature importance的重要依据。

Exact Greedy Algorithm
  • 从深度为0的树开始,对每个叶节点枚举所有的可用特征;
  • 针对每个特征,把属于该节点的训练样本根据该特征值进行升序排列,通过线性扫描的方式来决定该特征的最佳分裂点,并记录该特征的分裂收益;
  • 选择收益最大的特征作为分裂特征,用该特征的最佳分裂点作为分裂位置,在该节点上分裂出左右两个新的叶节点,并为每个新节点关联对应的样本集
  • 回到第 1 步,递归执行到满足特定条件为止
Approximate Algorithm

贪婪算法可以的到最优解,但当数据量太大时则无法读入内存进行计算,近似算法主要针对贪婪算法这一缺点给出了近似最优解。对于每个特征,只考察分位点可以减少计算复杂度该算法会首先根据特征分布的分位数提出候选划分点,然后将连续型特征映射到由这些候选点划分的桶中,然后聚合统计信息找到所有区间的最佳分裂点。在提出候选切分点时有两种策略:

  • Global:学习每棵树前就提出候选切分点,并在每次分裂时都采用这种分割;
  • Local:每次分裂前将重新提出候选切分点。

直观上来看,Local 策略需要更多的计算步骤,而 Global 策略因为节点没有划分所以需要更多的候选点。

Sparsity-aware Split Finding

在现实问题中,输入是稀疏数据是很常见的。

XGBoost 在构建树的节点过程中为每个节点增加了一个缺省方向,当样本相应的特征值缺失时,可以被归类到缺省方向上,最优的缺省方向可以从数据中学到。至于如何学到缺省值的分支,其实很简单,分别枚举特征缺省的样本归为左右分支后的增益,选择增益最大的枚举项即为最优缺省方向。

Xgboost实践

xgboost文档:https://xgboost.readthedocs.io/en/latest/python/index.html

先来看一个多分类的例子

import copy
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn import metrics
import xgboost as xgb

def load_data():
    iris = load_iris()
    X = iris.data
    y = iris.target
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
    return X_train, X_test, y_train, y_test
    
def basic_modeling(X_train, X_test, y_train, y_test):
    params = {
    'booster': 'gbtree',					# 使用gradient boosting tree
    'objective': 'multi:softmax',			# 分类目标,这里是多分类
    'num_class': 3,							# 分类类别数
    'gamma': 0.1,                           # 最小loss减小量
    'max_depth': 3,							# 树的最大深度
    'monotone_constraints': (-1,-1,0,-1)# 单调性约束
    }
    dtrain = xgb.DMatrix(X_train, y_train)
    dtest = xgb.DMatrix(X_test)
    model = xgb.train(params, dtrain, 10)
    y_pred = model.predict(dtest)
    score = metrics.accuracy_score(y_test, y_pred)
    return model, score
  
if __name__ == "main":
    import matplotlib.pyplot as plt
    X_train, X_test, y_train, y_test = load_data()
    model, score = basic_modeling(X_train, X_test, y_train, y_test)
    print(score)

monotonic constraints

参考文档:https://xgboost.readthedocs.io/en/latest/tutorials/monotonic.html

在建立xgboost模型的过程中,如果对模型有很强的先验,即对模型的某个feature和response之前的关系有很强的先验,可以对模型添加约束, 从而提高模型得整体预测性能。
一种常见的约束类型是,某个特定的feature和response具有单调性。

f ( x 1 , x 2 , . . . , x , . . . , x n ) ≤ f ( x 1 , x 2 , . . . , x ′ , . . . , x n ) f(x_1, x_2,...,x,...,x_n) \leq f(x_1, x_2,...,x',...,x_n) f(x1,x2,...,x,...,xn)f(x1,x2,...,x,...,xn)

whenever x ≤ x ′ x \leq x' xx is an increase constraints. 或者

f ( x 1 , x 2 , . . . , x , . . . , x n ) ≥ f ( x 1 , x 2 , . . . , x ′ , . . . , x n ) f(x_1, x_2,...,x,...,x_n) \geq f(x_1, x_2,...,x',...,x_n) f(x1,x2,...,x,...,xn)f(x1,x2,...,x,...,xn)

whenever x ≤ x ′ x \leq x' xx is an decrease constraints

来看一个例子。人为的构造数据集, x 1 x_1 x1 x 2 x_2 x2均服从正态分布,对训练集中的 y t r a i n y_{train} ytrain, 添加噪音。 但是测试集合中 y t e s t y_{test} ytest没有噪音。给定两个模型得参数,一个带有monotonic constraints, 一个没有montonic constraints, 发现给定单调约束的预测性能远远高于没有给定单调约束的模型

import math
import numpy as np
import pandas as pd
from sklearn import metrics
from sklearn.model_selection import train_test_split
# generate data
x1 = np.random.normal(0, 1, 1000)
x2 = np.random.normal(0, 1, 1000)

X = np.array([x1, x2]).T

X_train, X_test = train_test_split(X, test_size=0.25)

# add noise in train data
y_train = X_train[:,0] - X_train[:,1]  + np.random.normal(0, 2, X_train.shape[0])
# no noise in test data
y_test = X_test[:,0] - X_test[:,1]

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(12, 8))
ax1 = fig.add_subplot(1,2,1)
ax2 = fig.add_subplot(1,2,2)
ax1.scatter(X_train[:,0], y_train)
ax2.scatter(X_train[:,1], y_train)

训练数据中存在噪音

fig = plt.figure(figsize=(12, 8))
ax1 = fig.add_subplot(1,2,1)
ax2 = fig.add_subplot(1,2,2)
ax1.scatter(X_test[:,0], y_test)
ax2.scatter(X_test[:,1], y_test)

测试数据中没有噪音

import xgboost as xgb

params = {
'booster': 'gbtree',
'objective': 'reg:squarederror',
'gamma': 0.1,
'tree_method': "exact"
}

dtrain = xgb.DMatrix(X_train, y_train)
dtest = xgb.DMatrix(X_test, y_test)

model = xgb.train(params, dtrain, 10)
metrics.r2_score(y_test, model.predict(dtest)) # 0.629608701675472
params = {
'booster': 'gbtree',
'objective': 'reg:squarederror',
'gamma': 0.1,
'tree_method': "exact"
'monotone_constraints': (1, -1),
}
model = xgb.train(params, dtrain, 10)
metrics.r2_score(y_test, model.predict(dtest)) #     0.9429734575760605

只需要在params中加入"monotone_constraints"参数, 1代表单调递增,-1代表单调递减,0代表没有单调限制

  • (1,0): An increasing constraint on the first predictor and no constraint on the second.
  • (0,-1): No constraint on the first predictor and a decreasing constraint on the second.

feature importance

关于 feature importance可以参考 https://blog.csdn.net/John_xyz/article/details/85165064

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值