Fork me on GitHub

决策树的一些总结和理解

 

1. 决策树的定义

2. 决策树的分支:分类与回归

3. 随机森林软件隔支持向量机

4. 决策树处理缺失数据

5. 决策树的剪枝

 

1. 决策树的定义

  决策树,顾名思义,就是用来决策的树,通常来说,决策树分为C4.5,CART等,其实他们都是一个东西,区别就是在于他们的分支方法不同。决策树我们只要理解,他是一种将数据依据某几个最显著的属性,不断划分,以后遇到新的数据时,可以利用我们之前得到的决策树进行判断,分析新的数据和历史数据中的哪一个类最相似。这就是决策树。在基于决策树的其他算法例如随机森林,gbdt,xgboost等,只不过是使用了一些提升算法,本质上他们都是类似的,他们区别就是在于如何生成树,如何生成树,其实就是如何分裂树枝。就像GLM一样,可以解释逻辑斯特回归,高斯回归等一系列模型。  

2. 决策树的分支

上一段我也说了,决策树的核心就是在于分支的确定,而实际上,我们通常使用熵,基尼系数等损失函数来划分决策树,对于回归变量我们通常使用最小化方差(MSE)。

我们计算某一个类别的基尼系数时,我们只要将这一类从总的数据集中抽取出来,计算划分后的两个集合的损失与原集合的差值来判断是否采用这一个属性来划分数据集。

 基尼系数的计算:

def giniimpurity(rows):
    total=len(rows)
    countresult=uniquecount(rows) // 其中 uniquecount 函数是计算每一个属性有多少个类别,并统计数量。
    giniimp=0
    for num in countresult:
        p1=float(countresult[num])/total
        for num2 in countresult:
            if num==num2: continue
            p2=float(countresult[num2])/total
            giniimp += p1*p2
    return giniimp

熵的计算:

def entropy(rows):
    from math import log
    log2=lambda x:log(x)/log(2)
    entro=0
    total=len(rows)
    countresult = uniquecount(rows)
    for name in countresult:
        pi=float(countresult[name])/total
        entro =entro - pi*log2(pi)
    return entro

方差的计算:

def MSE(rows):
    datamean = float(np.mean(rows))
    R2 = sum([(x - datamean)**2 for x in rows])
    return R2

有了我们的计算损失的方式,我们便可以计算采用哪一个属性划分数据:

 

def selectBestFeature(rows,scoref=MSE):
    best_gain = float('inf')
    best_col=0
    best_iden=None
    for col in xrange(len(rows[0])-1):
        eachtypenum=counteachtype(rows,col)#对于每一列计算他们每一列有哪些属性。
        for iden in eachtypenum.keys():
            (set1,set2)=divideSetLast(rows,col,iden) #按照每一列的每一个属性划分数据集
            if len(set1)==0 and len(set2)!=0:
                gain=scoref(set2)             
            if len(set1)!=0 and len(set2) ==0:
                gain=scoref(set1)
            if len(set1) !=0 and len(set2) !=0:
                gain=scoref(set1)+scoref(set2)#计算划分后的得分
            if gain < best_gain and len(set1)>0 and len(set2)>0:
                best_gain=gain
                best_col=col
                best_iden=iden
    return (best_col,best_iden,best_gain)

所以我们得到了最优分裂特征后便按照这个特征划分数据集,将数据集按照这个特征的值的大小分成两个部分,这便是树枝的分叉。

3. 决策树处理缺失数据

 决策树处理缺失数据是一个非常好的方式,但是,我觉得它更适合处理只有少部分缺失,对于稀疏数据使用决策树来处理不是一个非常好的选择。

 决策树来处理缺失数据依然是在树枝分裂的阶段,我们可以看到在我们的最优特征的选择上的代码中,我们是如何计算score的值的呢? 使用的是我们预设的价值函数。实际上,我们处理缺失值也是在这里做文章,对于缺失值,我们先不管他,先将其中非缺失的部分做一个划分,然后对于缺失值,我们依次填充缺失值,那么我们得到的是这个缺失值在每一个类别的可能性。也就是说,我们最后得到的不是一个确定的集合,而是数据属于这个集合的可能性!

    这里也是解释了我为什么说适用于少部分缺失,如果大部分缺失的话,就是造成很大的困扰,每一次分裂,都有太多的可能性,造成决策树过于庞大,同时可视化程度降低,造成数据过拟合和欠拟合。

4. 决策树的剪枝

  决策树的剪枝,就是在生成一颗决策树后对决策树进行结构上的优化,通常分为预剪枝,后剪枝。在周志华的西瓜书中说:训练集用来决定树生成过程中每个结点划分所选择的属性;验证集在预剪枝中用于决定该结点是否有必要依据该属性进行展开,在后剪枝中用于判断该结点是否需要进行剪枝。

       预剪枝就是在生成树的同时进行剪枝,也就是说在进行分叉的同时,计算分叉与不分叉两种情况下,树的预测性能是否有提高,如果有提高那么就进行分叉,否则抛弃这一次的分叉。

  这个地方我想提的是,XGboost 的剪枝算法是使用树的层数和分支树作为惩罚项,这样可以有效的避免树的过拟合。

  后剪枝叶就是在一棵树的生成后,自下而上地进行收缩,步骤类似于预剪枝,看两课子树如果合并的话,对于树的性能是否有提高

 

posted @ 2019-05-30 16:20  顾鹏pen  阅读(2335)  评论(0编辑  收藏  举报