机器学习实战决策树

一、计算香农熵
香农熵的计算公式为
在这里插入图片描述
他表示样本集合D纯度的大小,取值越小,D的纯度越高。
下面是香农熵的计算公式的代码实现。

from math import log
import numpy as np
import operator

#计算熵
def ShannonEnt(DataSet):                                                       #计算信息熵已验证
    m=len(DataSet)
    classLabelList=[data[-1] for data in DataSet]
    NumberDict={}
    for classLabel in classLabelList:
        NumberDict[classLabel]=NumberDict.get(classLabel,0)+1
    ShannonEnt=0
    for key in NumberDict.keys():
        p=NumberDict[key]/m
        ShannonEnt-=p*log(p,2)
    return ShannonEnt

这里的基本想法是遍历所有样本的最后一个元素,即样本标记。统计样本每个类的数量,从而得到P。最后所有-p*log(p,2)相加,得到香农熵。

二、根据属性及取值将数据集分开
下面我们要计算信息增益,以选择最佳属性aaa在决策树内部节点进行划分。
属性aaa的信息增益的计算公式为:
在这里插入图片描述
DvD^vDv为在属性aaa上属性取值为vvv的样本集。
信息增益越大,表示用属性aaa进行划分所获得的纯度提升越大。所以我们需要在划分过程中选取纯度提升最大属性。
在公式中由于出现DvD^vDv,所以要将DDD拆分,以获得DvD^vDv。下面为代码实现:

def splitDataSet(DataSet,axis,value):
   splitDataList=[]
   for data in DataSet:
       if data[axis]==value:
           leftData=data[:axis]
           rightData=data[axis+1:]
           leftData.extend(rightData)
           splitDataList.append(leftData)
   return splitDataList

这里我们使用的数据形式形如DataSet=[[1,1,'yes'],[1,1,'yes'],[1,0,'no']]
分割主要思路为将数据集分割为data[:axis]data[axis+1:],再将两个分割集结合,这是正好去除第axis个属性,再用append得到DvD^vDv
这里我一开始使用del删除axis属性,后来发现出现问题,主要是因为使用del删除属性,但是后面计算信息增益要遍历所有属性,使用del就会对后面的属性信息增益的计算产生影响。

`三、计算信息增益
上面由于已经计算通过代码的到DvD^vDv,所以计算信息增益很容易,然后选择信息增益最大的属性作为划分属性。
以下为代码实现:

def ChooseBestFeature(DataSet):
    CurrentInfoGain=0
    m=len(DataSet)
    d=len(DataSet[0])-1
    BestFeature=-1
    for axis in range(d):
        totalSubEnt=0
        ValueList=[data[axis] for data in DataSet]
        ValueSet=set(ValueList)
        for value in ValueSet:
            split_data=splitDataSet(DataSet,axis,value)
            p=len(split_data)/m
            subEnt=p*ShannonEnt(split_data)
            totalSubEnt+=subEnt
        InfoGain=ShannonEnt(DataSet)-totalSubEnt
        if InfoGain>CurrentInfoGain:
            CurrentInfoGain=InfoGain
            BestFeature=axis
    return BestFeature

这里还可以使用其他准则,比如信息增益比,如果是CART决策树使用基尼系数。

四、建立决策树
一颗决策树的结构如图
在这里插入图片描述
每一层决策树选择一个最佳属性划分,每层选择一个属性后又得到一个样本集,又可以的到一个决策树,所以很自然想到用递归函数。递归终止条件为如果样本集中所有样本属于同一个类,将样本划分为这一类;如果只剩下一个属性则划分为占比最多的类。以下为代码实现:

def CreateTree(DataSet,labelsOfFeature):
    ClassLabelList=[data[-1] for data in DataSet]
    ClassLabelSet=set(ClassLabelList)
    if len(ClassLabelSet)==1:
        return DataSet[0][-1]
    if len(DataSet[0])==1:
        return mojority(DataSet)
    Bestaxis=ChooseBestFeature(DataSet)
    valueList=[data[Bestaxis] for data in DataSet]
    valueSet=set(valueList)
    BestFeature=labelsOfFeature[Bestaxis]
    Tree={BestFeature:{}}
    del labelsOfFeature[Bestaxis]
    for value in valueSet:
        labels=labelsOfFeature[:]
        Tree[BestFeature][value]=\
        CreateTree(splitDataSet(DataSet,Bestaxis,value),labels)
    return Tree

这里的labelsOfFeature表示每一列所代表的特征。
这里由于需要计算最大占比类,所以这里还编写一个momojority函数计算最大占比类,代码如下:

def mojority(DataSet):
    classLabelList=[data[-1] for data in DataSet]
    NumberDict={}
    for classLabel in classLabelList:
        NumberDict[classLabel]=NumberDict.get(classLabel,0)+1
    sortNumberDict=sorted(NumberDict.items(),key=operator.itemgetter(1),reverse=True)
    MostOfClass=sortNumberDict[0][0]
    return MostOfClass

现在我们就穿件了一棵决策树,现在我们可以做个检验:

labels=['age',' spectacle prescription','astigmatic','tear production rate']
tree=[['young', 'myope', 'no', 'reduced', 'no lenses'], ['young', 'myope', 'no', 'normal', 'soft'], \
['young', 'myope', 'yes', 'reduced', 'no lenses'], ['young', 'myope', 'yes', 'normal', 'hard'], ['young', 'hyper', 'no', 'reduced', 'no lenses'], \
['young', 'hyper', 'no', 'normal', 'soft'], ['young', 'hyper', 'yes', 'reduced', 'no lenses'], ['young', 'hyper', 'yes', 'normal', 'hard'],\
 ['pre', 'myope', 'no', 'reduced', 'no lenses'], ['pre', 'myope', 'no', 'normal', 'soft'], ['pre', 'myope', 'yes', 'reduced', 'no lenses'], \
 ['pre', 'myope', 'yes', 'normal', 'hard'], ['pre', 'hyper', 'no', 'reduced', 'no lenses'], ['pre', 'hyper', 'no', 'normal', 'soft'], \
 ['pre', 'hyper', 'yes', 'reduced', 'no lenses'], ['pre', 'hyper', 'yes', 'normal', 'no lenses'], ['presbyopic', 'myope', 'no', 'reduced', 'no lenses'],\
  ['presbyopic', 'myope', 'no', 'normal', 'no lenses'], ['presbyopic', 'myope', 'yes', 'reduced', 'no lenses'], \
  ['presbyopic', 'myope', 'yes', 'normal', 'hard'], ['presbyopic', 'hyper', 'no', 'reduced', 'no lenses'], ['presbyopic', 'hyper', 'no', 'normal', 'soft'],\
   ['presbyopic', 'hyper', 'yes', 'reduced', 'no lenses'], ['presbyopic', 'hyper', 'yes', 'normal', 'no lenses']]
print(CreateTree(tree,labels))

得到:

{'tear production rate': {'normal': {'astigmatic':{'no': {'age': {'presbyopic': {' spectacle prescription':\
 {'myope': 'no lenses', 'hyper': 'soft'}}, 'pre': 'soft', 'young': 'soft'}}, 'yes': {' spectacle prescription': \
 {'myope': 'hard', 'hyper':{'age': {'presbyopic': 'no lenses', 'pre': 'no lenses', 'young': 'hard'}}}}}}, \
 'reduced': 'no lenses'}}
### 使用决策树进行隐形眼镜类型预测的机器学习实战案例 #### 数据准备 为了构建一个能够预测隐形眼镜类型的决策树模型,首先需要准备好相应的数据集。此过程涉及读取并处理来自文件的数据。 ```python with open('lenses.txt', 'r') as fr: lenses = [inst.strip().split('\t') for inst in fr.readlines()] print(lenses) lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate'] ``` 上述代码片段展示了如何打开名为 `lenses.txt` 的文件,并将其内容按行分割成列表形式存储起来[^5]。每一行代表一位患者的信息,而这些信息被进一步按照制表符分隔开。最后定义了一个标签列表 `lensesLabels` 来描述各个特征名称。 #### 构建决策树模型 接下来就是利用 Scikit-Learn 库中的 `DecisionTreeClassifier` 类来创建决策树分类器实例,并通过给定的数据对其进行训练。 ```python from sklearn import tree clf = tree.DecisionTreeClassifier() clf.fit(X_train, y_train) ``` 这里假设已经完成了对原始数据的预处理工作(例如转换字符串为数值),并将输入变量 X 和目标变量 Y 分离出来作为训练参数传递给 fit 方法完成模型拟合操作[^1]。 #### 可视化决策树结构 为了让使用者更直观地理解所建立的决策逻辑,在 Sklearn 中还提供了一项功能叫做 export_graphviz ,它可以把生成好的决策路径导出成为图形化的表达方式以便观察分析。 ```python import graphviz dot_data = tree.export_graphviz(clf, out_file=None, feature_names=lensesLabels, class_names=['hard','soft','no'], filled=True, rounded=True, special_characters=True) graph = graphviz.Source(dot_data) graph.render("lenses") # 输出为 PDF 文件 ``` 这段脚本会调用 GraphViz 工具包绘制一棵基于之前训练所得的结果展示出来的决策流程图,并保存至当前目录下命名为 "lenses.pdf"。 #### 测试与评估性能 当一切就绪之后就可以开始检验这个新造出来的工具到底有多好用了! ```python predictions = clf.predict(X_test) accuracy_score(y_true=y_test, y_pred=predictions) ``` 此处先是对一批未知样本进行了预测尝试;紧接着计算其准确性得分以衡量整体表现情况。当然还可以考虑采用交叉验证等手段获取更加稳健可靠的评价指标[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值