机器学习task_03决策树

决策树

决策树是一种机器学习的方法。决策树的生成算法有ID3, C4.5和C5.0等。决策树是一种树形结构,其中每个内部节点表示一个属性上的判断,每个分支代表一个判断结果的输出,最后每个叶节点代表一种分类结果。
决策树是一种十分常用的分类方法,需要监管学习,监管学习就是给出一堆样本,每个样本都有一组属性和一个分类结果,也就是分类结果已知,那么通过学习这些样本得到一个决策树,这个决策树能够对新的数据给出正确的分类。

##### 决策树通常有三个步骤:

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

  • 用决策树分类:从根节点开始,对实例的某一特征进行测试,根据测试结果将实例分配到其子节点,此时每个子节点对应着该特征的一个取值,如此递归的对实例进行测试并分配,直到到达叶节点,最后将实例分到叶节点的类中。
  • 决策树学习的目标:根据给定的训练数据集构建一个决策树模型,使它能够对实例进行正确的分类。
  • 决策树学习的本质:从训练集中归纳出一组分类规则,或者说是由训练数据集估计条件概率模型。
  • 决策树学习的损失函数:正则化的极大似然函数
  • 决策树学习的测试:最小化损失函数
  • 决策树学习的目标:在损失函数的意义下,选择最优决策树的问题。
  • 决策树原理和问答猜测结果游戏相似,根据一系列数据,然后给出游戏的答案。
决策树的构造

决策树学习的算法通常是一个递归地选择最优特征,并根据该特征对训练数据进行分割,使得各个子数据集有一个最好的分类的过程。这一过程对应着对特征空间的划分,也对应着决策树的构建。

1) 开始:构建根节点,将所有训练数据都放在根节点,选择一个最优特征,按着这一特征将训练数据集分割成子集,使得各个子集有一个在当前条件下最好的分类。

2) 如果这些子集已经能够被基本正确分类,那么构建叶节点,并将这些子集分到所对应的叶节点去。

3)如果还有子集不能够被正确的分类,那么就对这些子集选择新的最优特征,继续对其进行分割,构建相应的节点,如果递归进行,直至所有训练数据子集被基本正确的分类,或者没有合适的特征为止。

4)每个子集都被分到叶节点上,即都有了明确的类,这样就生成了一颗决策树。

决策树的特点:

  • 优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据。
  • 缺点:可能会产生过度匹配的问题
  • 适用数据类型:数值型和标称型

首先:确定当前数据集上的决定性特征,为了得到该决定性特征,必须评估每个特征,完成测试之后,原始数据集就被划分为几个数据子集,这些数据子集会分布在第一个决策点的所有分支上,如果某个分支下的数据属于同一类型,则当前无序阅读的垃圾邮件已经正确的划分数据分类,无需进一步对数据集进行分割,如果不属于同一类,则要重复划分数据子集,直到所有相同类型的数据均在一个数据子集内。

If so return 类标签:
Else
     寻找划分数据集的最好特征
     划分数据集
     创建分支节点
         for 每个划分的子集
             调用函数createBranch()并增加返回结果到分支节点中
         return 分支节点

使用决策树做预测需要以下过程:
  • 收集数据:可以使用任何方法。比如想构建一个相亲系统,我们可以从媒婆那里,或者通过参访相亲对象获取数据。根据他们考虑的因素和最终的选择结果,就可以得到一些供我们利用的数据了。
  • 准备数据:收集完的数据,我们要进行整理,将这些所有收集的信息按照一定规则整理出来,并排版,方便我们进行后续处理。
  • 分析数据:可以使用任何方法,决策树构造完成之后,我们可以检查决策树图形是否符合预期。
  • 训练算法:这个过程也就是构造决策树,同样也可以说是决策树学习,就是构造一个决策树的数据结构。
  • 测试算法:使用经验树计算错误率。当错误率达到了可接收范围,这个决策树就可以投放使用了。
  • 使用算法:此步骤可以使用适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义。
信息增益

什么是信息增益呢?在划分数据集之前之后信息发生的变化成为信息增益,知道如何计算信息增益,我们就可以计算每个特征值划分数据集获得的信息增益,获得信息增益最高的特征就是最好的选择。

熵定义为信息的期望值,如果待分类的事物可能划分在多个类之中,则符号xi 的信息定义为:
x
i

)=−log
2

p(x
i

决策树如何构建的问题
每个节点的位置如何确定?

特征的选择:每次选入的特征作为分裂的标准,都是使得决策树在这个节点的根据你自己选择的标准(信息熵最小、信息增益最大、gini系数最小).

每个节点在哪个值上做划分,确定分支结构呢?

遍历划分的节点的分界值操作来解决这个问题
可以想象,我们构造的决策树足够庞大,决策树可以把每一个样本都分对,那么决策树的泛化能力就可以很差了
为了解决这个问题,就需要剪枝操作了

训练算法
基于信息熵的构造
当选择某个特征作为节点时,我们就希望这个特征的信息熵越小越好,那么不确定性越小
H(x)=−pi(x)logpi(x)=−njSlognjS

nj: 第j个类别,在样本中出现的频数
S: 样本个数
对于离散属性,直接计算信息熵,连续属性,就需要划分区间,按区间计算信息熵。

基于某一层的数据集 a. 遍历计算所有属性,遍历相应属性以不同值为分截点的信息熵 b. 选择信息熵最小的作为节点
如果到达终止条件,返回相应信息,否则,按照分支重复步骤1

ID3算法: 信息增益最大化
C:类别
H©=−∑i=1mpilogpi2

按照D组划分C
H(C/D)=∑i=1v|Ci||C|H(Ci)

信息增益
gain(D)=gain©−H(C/D)

决策树单个节点选择的代码实现

def split(X,y,d,value):
'''
在d纬度上,按照value进行划分
'''
    index_a =(X[:,d]<=value)
    index_b =(X[:,d]>value)
    return X[index_a],X[index_b],y[index_a],y[index_b]
from collections import Counter
from math import log 
from numpy as np
def entropy(y):
    counter = Counter(y) # 字典
    res = 0.0
    for num in counter.values():
        p = num/len(y)
        res+=-p*log(p)
    return res
def gain(X,y,d,v):
    X_l,X_r,y_l,y_r = split(X,y,d,v)
    e = len(y_l)/len(y)*entropy(y_l)+len(y_r)/len(y)*entropy(y_r)
    return (entropy(y)-e)
def gainratio(X,y,d,v):
    X_l,X_r,y_l,y_r = split(X,y,d,v)
    gain =entropy(y) - len(y_l)/len(y)*entropy(y_l)+len(y_r)/len(y)*entropy(y_r)
    return gain/(entropy(y_l)+entropy(y_r))
def gini(y):
    counter = Counter(y)
    res = 1.0
    for num in counter.values():
        p = num / len(y)
        res += -p**2
    return res
    #X_l,X_r,y_l,y_r = split(X,y,d,v)
    #return 1-(len(y_l)/len(y))**2-(len(y_r)/len(y))**2
def try_split(X,y):
    best_entropy = float('inf')
    best_d,best_v=-1,-1
    for d in range(X.shape[1]):
        sorted_index = np.argsort(X[:,d])
        
        for i in range(1, len(X)):
            if (X[sorted_index[i],d] != X[sorted_index[i-1],d]):
                v = (X[sorted_index[i-1],d]+X[sorted_index[i],d])/2
                X_l,X_r,y_l,y_r = split(X,y,d,v)
                # 信息熵
                e = entropy(y_l)+entropy(y_r)
                #gini
                e = gini(y_l) + gini(y_r)
                # 信息增益
                e = -gain(X,y,d,v)

                if e < best_entropy:
                    best_entropy, best_d,best_v = e,d,v
    return best_entropy, best_d, best_v

# 手动来划分

data =np.array([[   0.3 ,   5   ,   2   ,   0   ],
[   0.4 ,   6   ,   0   ,   0   ],
[   0.5 ,   6.5 ,   1   ,   1   ],
[   0.6 ,   6   ,   0   ,   0   ],
[   0.7 ,   9   ,   2   ,   1   ],
[   0.5 ,   7   ,   1   ,   0   ],
[   0.4 ,   6   ,   0   ,   0   ],
[   0.6 ,   8.5 ,   0   ,   1   ],
[   0.3 ,   5.5 ,   2   ,   0   ],
[   0.9 ,   10  ,   0   ,   1   ],
[   1   ,   12  ,   1   ,   0   ],
[   0.6 ,   9   ,   1   ,   0   ],
])
X =data[:,0:3]
y = data[:,-1]
# 手动来划分
best_entropy, best_d, best_v = try_split(X, y)
print(best_entropy, best_d, best_v)
X1_l, X1_r, y1_l, y1_r = split(X,y,best_d,best_v)
print(X1_l, X1_r, y1_l, y1_r)


best_entropy2, best_d2, best_v2 = try_split(X1_r, y1_r)
X2_l, X2_r, y2_l, y2_r = split(X1_r,y1_r,best_d2,best_v2)
entropy(y2_l)

Python sklean里面tree模块里面的DecisionTreeClassifier
from sklearn import tree
clf =tree.DecisionTreeClassifier(max_depth=1,criterion ='gini') # criterion='entropy|gini'

clf = clf.fit(X,y)

训练好一颗决策树之后,我们可以使用export_graphviz导出器以Graphviz格式导出树。

import graphviz 
dot_data = tree.export_graphviz(clf, out_file=None,) 
graph = graphviz.Source(dot_data) 
graph.render("data") 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值