机器学习--决策树1(知识点项目Python代码)

决策树

概念

决策树是一种有监督的机器学习算法,该方法可以用于解决分类和回归问题。决策树可以简单地理解为达到某一特定结果的一系列决策。

优点

  1. 易于理解和解释: 决策树的结构类似于人类的决策过程,因此容易理解和解释。它们可以可视化为树状图,便于展示和沟通。
  2. 不需要大量数据预处理: 决策树模型对于数据的缺失值或异常值具有相对较好的容忍度,通常不需要大量的数据预处理。
  3. 适用于离散型和连续型数据: 决策树可以处理离散型和连续型特征,不需要对数据进行特殊的转换。
  4. 计算复杂度相对较低: 在训练阶段,决策树的计算复杂度相对较低,使得它们在处理大型数据集时效率较高。
  5. 能够处理多输出问题: 决策树可以自然地处理多输出问题,而无需进行复杂的修改。
  6. 对于特征的缩放不敏感: 决策树的算法不受特征缩放的影响,即使特征具有不同的尺度也能够很好地工作。

缺点

  1. 容易过拟合: 决策树很容易在训练数据上过拟合,特别是当树的深度较大时。为了缓解过拟合,通常需要使用剪枝技术。决策树的过拟合是指模型在训练数据上表现很好,但在未见过的测试数据上表现较差的现象。具体来说,过拟合发生在决策树过度匹配训练数据的特点和噪声,而忽略了数据中的真实模式。
  2. 不稳定性: 输入数据的微小变化可能导致生成完全不同的树结构,这使得决策树在一些情况下比较不稳定。
  3. 忽略特征之间的关联性: 决策树通常假设特征之间是独立的,因此可能忽略了特征之间的相关性,这在某些情况下可能影响模型的性能。
  4. 不适合处理复杂的关系: 决策树可能无法捕捉一些复杂的关系,特别是涉及到多个特征之间复杂交互的情况。
  5. 类别不平衡问题: 当类别的分布不平衡时,即某个类别的样本数量远远超过其他类别时,决策树可能偏向于支持样本数量更多的类别。
  6. 对噪声敏感: 决策树对于数据中的噪声和异常值相当敏感,这可能导致产生不稳定的树结构。

包含的概念

信息量

一个事件发生的概率越大,包含的信息量越小。信息量公式:

− log ⁡ 2 p i -\log_{2}{p_i} log2pi

信息熵

信息熵是对事件中不确定的信息的度量,不确定信息越大,信息熵越大。

一个系统的信息熵
E ( P ) = − ∑ i p i log ⁡ 2 p i E(P)=-\sum_{i}^{} p_i\log_{2}{p_i} E(P)=ipilog2pi
其中p_i为事件发生的概率 (相当于加权)

信息增益

信息增益 = 信息熵 - 条件熵

条件熵:在每一个小类里面,都计算一个小熵,然后每一个小熵乘以各个类别的概率,然后求和。

通俗一点就是每一类中不同属性,计算不同属性的信息熵,最后用占比、加和来求最终的条件熵

流程图

image-20231229152818414

步骤

一、求出维度条件下的条件熵和自然熵

二、算出信息增益,求解最优特征值

三、根据特征值的大小排序,创建决策树

决策树创建实战示例:公司老板发红包

例题

image-20231229152951498 image-20231229153026411

解决问题流程图

image-20231229153104357

Python代码

算法思路

1.首先如何处理原始数据?

2.如何根据现有数据集计算熵值?

3.如何找去掉最佳特征后的数据集?

4.信息增益怎么计算?(计算每一个条件熵和信息熵的差值,返回最好的信息增益的索引)

5.信息增益相同怎么划分结点?(用sort排序)

6.递归构建决策树(前面的函数找到最佳特征,和值,删掉特征标签,)

决策树代码

#计算熵值
from math import log
def calcEntroy(datas):
        datalen=len(datas)  #数据总数
        labels={}
        #统计每个标签的出现次数
        for feat in datas:
            current= feat[-1] #数据的最后一个元素,标签
            if current not in labels.keys(): #遇见的标签不在 字典的键中
                labels[current]=0   #初始化
            labels[current]+=1 
            
        entroy=0.0 #初始化熵 表示有浮点数
        
        #计算熵
        for key in labels:
            prob=float(labels[key])/datalen
            entroy-=prob*log(prob,2)
        return entroy
#原始数据集
def createDatas():
    datas=[[1,1,'发'],[1,1,'发'],[1,0,'不发'],[0,1,'不发'],[0,1,'不发']]
    labels=["是否属于某种节日","是否是该员工的生日"]
    return datas, labels
#划分数据集
def splitDatas(datas,axis,value): #需要划分的数据集 ,指定的特征, 特征对应的返回值
    returnDatas=[]
    for feat in datas:
        if feat[axis]==value:
            featcopy=feat[:axis]
            featcopy.extend(feat[axis+1:])
            returnDatas.append(featcopy)
    return returnDatas
#信息增益计算
def chooseBest(datas):
    numFlag=len(datas[0])-1 #获取凷目标变量列的数量
    base=calcEntroy(datas)
    bestGain=0.0  #初始化最佳信息熵
    bestFlag=-1 #最佳标志  数据集中哪一列最好 
    for i in range(numFlag):
        # 获取当前特征的所有取值
        lists=[feat[i] for feat in datas]
        #因为要划分子数据集,所以要集合去重,比如好几个数据,而性别只有男女
        simpleVals=set(lists)
        #计算基于当前特征的新熵值
        entroy_new=0.0
        for value in simpleVals:
            # 根据当前特征的取值划分数据集
            subDatas=splitDatas(datas,i,value)
            #计算占比
            prob=len(subDatas)/float(len(datas))
            #计算子数据集的熵值 并求和
            entroy_new+=prob*calcEntroy(subDatas)
        gain=base-entroy_new
        if gain>bestGain:
            bestGain=gain
            bestFlag=i
    return bestFlag
#信息增益相同 采用多数表决法决定叶子节点分类 表决函数
import operator
def majority(classes):
    #统计每个类别的数量
    class_num={}
    for cls in classes:
        if cls not in class_num.keys():
            class_num[cls]=0
        class_num[cls]+=1
    sorted_class_num=sorted(class_num.items(),key=operator.itemgetter(1),reverse=True)
    return sorted_class_num
def createTree(datas, labels):
    # 获取数据集中的所有类别
    classes = [example[-1] for example in datas]

    # 如果所有数据属于同一类别,返回该类别作为叶子节点
    if classes.count(classes[0]) == len(classes):
        return classes[0]

    # 如果数据集中的特征只剩下一个,返回多数表决的结果作为叶子节点
    if len(datas[0]) == 1:
        return majorityNode(classes)

    # 选择最佳的特征进行划分    由于是递归,每一次都会计算新的最佳特征值 去掉前一个最佳
    bestFlag = chooseBest(datas)
    bestFlagLabel = labels[bestFlag]
    result_tree = {bestFlagLabel: {}}

    # 删除已经使用的特征标签   
    del labels[bestFlag]

    # 获取最佳特征的所有取值
    flag_values = [example[bestFlag] for example in datas]
    unique_values = set(flag_values)

    # 对每个取值递归构建子树
    for mValue in unique_values:
        sub_labels = labels[:]
        result_tree[bestFlagLabel][mValue] = createTree(splitDatas(datas, bestFlag, mValue), sub_labels)

    # 返回构建好的决策树
    return result_tree
#测试是否分类成功
datas,labels=createDatas()
print(createTree(datas,labels))

之后会再上传

决策树绘制代码

决策树减枝

决策树预测

  • 19
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值