决策树——对函数的解析(超详解)

目录

一、数据集的含义

二、决策树建立的过程

三、代码解析

1、X,y的array数组

2、引入的函数包

3、计算信息熵

4、决策树类

5、训练决策树

6、递归生成决策树

7、预测结果

8、输出结果

四、辅助图示


一、数据集的含义

      根据是否是985毕业,学历,掌握的技能来评判求职者是否可以录用(这些都是一些离散的点)

二、决策树建立的过程

1、将所有的指标加入到列表中

2、计算其信息熵,保存其最小的信息熵

3、根据最小的信息熵进行划分,若能成功划分,则输出结果,若不能成功划分,则将该指标从列表中溢出后返回步骤2,并将结果添加至决策树中

三、代码解析

1、X,y的array数组

X=np.array([['Yes985','本科','C++'],
            ['Yes985','本科','Java'],
            ['No985' ,'硕士','Java'],
            ['No985' ,'硕士','C++'],
            ['Yes985','本科','Java'],
            ['No985' ,'硕士','C++'],
            ['Yes985','硕士','Java'],
            ['Yes985','博士','C++'],
            ['No985' ,'博士','Java'],
            ['No985' ,'本科','Java']])
y=np.array(['No','Yes','Yes','No','Yes','No','Yes','Yes','Yes','No'])

2、引入的函数包

import numpy as np
from collections import Counter
from math import log2

3、计算信息熵

#计算信息熵
def entropy(y_label):
    counter = Counter(y_label)
    ent = 0.0
    for num in counter.values():
        p = num / len(y_label)
        ent += -p * log2(p)
    return ent

 (1)、计算信息熵的公式:H(x) = -∑P(xi)log(2,P(xi)) (i=1,2,..n)。

(2)、counter=Counter(y_label)含义:读取标签数据,并用counter生成标签的字典数组,标签为键,值为出现的次数

4、决策树类

class DecisionTree:
    def __init__(self):
        self.tree = {}

决策树为字典类型

5、训练决策树

    def fit(self,X,y):
        cols = list(range(X.shape[1]))
        self.tree = self._genTree(cols,X,y)

1)、函数目的为:对X得每一列数据进行分割,用以计算分割后得到的信息熵

2)、shape可输出矩阵的维度,即行数和列数。shape[0]和shape[1]分别代表行和列的长度

3)、X.shape[1]是X中的列数,在本实验中共3列,故X.shape[1]的值为3

4)、range(X.shape[1])表示从0取到3,步长为默认步长:1,输出结果为[0,1,2]

6、递归生成决策树

    def _genTree(self,cols,X,y):
       
        imin=cols[0]#最小熵的列
        emin=100#最小熵值,此时imin是一个int型函数,值为0
        for i in cols:
            coli = X[:,i]#拿到第i个特征数据
            enti = sum([entropy(y[coli==d]) for d in set(coli)])
            if enti < emin:
                imin = i
                emin = enti
        newtree={}
        mincol = X[:,imin]
        cols.remove(imin)
        for d in set(mincol):
            entd = entropy(y[mincol==d])
            if entd <1e-10:
                newtree[d] = y[mincol==d][0]
            else:
                newtree[d] = self._genTree(cols.copy(),X[mincol==d,:],y[mincol==d])
        return { imin : newtree}#将列号作为索引,返回新生成的树

1)、 函数目的为:计算最小信息熵的特征

2)、coli = X[:,i]是为了拿到第i个特征数据 。X[:,i]是提取X中每一个行中的第i个元素

3)、enti = sum([entropy(y[coli==d]) for d in set(coli)])

 for d in set(coli)含义:将信息熵的转换为集合的形式,如:当coli是‘Yes985’,‘No985’这一个特征时,其输出结果只有两个值,‘Yes985’和‘No985’。特别注意:set(coli)是将coli里面重复的函数去掉,同时将其转化为集合的形式。

4)、若单看y[coli==d] for d in set(coli)时,其目的是输出y中所有满足coli==d的元素,故sum([entropy(y[coli==d]) for d in set(coli)])的含义是,将y[coli==d]作为一个标签代入到entropy()函数中,进行运算,并求和

5)、newtree={}的含义是为:根据最小熵特征有几个值,就生成几个新的子树分支 newtree={}

6)、mincol = X[:,imin]是获得最小熵特征的那一个列,当输出mincol得到

 

 说明第一次得到最小熵的列是技能这一列,将技能这一列移除后,获取技能中‘JAVA’这一分支的最小熵,即是否是985,依次获取每一分支上的最小熵,直至已经完全分开(可见最下方的图示)

7)、cols.remove(imin)是将搜索到的熵值最小的imin这一列列移除 ,再针对这个特征得每个值,进一步划分树

8)、y[mincol==d][0]:该语句是在if条件中,因为已经完全分开了,所以最后得出的结果一致,均为yes或均为no,故需要取出第一个元素

9)、newtree[d] = self._genTree(cols.copy(),X[mincol==d,:],y[mincol==d])

其中cols.copy()为复制去除最小信息熵这个特征值后的cols,然后参与下一次的递归运算,

X[mincol==d,:]是指取出所有满足mincol==d这一条件的求职者信息,直至该树的叶子结点为Yes或No为止

y[mincol==d]是指保存X[mincol==d,:]中所对应的y类别标签

10)、在改代码中,如果entd的值小于1e-10,则判断结束,否则则进行递归运算,若始终无法使entd的值小于1e-10,则当cols里面的特征值没有的时候,则不进行循环,直接输出结果

7、预测结果

 def predict(self, X):
        X=X.tolist()
        y=[None for i in range(len(X))]
        for i in range (len(X)):
            Predict_tree=self.tree
            while Predict_tree!='Yes' and Predict_tree!='No':
                cols=list(Predict_tree.keys())[0]
                Predict_tree=Predict_tree[cols]
                Predict_tree=Predict_tree[X[i][cols]]
            y[i]=Predict_tree
        return y

1)、X=X.tolist()将X转换为列表的形式,此时X是一个二维列表

2)、y=[None for i in range(len(X))]生成一个长度为len(X)的空列表

3)、进入循环,当Predict_tree为Yes或No时结束循环

4)、cols=list(Predict_tree.keys())[0]是指将最外层字典的键取出,转换为列表,取第一个元素

5)、Predict_tree=Predict_tree[cols],指用cols值所对应的分支进行向下延伸

6)、Predict_tree=Predict_tree[X[i][cols]],根据X中第i个求职者的第cols个信息进行判断

8、输出结果

dt = DecisionTree()
dt.fit(X,y)
print(dt.tree)
print(dt.predict(X))

四、辅助图示

由图可知,只有当叶子结点为Yes或No的时候,判断才结束

在本文中,采用字典的形式来表示一颗树

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值