决策树id3算法_手写决策树系列算法之ID3

上上周阿里面试的笔试题,手写ID3决策树算法。。。很不幸的挂了,ID3几年没用了。。这次好好总结一下。

信息熵是通信原理中常见的概率,用于衡量抽象的“信息量”大小的概念,在ID3中使用的信息熵公式为:

equation?tex=Ent%28D%29%3D-%5Csum_%7Bk%3D1%7D%5E%7B%7Cy%7C%7D%7BP_%7Bk%7D%2Alog2%28p_%7Bk%7D%29%7D

Pk表示随机事件在总时间中发生的概率,后面那一项显然表示概率的对数值,这里使用常见的2为底数,这样的信息熵的单位为byte,|y|表示事件的数量。

从大白话的角度来说,这里的P表示类别标签中某一个类别出现的概率。|y|表示类别的总数,根据这个公式,假设我们的类别只有1个,则带入计算Ent=0,如果类别有64个并且每个类别都只有一个则计算可得Ent=6,显然,类别的数量越大,则Ent的计算结果越大。ID3以此来衡量数据集的纯度,Ent的值越小则纯度越高

而信息增益用于衡量 是否对某个类别特征的划分,如果信息增益为正则划分否则不划分。

equation?tex=Gain%28D%2Ca%29%3DEnt%28D%29-%5Csum_%7Bv%3D1%7D%5E%7BV%7D%7B%5Cfrac%7B%7CD%5E%7Bv%7D%7C%7D%7BD%7D%2AEnt%28D%5E%7Bv%7D%29%7D

假设某个类别特征有(a,b,c)三类,则根据ID3的算法,是直接按照a,b,c把所有样本分成3类,这和cart,xgb,lgb等目前常用的决策树算法完全不用,ID3本质上算是多分类树,并且根据ID3的算法原理,ID3只能处理全是类别的特征集,对于连续值无能为力。

那么这里式子的含义很好理解了,就是分类之后每一个数据子集的信息熵计算之后乘上一个权重系数(子数据集的样本数量/总样本数量)然后求和,就得到了划分之后的所有数据集的总信息熵,和原来的信息熵进行比较即可。

很明显ID3存在着以下不足:

a)ID3没有考虑连续特征,比如长度,密度都是连续值,无法在ID3运用。这大大限制了ID3的用途。
b)ID3采用信息增益大的特征优先建立决策树的节点。很快就被人发现,在相同条件下,取值比较多的特征比取值少的特征信息增益大。因为类别特征中的每一个类别越多,往往每一个小类别的信息熵会很低,从而整体信息熵虚低,举一个极端的例子,假设某个类别只有一个,则信息熵直接等于0
c) ID3算法对于缺失值的情况没有做考虑
d) 没有考虑过拟合的问题

另外id3和c4.5每次用完一个特征之后后续分裂就不会再用了,这显然并不是一个好的分裂逻辑。

import numpy as np
import operator
#dataset是特征矩阵,y是标签值,为了简单起见这里假设y是0,1类别

def cal_Ent(y0,y1): #用于计算每一个类别的每一个类的信息熵,y表示其对应的标签值
    total=y0+y1 #y0,y1分别表示类别1和类别0的数量
    y1=sum(y)/total#计算类别1的占比,就是公式中的pk
    y0=(length-y1)/total#计算类别0的占比
    Ent=-(y1*np.log2(y1)+y0*np.log2(y0))# 根据信息熵的公式计算信息熵
    return Ent

def ID3(dataset,y):
    #dataset是特征矩阵,y是标签值,为了简单起见这里假设y是0,1类别
    all_feature_ent=[]
    all_feature_col=[]
    y0=y[y==0]
    y1=y[y==1]
    orginal_ent=cal_Ent(y0,y1)
    dataset['y']=y
    for col in dataset.columns:
        if col=='y':
            continue
        y1=dataset.groupby([col])['y'].apply('sum'))#对每一列的类别特征中的每一个类别
#计算类别1的数量
        y0=dataset[col].value_counts()-y #计算每一类别中0的数量
        feature_ent=[]
        for i in range(len(y1)):
            feature_ent.append(cal_Ent(y0[i],y1[i])) ##计算当前类别特征中每一个类别对应的信息熵
        if sum(feature_ent)<original_ent:#如果当前特征分裂之后的信息熵之和小于原始的信息熵则列入
#待选择分裂的特征,记住,信息熵越小说明不确定越小则越好
            all_feature_ent.append(sum(feature_ent))##存放所有信息增益大于0的信息熵值
            all_feature_col.append(col) ##存放入选 特征的名字 
    return all_feature_ent,all_feature_col

决策树写起来确实挺麻烦的。。。单纯为了理解算法,所以就不调bug了。。实现也不完整,ID3每次分裂用过的特征就不会再用了,然后就是循环上述操作就是了,行了差不多就这样。。。下次笔试还是写伪代码吧。。。那么点时间要完整写完一个可以用的算法对我这个菜鸡来说比较费劲。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值