GBDT的面试问题

1.简介

    gbdt全称梯度提升决策树,在传统机器学习算法里面是对真实分布拟合的最好的几种算法之一,在前几年深度学习还没有大行其道之前,gbdt在各种竞赛是大放异彩。原因大概有几个,一是效果确实挺不错。二是即可以用于分类也可以用于回归。三是可以筛选特征。这三点实在是太吸引人了,导致在面试的时候大家也非常喜欢问这个算法。 gbdt的面试考核点,大致有下面几个:

  • gbdt 的算法的流程?
  • gbdt 如何选择特征 ?
  • gbdt 如何构建特征 ?
  • gbdt 如何用于分类?
  • gbdt 通过什么方式减少误差 ?
  • gbdt的效果相比于传统的LR,SVM效果为什么好一些 ?
  • gbdt 如何加速训练?
  • gbdt的参数有哪些,如何调参 ?
  • gbdt 实战当中遇到的一些问题 ?
  • gbdt的优缺点 ?

2. 正式介绍

    首先gbdt 是通过采用加法模型(即基函数的线性组合),以及不断减小训练过程产生的残差来达到将数据分类或者回归的算法。

  •  gbdt的训练过程

        我们通过一张图片,图片来源来说明gbdt的训练过程: 

    

                      图 1:GBDT 的训练过程

        gbdt通过多轮迭代,每轮迭代产生一个弱分类器,每个分类器在上一轮分类器的残差基础上进行训练。对弱分类器的要求一般是足够简单,并且是低方差和高偏差的。因为训练的过程是通过降低偏差来不断提高最终分类器的精度,(此处是可以证明的)。

        弱分类器一般会选择为CART TREE(也就是分类回归树)。由于上述高偏差和简单的要求 每个分类回归树的深度不会很深。最终的总分类器 是将每轮训练得到的弱分类器加权求和得到的(也就是加法模型)。

        模型最终可以描述为:

Fm(x)=m=1MT(x;θm)Fm(x)=∑m=1MT(x;θm)

  • GBDT 多分类举例说明

        上面的理论阐述可能仍旧过于难懂,我们下面将拿Iris 数据集中的六个数据作为例子,来展示gbdt 多分类的过程。

    • 样本编号花萼长度(cm)花萼宽度(cm)花瓣长度(cm)花瓣宽度花的种类
1 5.1 3.5 1.4 0.2 山鸢尾 2 4.9 3.0 1.4 0.2 山鸢尾 3 7.0 3.2 4.7 1.4 杂色鸢尾 4 6.4 3.2 4.5 1.5 杂色鸢尾 5 6.3 3.3 6.0 2.5 维吉尼亚鸢尾 6 5.8 2.7 5.1 1.9 维吉尼亚鸢尾

图四 Iris 数据集

        这是一个有6个样本的三分类问题。我们需要根据这个花的花萼长度,花萼宽度,花瓣长度,花瓣宽度来判断这个花属于山鸢尾,杂色鸢尾,还是维吉尼亚鸢尾。具体应用到gbdt多分类算法上面。我们用一个三维向量来标志样本的label。[1,0,0] 表示样本属于山鸢尾,[0,1,0] 表示样本属于杂色鸢尾,[0,0,1] 表示属于维吉尼亚鸢尾。

        gbdt 的多分类是针对每个类都独立训练一个 CART Tree。所以这里,我们将针对山鸢尾类别训练一个 CART Tree 1。杂色鸢尾训练一个 CART Tree 2 。维吉尼亚鸢尾训练一个CART Tree 3,这三个树相互独立。

        我们以样本 1 为例。针对 CART Tree1 的训练样本是[5.1,3.5,1.4,0.2][5.1,3.5,1.4,0.2]

        下面我们来看 CART Tree1 是如何生成的,其他树 CART Tree2 , CART Tree 3的生成方式是一样的。CART Tree的生成过程是从这四个特征中找一个特征做为CART Tree1 的节点。比如花萼长度做为节点。6个样本当中花萼长度 大于5.1 cm的就是 A类,小于等于 5.1 cm 的是B类。生成的过程其实非常简单,问题 1.是哪个特征最合适? 2.是这个特征的什么特征值作为切分点? 即使我们已经确定了花萼长度做为节点。花萼长度本身也有很多值。在这里我们的方式是遍历所有的可能性,找到一个最好的特征和它对应的最优特征值可以让当前式子的值最小。

         我们以第一个特征的第一个特征值为例。R1 为所有样本中花萼长度小于 5.1 cm 的样本集合,R2 为所有样本当中花萼长度大于等于 5.1cm 的样本集合。所以 R1={2}R1={2}

        下面我们用代码来实现整个找特征的过程,大家可以自己再对照代码看看。

复制代码
 1 # 定义训练数据
 2 train_data = [[5.1,3.5,1.4,0.2],[4.9,3.0,1.4,0.2],[7.0,3.2,4.7,1.4],[6.4,3.2,4.5,1.5],[6.3,3.3,6.0,2.5],[5.8,2.7,5.1,1.9]]
 3 
 4 # 定义label
 5 label_data = [[1,0,0],[1,0,0],[0,1,0],[0,1,0],[0,0,1],[0,0,1]]
 6 # index 表示的第几类
 7 def findBestLossAndSplit(train_data,label_data,index):
 8         sample_numbers = len(label_data)
 9         feature_numbers = len(train_data[0])
10         current_label = []
11 
12         # define the minLoss
13         minLoss = 10000000
14 
15         # feature represents the dimensions of the feature
16         feature = 0
17 
18         # split represents the detail split value
19         split = 0
20 
21         # get current label
22         for label_index in range(0,len(label_data)):
23             current_label.append(label_data[label_index][index])
24 
25         # trans all features
26         for feature_index in range(0,feature_numbers):
27             ## current feature value
28             current_value = []
29 
30             for sample_index in range(0,sample_numbers):
31                 current_value.append(train_data[sample_index][feature_index])
32             L = 0
33             ## different split value
34             print current_value
35             for index in range(0,len(current_value)):
36                 R1 = []
37                 R2 = []
38                 y1 = 0
39                 y2 = 0
40 
41                 for index_1 in range(0,len(current_value)):
42                     if current_value[index_1] < current_value[index]:
43                         R1.append(index_1)
44                     else:
45                         R2.append(index_1)
46 
47                 ## calculate the samples for first class
48                 sum_y = 0
49                 for index_R1 in R1:
50                     sum_y += current_label[index_R1]
51                 if len(R1) != 0:
52                     y1 = float(sum_y) / float(len(R1))
53                 else:
54                     y1 = 0
55 
56                 ## calculate the samples for second class
57                 sum_y = 0
58                 for index_R2 in R2:
59                     sum_y += current_label[index_R2]
60                 if len(R2) != 0:
61                     y2 = float(sum_y) / float(len(R2))
62                 else:
63                     y2 = 0
64 
65                 ## trans all samples to find minium loss and best split
66                 for index_2 in range(0,len(current_value)):
67                     if index_2 in R1:
68                         L += float((current_label[index_2]-y1))*float((current_label[index_2]-y1))
69                     else:
70                         L += float((current_label[index_2]-y2))*float((current_label[index_2]-y2))
71 
72                 if L < minLoss:
73                     feature = feature_index
74                     split = current_value[index]
75                     minLoss = L
76                     print "minLoss"
77                     print minLoss
78                     print "split"
79                     print split
80                     print "feature"
81                     print feature
82         return minLoss,split,feature
83 
84 findBestLossAndSplit(train_data,label_data,0)
复制代码

 

  • 3 总结

        目前,我们总结了 gbdt 的算法的流程,gbdt如何选择特征,如何产生特征的组合,以及gbdt 如何用于分类,这个目前可以认为是gbdt 最经常问到的四个部分。至于剩余的问题,因为篇幅的问题,我们准备再开一个篇幅来进行总结。也欢迎大家关注我的微信公众号。ModifyAI

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值