机器学习--决策树(ID3)算法

一、基本原理

    决策树是一个预测模型。它代表的是对象属性与对象值之间的一种映射关系。树中每个节点表示某个对象,每个分支路径代表某个可能的属性值,每个叶结点则对应从根节点到该叶节点所经历的路径所表示的对象的值。一般情况下,决策树由决策结点、分支路径和叶结点组成。在选择哪个属性作为结点的时候,采用信息论原理,计算信息增益,获得最大信息增益的属性就是最好的选择。信息增益是指原有数据集的熵减去按某个属性分类后数据集的熵所得的差值。然后采用递归的原则处理数据集,并得到了我们需要的决策树。   

二、算法流程

    检测数据集中的每个子项是否属于同一分类:

        If 是,则返回类别标签;

        Else             

           计算信息增益,寻找划分数据集的最好特征          

           划分数据数据集

           创建分支节点(叶结点或决策结点)

               for 每个划分的子集

                   递归调用,并增加返回结果到分支节点

           return 分支结点

三、算法的特点

    优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据。
    缺点:可能会产生过度匹配问题
    适用数据范围:数值型和标称型。
 
四、python代码实现
 
1、创建初始数据集,用于测试
 

######################################
#功能:创建数据集
#输入变量:空
#输出变量:data_set, labels 数据集,标签
######################################
def create_data_set():

    data_set = [[1, 1, 'yes'],  
                [1, 1, 'yes'],
                [1, 0, 'no'],
                [0, 1, 'no'],
                [0, 1, 'no']]    #  数据集最后一列表示叶结点,也称类别标签
    labels = ['no surfacing', 'flippers']   # 表示决策结点,也称特征标签

    return data_set, labels

 
2、计算给定数据集的信息熵
 

#############################
#功能:计算信息熵
#输入变量:data_set 数据集
#输出变量:shannon_ent 信息熵
#############################
def calc_shannon_ent(data_set):

    num_entries = len(data_set)
    label_counts = {}

    for feat_vec in data_set:
        current_label = feat_vec[-1]
        # get相当于一条if...else...语句
        # 如果参数current_label不在字典中则返回参数0,
        # 如果current_label在字典中则返回current_label对应的value值
        label_counts[current_label] = label_counts.get(current_label, 0) + 1

    shannon_ent = 0.0

    for key in label_counts:
        prob = float(label_counts[key])/num_entries
        shannon_ent -= prob*log(prob, 2)

    return shannon_ent

 

3、按照给定特征划分数据集。分类算法除了需要测量信息熵,还需要划分数据集,这就需要对每个特征划分数据集的结果计算一次信息熵,然后判断按照哪个特征划分数据集是最好的划分方式。

#################################
#功能:划分数据集
#输入变量:data_set, axis, value
# 数据集,数据集的特征,特征的值
#输出变量:ret_data_set, 划分后的数据集
#################################

def split_data_set(data_set, axis, value):

    ret_data_set = []

    for feat_vec in data_set:
        if feat_vec[axis] == value:

            # 把axis特征位置之前和之后的特征值切出来
            # 没有使用del函数的原因是,del会改变原始数据
            reduced_feat_vec = feat_vec[:axis]
            reduced_feat_vec.extend(feat_vec[axis+1:])
            ret_data_set.append(reduced_feat_vec)

    return ret_data_set

 

4、遍历整个数据集,循环划分数据并计算信息熵,通过计算最大信息增益来找到最好的特征划分方式。

具体做法是,遍历当前特征中的所有唯一属性值,对每个特征划分一次数据集,然后计算数据集的新熵值,并对所有唯一特征值得到的熵求和。最后用所求的和值与原始信息熵相减,计算寻找最大信息增益。

######################################
#功能:选择最好的数据集划分方式
#输入变量:data_set 待划分的数据集
#输出变量:best_feature 计算得出最好的划分数据集的特征
######################################
def choose_best_feature_to_split(data_set):

    num_features = len(data_set[0]) - 1  # 最后一个是类别标签,所以特征属性长度为总长度减1
    base_entropy = calc_shannon_ent(data_set)  # 计算数据集原始信息熵

    best_info_gain = 0.0
    best_feature = -1

    for i in xrange(num_features):

        # feat_vec[i]代表第i列的特征值,在for循环获取这一列的所有值
        feat_list = [feat_vec[i] for feat_vec in data_set]
        unique_vals = set(feat_list)  # set函数得到的是一个无序不重复数据集

        new_entropy = 0.0

        # 计算每种划分方式的信息熵
        for value in unique_vals:

            sub_data_set = split_data_set(data_set, i, value)
            prob = len(sub_data_set)/float(len(data_set))
            new_entropy += prob*calc_shannon_ent(sub_data_set)

        info_gain = base_entropy - new_entropy

        if info_gain > best_info_gain:

            best_info_gain = info_gain
            best_feature = i

    return best_feature

 

5、递归构建决策树

工作原理:得到原始数据集,然后基于最好的属性值划分数据集,由于特征值可能多于两个,因此可能存在大于两个分支的数据集划分。第一次划分之后,数据将被向下传递到树分支的下一个节点,在这个节点上,我们可以再次划分数据。因此我们可以采用递归的原则处理数据集。
递归结束条件是:第一、所有的类别标签(叶结点)完全相同。第二、使用完了所有的特征,仍然不能将数据集划分成仅包含唯一类别的分组,则挑选出次数最多的类别作为返回值。
 

######################################
#功能:多数表决分类
#输入变量:class_list 所有数据的标签数组
#输出变量:sorted_class_count[0][0] 出现次数最多的分类名称
######################################
def majority_vote_sort(class_list):

    class_count = {}

    for vote in class_list:
        class_count[vote] = class_count.get(vote, 0) + 1

    # items以列表方式返回字典中的键值对,iteritems以迭代器对象返回键值对,而键值对以元组方式存储,即这种方式[(), ()]
    # operator.itemgetter(0)获取对象的第0个域的值,即返回的是key值
    # operator.itemgetter(1)获取对象的第1个域的值,即返回的是value值
    # operator.itemgetter定义了一个函数,通过该函数作用到对象上才能获取值
    # reverse=True是按降序排序
    sorted_class_count = sorted(class_count.iteritems(), key=operator.itemgetter(1), reverse=True)

    return sorted_class_count[0][0]

 

######################################
#功能:创建数
#输入变量:data_set, labels 待分类数据集,标签
#输出变量:my_tree 决策树
######################################
def create_tree(data_set, labels):

    class_list = [example[-1] for example in data_set]

    # 判断类别标签是否完全相同
    # count()是列表内置的方法,可以统计某个元素在列表中出现的次数
    if class_list.count(class_list[0]) == len(class_list):
        return class_list[0]

    # 遍历完所有特征时返回出现次数最多的
    if len(data_set[0]) == 1:
        return majority_vote_sort(class_list)

    best_feat = choose_best_feature_to_split(data_set)
    best_feat_label = labels[best_feat]
    my_tree = {best_feat_label: {}}
    del(labels[best_feat])

    # 得到列表包含的所有属性值
    feat_values = [example[best_feat] for example in data_set]
    unique_vals = set(feat_values)

    for value in unique_vals:

        sub_labels = labels[:]  # :复制特征标签,为了保证循环调用函数create_tree()不改变原始的内容
        ret_data_set = split_data_set(data_set, best_feat, value)
        my_tree[best_feat_label][value] = create_tree(ret_data_set, sub_labels)

    return my_tree

 

6、测试代码

def main():

    my_data, my_labels = create_data_set()
    #my_data[0][-1] = 'maybe'
    print 'my_data=', my_data
    print 'my_labels=', my_labels

    shannon_ent = calc_shannon_ent(my_data)
    print 'shannon_ent=', shannon_ent

    ret_data_set = split_data_set(my_data, 1, 1)  # 由第1个特征且特征值为1的数据集划分出来
    print 'ret_data_set=', ret_data_set

    best_feature = choose_best_feature_to_split(my_data)
    print 'best_feature=', best_feature

    my_tree = create_tree(my_data, my_labels)
    print 'my_tree=', my_tree


if __name__ == '__main__':
    main()

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
决策树算法机器学习中常用的一种算法,它通过构建一棵树形结构来进行分类或回归任务。决策树算法有多种不同的变体,其中包括ID3算法、C4.5算法和基本决策树算法ID3算法是最早提出的一种决策树算法,它的核心思想是通过计算信息增益来选择最佳的特征进行节点的划分。具体步骤是:从根节点开始,计算每个特征的信息增益,选择信息增益最大的特征作为当前节点的划分特征,然后根据该特征的不同取值建立子节点,再对子节点递归地应用以上步骤,直到所有的特征信息增益很小或没有特征可选为止。 C4.5算法是对ID3算法的改进,它引入了信息增益率(比)来选择特征,解决了ID3算法对于取值较多的特征有偏好的问题。与ID3算法相似,C4.5算法也使用递归的方式构建决策树,但在选择划分特征时,使用信息增益率作为选择的依据。 基本决策树算法决策树算法的一种简化版,它没有引入信息增益或信息增益率,而是通过计算基尼指数来选择最佳的划分特征。基尼指数衡量了一个特征的不纯度,选择基尼指数最小的特征进行划分。基本决策树算法相对于ID3算法和C4.5算法更简单直观,但在某些情况下可能会有一定的性能损失。 总的来说,决策树算法通过构建一棵树形结构来进行分类或回归任务,其中ID3算法、C4.5算法和基本决策树算法是其中的三种常见变体。每种算法都有其特点和优缺点,选择适合具体问题的算法可以提高算法的性能和准确性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [机器学习算法(3)之决策树算法](https://blog.csdn.net/qq_20412595/article/details/82048795)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值