iris数据_决策树Decision Tree(ID3算法)(UCI数据库)

iris数据_决策树Decision Tree(ID3算法)(UCI数据库)_第1张图片

决策树构建流程

决策树的构造过程一般分为3个部分,分别是特征选择、决策树生产和决策树裁剪。

(1)特征选择:

特征选择表示从众多的特征中选择一个特征作为当前节点分裂的标准,如何选择特征有不同的量化评估方法,从而衍生出不同的决策树,如ID3(通过信息增益选择特征)、C4.5(通过信息增益比选择特征)、CART(通过Gini指数选择特征)等。

目的(准则):使用某特征对数据集划分之后,各数据子集的纯度要比划分钱的数据集D的纯度高(也就是不确定性要比划分前数据集D的不确定性低)

(2)决策树的生成

根据选择的特征评估标准,从上至下递归地生成子节点,直到数据集不可分则停止决策树停止生长。这个过程实际上就是使用满足划分准则的特征不断的将数据集划分成纯度更高,不确定行更小的子集的过程。对于当前数据集的每一次划分,都希望根据某个特征划分之后的各个子集的纯度更高,不确定性更小。

(3)决策树的裁剪

决策树容易过拟合,一般需要剪枝来缩小树结构规模、缓解过拟合。

实例

以UCI的数据集IRIS为例,一共有3种不同的类别setosa, versicolor, virginica,当输入是一个集合的时候, 统计集合中各种类别的数量,记录在字典里,然后分别求出概率p1,p2和p3,最后得信息熵。

iris数据_决策树Decision Tree(ID3算法)(UCI数据库)_第2张图片

为计算公式。

def entropy(data_iris):
    tmp={'Iris-setosa':0,'Iris-versicolor':0,'Iris-virginica':0}
    #构建空字典用来统计各个类别的数量
    for j in range(len(data_iris)):
        if data_iris[j][-1]=='Iris-setosa':
            tmp['Iris-setosa']+=1
        elif data_iris[j][-1]=='Iris-versicolor':
            tmp['Iris-versicolor'] += 1
        else:
            tmp['Iris-virginica'] +=1
    sum=returnSum(tmp)
    p1= tmp['Iris-setosa']/sum
    p2 = tmp['Iris-versicolor'] / sum
    p3 = tmp['Iris-virginica'] / sum
    return -p1*log(p1)-p2*lo g(p2)-p3*log(p3)
    
def returnSum(myDict):#该函数用来计算字典值之和
    sum = 0
    for i in myDict:
        sum = sum + myDict[i]
    return sum

ID3算法就是用信息增益来判断当前节点应该用什么特征来构建决策树。信息增益大,则越适合用来分类。考虑IRIS数据集是连续的,我们采用二分法的策略,遍历每一属性的每一种可能值,寻找最佳选项。
首先对IRIS数据集进行预处理。

def make_dataset():
    f = open("D:PycharmcpystanPR_homework决策树iris.txt")
    data = f.read()
    data = data.split()
    data_iris=[]
    for i in range(len(data)):
        data_iris.append(data[i].split(','))
        data_iris[i][0]=float(data_iris[i][0])
        data_iris[i][1] = float(data_iris[i][1])
        data_iris[i][2] = float(data_iris[i][2])
        data_iris[i][3] = float(data_iris[i][3])
    return data_iris
#经过预处理后的数据形式为
#[[5.1, 3.5, 1.4, 0.2, 'Iris-setosa'], ……,] 

下面用表格详细说明每一条数据的物理含义。

iris数据_决策树Decision Tree(ID3算法)(UCI数据库)_第3张图片

接下来我们需要对每一条数据的前四种属性的每一种二分分类方式遍历,寻找最大增益。以上面这条数据为例,选定属性sepal_length,则通过划分出两个区间,大于等于5.1的部分和小于5.1的部分,计算信息增益。信息增益计算公式为:

iris数据_决策树Decision Tree(ID3算法)(UCI数据库)_第4张图片
 def informative_attribute(data_iris,ori_entropy):
    #最优属性,最优区间
    result=[]
    for i in range(len(data_iris[0])-1):
        #对某一attribute的任意一个值分类,遍历
        best_edge=0
        best_gain=0
        for j in range(len(data_iris)):#遍历每一个值
            edge=data_iris[j][i]
            class1=[]
            class2=[]
            for t in range(len(data_iris)):
                if data_iris[t][i]>=edge:
                    class1.append(data_iris[t])
                else :
                    class2.append(data_iris[t])
            gain= ori_entropy-(len(class1)/len(data_iris))*entropy(class1)-(len(class2)/len(data_iris))*entropy(class2)
            if gain>best_gain:
                best_gain=gain
                best_edge=edge
        result.append([best_edge,best_gain])
    return result
#Print(result)显示计算结果如下
#[[5.6, 0.3862442664692114], [3.4, 0.18570201019349386],
 [3.0, 0.6365141682948128], [1.0, 0.6365141682948128]]

(1)首先寻找最有信息量的属性

通过上述函数计算得到四种属性各自的最大信息增益及对应分界点为:

iris数据_决策树Decision Tree(ID3算法)(UCI数据库)_第5张图片

因此most informative attribute是petal_length或者petal_width。

(2)构建决策树

首先略微修改informative_attribute函数,方便寻找全局最优:

def informative_attribute(data_iris,ori_entropy,list):
    #全局最优属性,最优区间
    result=[]
    best_edge = 0
    best_gain = 0
    best_class1 = []
    best_class2 = []
    flag=0
    for i in list:
        #对某一attribute的任意一个值分类,遍历

        for j in range(len(data_iris)):#遍历每一个值
            edge=data_iris[j][i]
            class1=[]
            class2=[]

            for t in range(len(data_iris)):
                if data_iris[t][i]>=edge:
                    class1.append(data_iris[t])
                else :
                    class2.append(data_iris[t])
            gain= ori_entropy-(len(class1)/len(data_iris))*entropy(class1)-(len(class2)/len(data_iris))*entropy(class2)
            if gain>best_gain:
                best_gain=gain
                best_edge=edge
                best_class1=class1
                best_class2=class2
                flag=i
        #result.append([[i,best_edge,best_gain],best_class1,best_class2])

    return [flag,best_edge,best_gain],best_class1,best_class2

接下来就是不断重复循环最大增益并进行分割的过程。

data_iris=make_dataset()


result1,class2_1,class2_2=informative_attribute(data_iris,entropy(data_iris),[0,1,2,3])
print(result1)
#第一个分叉点,选择属性2,分界点为3.0,
#[2, 3.0, 0.6365141682948128]

result2_1,class3_1,class3_2=informative_attribute(class2_1,entropy(class2_1),[0,1,3])
print(result2_1)
print(class3_1)
print(class3_2)
#第二行第一个分叉点,选择属性3,分界点为1.8
#[3, 1.8, 0.4783827151228094]
result2_2,class3_3,class3_4=informative_attribute(class2_2,entropy(class2_2),[0,1,3])
print(result2_2)
#第二行第二个分叉点已达到熵最小,均为setosa,不需要继续往下分
#[0, 0, 0]

result3_1,class4_1,class4_2=informative_attribute(class3_1,entropy(class3_1),[0,1])
print(result3_1)
#第三行第一个分叉点,选择属性0,分界点为6.0
#[0, 6.0, 0.042323434148154725]
print(class4_1)#均为同一种类Virginica
print(class4_2)#观察数据可知以属性1,3.0为界继续分类

result3_2,class4_3,class4_4=informative_attribute(class3_2,entropy(class3_2),[0,1])
print(result3_2)
#第三行第二个分叉点,选择属性0,分界点为7.2
#[0, 7.2, 0.04588249960217444]
print(class4_3)#均为virginica
print(class4_4)

result5,class5_1,class5_2=informative_attribute(class4_4,entropy(class4_4),[1])
print(result5)
print(class5_1)
print(class5_2)

将结果可视化如下:

iris数据_决策树Decision Tree(ID3算法)(UCI数据库)_第6张图片


值得注意的是,在代码中可以看到,我对sepal_length小于7.2的情况进行了尝试性的进一步分类,但是我发现分类后的两个集合仍然大部分都是Versicolor。主要是因为此时集合中,只有几个Virginica的样本,再进一步细分造成了严重的过拟合。所以在图片中我没有继续往下分。
纵观决策树生长过程,我注意到几个分叉点的分类都是将小样本从大集合中剔除出去,信息增益只有0.04左右,我们可以认为这是过拟合的一种表现。在stage2中,我会进一步修剪决策树,减少overfitting。

(3)进一步的思考和总结

1 / Now consider the case of with continuous attributes or mixed attributes (with both continuous and discrete attributes), how can we deal with the decision trees? Can you propose some approaches to do discretization?


对于离散型变量,直接遍历每一种属性的每一种取值,计算信息增益即可。
对于连续型变量,我们需要找出一种对数据分类的标准,在本次实验中,我采用的是二分的方法,对每一个变量的取值遍历,分为大于等于和小于的两部分,计算增益。如果先排序再取值,时间复杂度是N三次方。我在这次实验中,没有排序,直接遍历,时间复杂度N平方。

2 /Is there a tradeoff between the size of the tree and the model accuracy? Is there existing an optimal tree in both compactness and performance?


考虑这样的极端情况,集合D中有大量的种类A,以及唯一一个种类B。对集合D再进行一次分类,可以将B和A完全分开。显然我们认为这样的分类是过拟合了,一个优秀的模型应该具有足够强的泛化能力。剔除大样本中的小个体,得到的信息增益是十分小的。因此我对stage1中的决策树进行修建,给定一个信息增益阈值,当信息增益小于0.1时,决策树将不再进行分叉。得到结果如下:

iris数据_决策树Decision Tree(ID3算法)(UCI数据库)_第7张图片
修建后的决策树


3/For one data element, the classical decsion tree gives a hard bounday to decide which branch to follow, can you propose a “soft approach” to increase the robustness of the decision tree?
首先,决策树的决策边界都是正交直线,我们可以对边界的形状进行改变,使其尽量soft。比如说对于两个属性x1,x2,我们不再对这两个属性依次分类,可以构造类似于x1平方加x2平方小于等于1,这样的圆形边界或者其他类型的边界。

iris数据_决策树Decision Tree(ID3算法)(UCI数据库)_第8张图片


同时也可以通过许多决策树的预测平均值,提高鲁棒性。
4/Compare to the Naïve Bayes, what are the advantages and disvantages of the decision tree learning?

  1. 朴素贝叶斯基于的假设是各个变量的分布是独立的,这是一个很强的假设,可能会带来较大的误差。而决策树原理更加符合人的经验。
  2. 决策树存在过拟合,需要通过修剪树枝,平衡精确度和鲁棒性。

你可能感兴趣的:(iris数据,iris数据集,西瓜数据集3.0)