机器学习实战--决策树

  • 决策树概述

    决策树利用分层的概念将一个复杂的决策问题分解为多个简单的判断问题,最后逐级得到最大支持度的决策结果。

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

    决策树概念比较简单,用一个男女相亲的例子来描述决策树原理如下:

  • 示例:使用决策树实现分类器

    1. 决策树的构造

    在构造决策树时,我们需要解决的第一个问题就是,当前数据集上哪个特征在划分数据分类时起决定性作用。

    (1)信息增益

    划分数据集的最大原则是:将无序数据变得更加有序。组织杂乱无章数据的一种方法就是使用信息论度量信息,信息论是量化处理信息的分支科学。在划分数据之前和之后信息发生的变化称为信息增益,知道如何计算信息增益,我们就可以计算每个特征值划分数据集获得的信息增益,获得信息增益最高的特征就是最好的选择。

    如果待分类的事物可能划分在多个分类之中,则符号ci的信息定义为:

    其中p(ci)是选择该分类的概率。

    熵定义为信息的期望值,通过下面的公式得到:

    熵越高,则数据集混合的数据越多即数据集无序程度越高,计算香农熵的python代码如下:

    
    # 计算给定数据集的香农熵
    
    def calc_entropy(self,data_set):
        # 获取数据集大小
        entries_num = len(data_set)
        label_counts = {}
        for feat_vec in data_set:
            # 每个数据示例的最后一列存储的是类别信息
            current_label = feat_vec[-1]
            # 判断当前类别是否在类库中,如果不存在则初始化为1,如果存在则将数量增1
            if current_label not in label_counts.keys():
                label_counts[current_label] = 0
            label_counts[current_label] += 1
        entrop = 0.0
        for key in label_counts:
            # 计算当前类别出现的概率
            prob = float(label_counts[key])/entries_num
            entrop -= prob * log(prob, 2)
        return entrop

    (2)划分数据集

    循环计算所有特征划分数据集后的香农熵,并利用原始数据集的熵和划分后的熵相减得到该特征划分的信息增益。取信息增益最大的划分,作为最好的划分方式。

    
    # 按照给定特征划分数据集
    
    # dataset-待划分数据集 axis-划分数据集的特征 value-需要返回的特征的值
    
    def split_dataset(self,dataset, axis, value):
        # 创建新的数据集,避免破坏原数据集结构
        new_dataset = []
        for feat_vec in dataset:
            # 如果某个实例的指定特征值符合要求,则剔除此特征后,将本实例加入划分后的数据集
            if feat_vec[axis] == value:
                reduce_feat_vec = feat_vec[:axis]
                reduce_feat_vec.extend(feat_vec[axis+1:])
                new_dataset.append(reduce_feat_vec)
        return new_dataset
    
    # 选择最好的数据集划分方式
    
    def choose_best_feature_to_split(self, dataset):
        # 获取特征向量中特征的个数
        feature_nums = len(dataset[0]) - 1
        # 计算原数据集香农熵
        base_entropy = self.calc_entropy(dataset)
        best_info_gain = 0.0
        best_feature = -1
        for i in range(feature_nums):
            # 获取所有实例中,指定特征的特征值列表
            feat_list = [example[i] for example in dataset]
            # 去除特征值列表中重复值
            unique_vals = set(feat_list)
            new_entropy = 0.0
            for value in unique_vals:
                # 为指定特征的所有不同的值划分数据集
                sub_dataset = self.split_dataset(dataset, i ,value)
                prob = len(sub_dataset)/float(len(dataset))
                # 计算利用此特征划分数据集后的香农熵
                new_entropy += prob * self.calc_entropy(sub_dataset)
            # 计算利用此特征划分数据集后的信息增益
            info_gain = base_entropy - new_entropy
            # 取信息增益最大的特征划分数据集
            if info_gain > best_info_gain:
                best_info_gain = info_gain
                best_feature = i
        return best_feature

    (3)递归构建决策树

    递归构建决策树工作原理如下:得到原始数据集,然后基于最好的特征值划分数据集,由于特征值可能多于两个,因此可能存在大于两个分支的数据集划分。第一次划分之后,数据将被向下传递到树分支的下一个节点,在这个节点上我们可以再次划分数据。因此我们可以采用递归的原则处理数据集。

    递归结束的条件是:程序遍历完所有划分数据集的特征,或者每个分支下的所有实例都具有相同的分类。如果所有实例具有相同的分类,则得到一个叶子节点或者终止块,任何到达叶子节点的数据必然属于叶子节点的分类。

    如果数据集已经处理了所有属性,但是类标签依然不是唯一的,此时我们需要决定如何定义该叶子节点,在这种情况下,我们通常会采用多数表决的方法决定该叶子节点的分类。

    
    # 利用投票表决的方式来决定叶子节点的分类
    
    def majority_cnt(self, class_list):
        class_count = {}
        for vote in class_list:
            if vote not in class_count.keys():
                class_count[vote] = 0
            class_count[vote] += 1
        sorted_class_count = sorted(class_count.iteritems(),key=operator.itemgetter(1),reverse=True)
        return sorted_class_count[0][0]

    最终,创建决策树的代码如下:

    
    # 创建决策树
    
    # dataset-数据集 labels-标签列表,包含数据集中所有特征的名称
    
    def creat_tree(self, dataset, labels):
        # 创建包含数据集所有类标签的列表
        class_list = [example[-1] for example in dataset]
        # 如果类标签列表中的所有类标签相同则返回此类标签
        if class_list.count(class_list[0]) == len(class_list):
            return class_list[0]
        # 如果所有特征都被使用完,则利用投票方法选举出类标签返回
        if len(dataset[0]) == 1:
            return self.majority_cnt(class_list)
        # 获取最好的数据集划分方式
        best_feat = self.choose_best_feature_to_split(dataset)
        best_feat_label = labels[best_feat]
        my_tree = {best_feat_label:{}}
        del(labels[best_feat])
        feat_values = [example[best_feat] for example in dataset]
        unique_vals = set(feat_values)
        for value in unique_vals:
            sub_labels = labels[:]
            my_tree[best_feat_label][value] = self.creat_tree(self.split_dataset(dataset,best_feat,value), sub_labels)
        return my_tree
    

    2. 测试和存储分类器

    我们以上已经完成了决策树的所有创建工作,加入以下代码进行测试即可:

    
    # 创建训练数据集
    
    # dataset-训练数据集 labels-特征名称
    
    def creat_dataset(self):
        dataset = [[1, 1, ‘yes‘],
                   [1, 0, ‘no‘],
                   [0, 1, ‘no‘],
                   [0, 1, ‘no‘]]
        labels = [‘不浮出水面是否可以生存‘, ‘是否有脚蹼‘]
        return dataset,labels
    
    # 决策树分类器
    
    def classify(self, input_tree, feat_labels, test_vec):
        first_str = input_tree.keys()[0]
        second_dict = input_tree[first_str]
        feat_index = feat_labels.index(first_str)
        for key in second_dict.keys():
            if test_vec[feat_index] == key:
                if type(second_dict[key]).__name__ == ‘dict‘:
                    class_label = self.classify(second_dict[key], feat_labels, test_vec)
                else:
                    class_label = second_dict[key]
        return class_label
    
    def test_classify(self):
        dataset,labels = self.creat_dataset()
        feat_labels = []
        feat_labels.extend(labels)
        decision_tree = self.creat_tree(dataset,feat_labels)
        test_vec = [1,0]
        print self.classify(decision_tree,labels,test_vec)
    

    我们还存在一个问题,每次训练一颗决策树耗费大量的时间与物理资源,所以我们需要将训练好的决策树储存到物理磁盘上,以便进行分类预测时进行调用:

    
    # 将训练好的决策树存入磁盘    
    
    def store_tree(self, input_tree, file_name):
        import pickle
        fw = open(file_name, ‘w‘)
        pickle.dump(input_tree, fw)
        fw.close()
    
    # 从磁盘读取预存的决策树
    
    def grab_tree(self,file_name):
        import pickle
        fr = open(file_name)
        return pickle.load(fr)
时间: 2024-08-04 11:03:52

机器学习实战--决策树的相关文章

[机器学习&数据挖掘]机器学习实战决策树plotTree函数完全解析

在看机器学习实战时候,到第三章的对决策树画图的时候,有一段递归函数怎么都看不懂,因为以后想选这个方向为自己的职业导向,抱着精看的态度,对这本树进行地毯式扫描,所以就没跳过,一直卡了一天多,才差不多搞懂,才对那个函数中的plotTree.xOff的取值,以及计算cntrPt的方法搞懂,相信也有人和我一样,希望能够相互交流. 先把代码贴在这里: import matplotlib.pyplot as plt #这里是对绘制是图形属性的一些定义,可以不用管,主要是后面的算法 decisionNode

机器学习实战——决策树

from math import log #以决策为标准计算信息熵 def calcShannonEnt(dataSet): numEntries = len(dataSet) labelCounts = {} for featVec in dataSet: currentLabel = featVec[-1] if currentLabel not in labelCounts.keys(): labelCounts[currentLabel] = 0 labelCounts[currentL

机器学习实战-决策树(ID3)

//==================================================== 决策树的构造: 构造决策树时,需要解决的第一个问题是,当前数据集上那个特征在划分数据是起决定性作用.为了找到决定性特征,我们必须使用某种度量来评估每个特征.完成评估之后,找到决定性特征,使用该特征划分数据,原始的数据集就被划分为几个数据子集.这个子集会发布在第一个决策点的所有分支.如果某个分支下的数据属于同一类型,则当前已经准确划分数据分类.如果数据子集内的数据不属于同一类型,则需要重复

【读书笔记】机器学习实战-决策树(1)

简述算法 上一章的kNN更像是应用统计知识来进行科学的预测,它可以完成许多分类任务.但是最大的缺点就是无法给出数据的内在含义,而决策树算法数据形式非常便于理解.决策树的结果经常会应用到专家系统当中. 构建一棵决策树的流程: 检测数据集中每一个子祥的属性是否属于同一类 if so return 类标签: else 寻找划分数据集的最好特征 划分数据集 创建分支结点 for 每个划分的子集 调用createBranch并增加返回结果到分支结点中 return 分支结点 决策树的一般流程 收集数据 准

机器学习实战—决策树(二)

#-*-coding:utf-8-*- import ch ch.set_ch() import matplotlib.pyplot as plt decisionNode = dict(boxstyle = "sawtooth",fc="0.8") leafNode = dict(boxstyle="round4",fc = "0.8") arrow_args = dict(arrowstyle = "<-&

决策树代码《机器学习实战》

22:45:17 2017-08-09 KNN算法简单有效,可以解决很多分类问题.但是无法给出数据的含义,就是一顿计算向量距离,然后分类. 决策树就可以解决这个问题,分类之后能够知道是问什么被划分到一个类.用图形画出来就效果更好了,这次没有学哪个画图的,下次. 这里只涉及信息熵的计算,最佳分类特征的提取,决策树的构建.剪枝没有学,这里没有. 1 # -*- oding: itf-8 -*- 2 3 ''' 4 function: <机器学习实战>决策树的代码,画图的部分没有写: 5 note:

机器学习实战读书笔记(三)决策树

3.1 决策树的构造 优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据. 缺点:可能会产生过度匹配问题. 适用数据类型:数值型和标称型. 一般流程: 1.收集数据 2.准备数据 3.分析数据 4.训练算法 5.测试算法 6.使用算法 3.1.1 信息增益 创建数据集 def createDataSet(): dataSet = [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, '

机器学习实战笔记3(决策树)

决策树的优势就在于数据形式非常容易理解,而kNN的最大缺点就是无法给出数据的内在含义. 1:简单概念描述 决策树的类型有很多,有CART.ID3和C4.5等,其中CART是基于基尼不纯度(Gini)的,这里不做详解,而ID3和C4.5都是基于信息熵的,它们两个得到的结果都是一样的,本次定义主要针对ID3算法.下面我们介绍信息熵的定义. 事件ai发生的概率用p(ai)来表示,而-log2(p(ai))表示为事件ai的不确定程度,称为ai的自信息量,sum(p(ai)*I(ai))称为信源S的平均信

机器学习实战之一---简单讲解决策树

机器学习实战之一---简单讲解决策树 https://blog.csdn.net/class_brick/article/details/78855510 前言:本文基于<机器学习实战>一书,采用python语言,对于机器学习当中的常用算法进行说明. 一. 综述 定义:首先来对决策树进行一个定义,决策树是一棵通过事物的特征来进行判断分支后得到该事物所需要的预测的属性的树. 流程:提取特征à计算信息增益à构建决策树à使用决策树进行预测 关键:树的构造,通过信息增益(熵)得到分支点和分支的方式.