决策树

目录

决策树的构造

 信息增益

划分数据集

递归构建决策树

使用Matplotlib注解绘制树形图


决策树是最经常使用的数据挖掘算法。

决策树的构造

决策树的一般流程:

  1. 收集数据:可以使用任何方法;
  2. 准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化;
  3. 分析数据:可以使用任何方法,构造树完成之后骂我们应该检查图形是否符合预期;
  4. 训练算法:构造树的数据结构;
  5. 测试算法:使用经验树计算错误率;
  6. 使用算法:此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义。

 信息增益

划分数据集的大原则是:将无序的数据变得更加有序。组织杂乱无章数据的一种方法就是使用信息论度量信息,信息论是量化处理信息的分支科学。

再换分数剧集之前之后发生的变化成为信息增益,获得信息增益最高的特征就是最好的选择。

“熵”——描述为信息的期望值

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

l(x_i)=-\log_2p(x_i)

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

为了计算熵,我们需要计算所有类别多有可能值包含的信息期望值,通过下面的公式得到:

H=-\sum_{i=1}^np(x_i)\log_2p(x_i)

计算给定数据集香农熵的代码:

from math import log


def calc_shannon_entropy(data_set):
    num_entries = len(data_set)
    label_counts = {}
    for feat_vec in data_set:
        current_label = feat_vec[-1]
        if current_label not in label_counts.keys():
            label_counts[current_label] = 0
        label_counts[current_label] += 1
    shannon_entropy = 0.0
    for key in label_counts:
        prob = float(label_counts[key])/num_entries
        shannon_entropy -= prob * log(prob, 2)
    return shannon_entropy

构造一个简单的数据集来计算香农熵:

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


if __name__ == '__main__':
    data_set, labels = create_data_set()
    shannon_entropy = calc_shannon_entropy(data_set)
    print("shannon entropy: %f" % shannon_entropy)

结果:

shannon entropy: 0.970951

熵越高,则混合的数据也越多。数据集中的分类增大时,则熵增大。

划分数据集

def split_data_set(data_set, axis, value):
    """
    按照给定特征划分数据集
    :param data_set:
    :param axis:
    :param value:
    :return:
    """
    return_data_set = []
    for feat_vec in data_set:
        if feat_vec[axis] == value:
            reduced_feat_vec = feat_vec[:axis]
            reduced_feat_vec.extend(feat_vec[axis+1:])
            return_data_set.append(reduced_feat_vec)
    return return_data_set

一个按照人为设定的特征划分的结果:

if __name__ == '__main__':
    data_set, labels = create_data_set()
    
    # 测试不同的数据划分方式
    print("按axis=0, value=1 的划分结果: ", split_data_set(data_set, 0, 1))
    print("按axis=0, value=0 的划分结果: ", split_data_set(data_set, 0, 0))

那么按照什么样的特征进行划分呢?

——选择最大信息增益的特征进行划分

Gain = H_{base}-H_{new}

这里设置原始香农熵base_entropy = 0, 选择最好划分特征的代码如下:

def choose_best_feature_to_split(data_set):
    """
    选择最好的数据集划分方式
    :param data_set:
    """
    num_features = len(data_set[0]) - 1
    base_entropy = calc_shannon_entropy(data_set)
    best_info_gain = 0.0
    best_feature = -1
    for i in range(num_features):
        feature_list = [example[i] for example in data_set]
        unique_values = set(feature_list)
        new_entropy = 0.0
        for value in unique_values:
            sub_data_set = split_data_set(data_set, i, value)
            prob = len(sub_data_set)/float(len(data_set))
            new_entropy += prob * calc_shannon_entropy(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

结果:

data_set, labels = create_data_set()
best_feature = choose_best_feature_to_split(data_set)
    print("best feature: %d" % best_feature)

递归构建决策树

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

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

def create_tree(data_set, labels):
    """
    创建树的函数代码
    :param data_set:
    :param labels:
    """
    class_list = [data[-1] for data in data_set]
    # 类别完全相同时停止继续划分
    if class_list.count(class_list[0]) == len(class_list):
        return class_list[0]
    # 遍历完所有特征时返回出现次数最多的
    if len(data_set[0]) == 1:
        return majority_cnt(class_list)
    best_feature = choose_best_feature_to_split(data_set)
    best_feature_label = labels[best_feature]
    tree = {best_feature_label: {}}
    del labels[best_feature]
    feature_values = [data[best_feature] for data in data_set]
    unique_values = set(feature_values)
    for value in unique_values:
        sub_labels = labels[:]
        tree[best_feature_label][value] = create_tree(split_data_set(data_set, best_feature, value), sub_labels)
    return tree

得到决策树的结果:

data_set, labels = create_data_set()
tree = create_tree(data_set, labels)
print("tree: ", tree)
tree:  {'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}

使用Matplotlib注解绘制树形图

Matplotlib 提供了一个注解工具annotations,它可以在数据图形上添加文本注解。

你可能感兴趣的:(Machine,Learning)