决策树的理解

决策数应该是那些对人工智能/专家系统了解不深的人的最初认知吧,各种if-then的强逻辑关系来让计算机具备人脑一样的决策力。说起来似乎挺简单的,找行业专家把他的经验都写下来,然后找人开始写if-then语句blablabla。但是人脑的经验决策一定对吗?人脑的决策思路真的没问题吗?抛开工作量,真的将一堆if-then放进计算机就是人工智能?

这些问题时不时会出现在我的脑海里,让我去思考,在我这一路人工智能进阶的路上,对于A.I.,对于专家系统,我的理解逐渐变化,对上述的几个问题,也逐渐懂得了如何去回答。

首先,if-then的说法是一个没毛病的策略,买车买房子等等生活中所有需要做出选择的场景,if-then是每个人思考的核心逻辑。但是决策树算法并非那样简单,算法工程师需要思考的是将所有的判断进行最优化排序,让对结果影响大的决策优先进行判断,按照强度顺序依次判断分类,到最终得到结果。这一步的逻辑是行外人所不知的,现实生活中,我们思考问题都有权重之分,我们去买车,选择面太广了,日本车,美国车,德国车,豪跑,SUV,四驱,两驱,颜色,内室设计等等,我们人脑的运算能力有限,一提出这些问题,我们就头大,这是很普遍的问题,因为我们没法一次性得出我们想找的答案,我们只能和家里人商量,“我们究竟最关注什么?”,对我来说,我喜欢SUV,那么我首选SUV,这样大量的轿车跑车就会被排除,然后,我比较看重车牌的原产地,我喜欢美系车,没有理由,因此,日本车德国车国产车等等就都排除出去,现在剩下的选择就少很多了,这个思路是我们人脑在先天运算能力有限的情况下,我们的思考方法,当我们的思考面不够宽广,也许我们会得到一些错误的答案。这也就是目前人工智能需要避免并且有能力避免的问题。

人工智能的前提是数据挖掘,完整的数据挖掘体系可以为人工智能提供良好的数据基础。这一点,所谓的行业专家就变得不那么“专家”了。数据挖掘可以在大量的数据里找出问题,而这些问题有可能是专家预见的,有可能是非预见的,人工智能促进专家去思考,而专家以判断的形式反哺人工智能,这是主辅关系不停轮换,也是一种积极的学习模式。

扯远了,回过头来,决策树就是要用历史数据来找出对结果影响最大的特征,而并非专家的经验,经验可以骗人,但是完整的数据不会。如果将单一的专家经验通过if-then注入计算机,那不是人工智能,那是伪人工智能,他的能力太有限了,就像那个专家一样。更有意思的是,如果专家的逻辑有问题,理解有误,那就不是人工智能,那就是人工智障了。


说了这么多,其实是为了将决策树和传统意义的if-then分开,决策树的能力远远强于我们字面对他的理解。接下类就重点说说决策树的算法和功能。

决策树的概念

决策树(Decision Tree)是一种基本的分类与回归方法。可以做分类问题,也可以做回归问题。他的优点是他的树形构架是通过if-then实现,因此做分类时结果的可读性可理解性都很强。但是决策树的缺点也很明显,就是容易出现过拟合的问题。在决策树模型在学习时,利用训练数据,根据损失函数最小的原则建立决策树模型。回归问题和回归问题的损失函数不同。

决策树的步骤

特征选择,决策树的生成,决策树的修剪。

决策树的分类思路

用决策树分类:从根节点开始,对实例的某一个特征进行测试,根据测试结果将实例分配到其子节点,此时每个子节点对应着该特征的一个取值,递归对实例进行测试并分配,直到到达叶节点,最后将实例分到叶节点的类中,分类结束。

  1. 决策树每通过一个节点都需要选择一次最优特征,然后按照这个特征进行分割子集。
  2. 如果子集已经被基本正确分类,那么就需要构建叶节点,叶节点为终止节点。
  3. 如果每个子集都被分到叶节点上,即都有了明确的类,这时决策树就生成了。
树结构

决策树在分类过程中特征选择的依据

  • 信息熵&信息增益

信息熵定义: 字面意思上的理解就是描述一个信息不确定度的标量。信息熵越大,表示该信息不确定度越大,信息熵越小,表示该信息不确定性越小。
, 样本k的经验概率
, 有k个类别,样本总数为D,某类别的样本个数。
信息增益:根据某特征分类前后,信息不确定性发生的变化。表示得知特征X的信息而使得类Y的信息不确定性减少的程度。决策树中我们优先选取信息增益最大的特征进行分类。

信息增益比:从信息增益中,可以看出,信息增益的大小取决于数据集的经验熵,经验熵大的时候,信息增益会偏大,反之,信息增益会减小。特征取值越多,信息增益便会偏大。信息增益比会对这个问题进行矫正。


缺点:当特征取值较少时,取值越小,那么信息增益比就会越大,因此,信息增益比倾向于取值较少的特征。

综上,在使用信息增益比的时候,应该是先选择信息增益高于平均水平的特征,然后在这些特征中再选择信息增益率最高的特征。
  • gini指数

定义:表示在样本集合中一个随机选中的样本被分错的概率。gini指数越小表示集合被选中的样本被分错的概率越小,也就是说集合的纯度越高,反之,集合越不纯。

表示样本属于K类别的概率,表示样本不属于K类别的概率。
样本集合D的gini指数:


上代码,在代码里理解这些变量。
数据集

def createDataSet():
    # 数据集
    dataSet=[[0, 0, 0, 0, 'no'],
            [0, 0, 0, 1, 'no'],
            [0, 1, 0, 1, 'yes'],
            [0, 1, 1, 0, 'yes'],
            [0, 0, 0, 0, 'no'],
            [1, 0, 0, 0, 'no'],
            [1, 0, 0, 1, 'no'],
            [1, 1, 1, 1, 'yes'],
            [1, 0, 1, 2, 'yes'],
            [1, 0, 1, 2, 'yes'],
            [2, 0, 1, 2, 'yes'],
            [2, 0, 1, 1, 'yes'],
            [2, 1, 0, 1, 'yes'],
            [2, 1, 0, 2, 'yes'],
            [2, 0, 0, 0, 'no']]
    #分类属性
    labels=['年龄','有工作','有自己的房子','信贷情况']
    #返回数据集和分类属性
    return dataSet,labels
import numpy as np

def entropyCalculate(dataSet):
    numData = len(dataSet)
    labelCount={}
    for row in dataSet:
        label = row[-1]
        if label not in labelCount.keys():
            labelCount[label] = 0
        labelCount[label] += 1
    entropy = 0
    for key in labelCount:
        prob = float(labelCount[key])/numData
        entropy = entropy - prob*np.log2(prob)
    return(entropy)
    
    
    
def featureSelection(dataSet):
    #dataSet实际上是每一层的数据
    numFeature = len(dataSet[0])-1
    dataEntropy = entropyCalculate(dataSet)
    largestgain = 0
    for i in range(numFeature):
        featureList = [data[i] for data in dataSet]
        featureValue = set(featureList)
        conditionEntropy = 0
        for value in featureValue:
            subdataSet = regroupData(dataSet, i, value)
            prob = len(subdataSet)/float(len(dataSet))
            conditionEntropy += prob * entropyCalculate(subdataSet)
        inforgain = dataEntropy - conditionEntropy
        print('第%d个特征的增益为%.3f' %(i, inforgain))
        if (inforgain > largestgain):
            largestgain = inforgain
            bestFeature = i
    return(bestFeature)
            
    
    
#axis代表特征index, value代表特征某一个变量
def regroupData(dataSet, axis, value):
    dataSetNew=[]
    for data in dataSet:
        if data[axis] == value:
            midvalue = data[:axis]
            midvalue.extend(data[axis+1:])
            dataSetNew.append(midvalue)
    return(dataSetNew)
    
    
#构建决策树
def createTree(dataSet, labels, featLabels):
    #首先分析数据标签,如果标签一致,就停止分类,如果标签不一致,继续下面的决策树分类
    classList = [example[-1] for example in dataSet]
    if classList.count(classList[0]) == len(classList):
        return(classList[0])
    #选择最优特征
    bestFeat = featureSelection(dataSet)
    #定位最优特征的标签
    bestFeatLabel=labels[bestFeat]
    featLabels.append(bestFeatLabel)
    #生成树
    myTree={bestFeatLabel:{}}
    #删除已经使用的特征标签
    del(labels[bestFeat])
    #找最有特征的属性
    featValues = [example[bestFeat] for example in dataSet]
    #去掉重复属性
    uniqueVls = set(featValues)
    for value in uniqueVls:
        myTree[bestFeatLabel][value]=createTree(regroupData(dataSet,bestFeat,value),labels,featLabels)
    return(myTree)

featLabels=[]
myTree=createTree(dataSet,labels,featLabels)
print(myTree)

决策树是一个不断迭代的过程,直到数据属于同一类,程序终止。

你可能感兴趣的:(决策树的理解)