【统计学习方法】决策树

特征选择

信息增益

信息熵

信息熵就是用来表示随机变量不确定性的度量。随机变脸的熵可以定义为:
H ( x ) = − ∑ i = 1 n p i l o g p i (1) H(x) = -\sum_{i=1}^{n}p_ilogp_i \tag{1} H(x)=i=1npilogpi(1)
我们以贷款申请样本数据表为例子。

ID年龄有工作有自己的房子信贷情况类别
1青年一般
2青年
3青年
4青年一般
5青年一般
6中年一般
7中年
8中年
9中年非常好
10中年非常好
11老年非常好
12老年
13老年
14老年非常好
15老年一般
条件信息熵

G ( D , A ) = H ( D ) − H ( D ∣ A ) (2) G(D,A) = H(D) - H(D|A) \tag{2} G(D,A)=H(D)H(DA)(2)

基尼指数

在分类任务中,假设有K个类别,样本点属于第k类的概率是 p k p_k pk,那么概率分布的基尼指数定义为:
G i n i ( p ) = ∑ k = 1 K p k ( 1 − p k ) = ∑ k = 1 K p k − ∑ k = 1 K p k 2 = 1 − ∑ k = 1 K p k 2 (1) \begin{aligned} Gini(p) =& \sum_{k=1}^{K}p_k(1-p_k) \\ =& \sum_{k=1}^{K}p_k -\sum_{k=1}^{K}p_k^2 \\ =& 1 - \sum_{k=1}^{K}p_k^2 \tag{1} \end{aligned} Gini(p)===k=1Kpk(1pk)k=1Kpkk=1Kpk21k=1Kpk2(1)
在给定特征A的条件下,集合D的基尼指数可以定义为:
G i n i ( D , A ) = ∣ D 1 ∣ ∣ D ∣ G i n i ( D 1 ) + ∣ D 2 ∣ ∣ D ∣ G i n i ( D 2 ) Gini(D,A) = \frac{|D_1|}{|D|}Gini(D_1) + \frac{|D_2|}{|D|}Gini(D_2) Gini(D,A)=DD1Gini(D1)+DD2Gini(D2)

信息增益比

以信息增益作为划分训练数据集的特征,存在偏向于选择取值较多的特征问题,使用信息增益比可以对这个问题进行校正,这是特征选择的另一准则。
特征A对训练数据集D的信息增益比 g R ( D , A ) = g ( D , A ) H A ( D ) g_R(D,A) = \frac{g(D,A)}{H_A(D)} gR(D,A)=HA(D)g(D,A),其中 H A ( D ) = ∑ i = 1 n ∣ D i ∣ ∣ D ∣ l o g 2 ∣ D i ∣ ∣ D ∣ H_A(D) = \sum_{i=1}^{n}\frac{|D_i|}{|D|}log_2\frac{|D_i|}{|D|} HA(D)=i=1nDDilog2DDi

决策树生成

ID3

'''
Author: your name
Date: 2020-08-08 11:52:19
LastEditTime: 2020-08-22 16:43:41
LastEditors: Please set LastEditors
Description: In User Settings Edit
FilePath: /统计学习方法/决策树/main.py
'''
# %%
import random
import numpy as np
import pprint
from math import log
from collections import Counter
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
from collections import defaultdict

import math
import pandas as pd
from graphviz import Digraph
import networkx as nx
import matplotlib.pyplot as plt
# 书上题目5.1
g = Digraph('决策树')


def H(D: pd.DataFrame, condition=None, class_label='class') -> float:
    class_list = D.groupby(class_label).size().to_list()
    total = sum(class_list)
    entropy = -1 * sum([c_num / total * math.log2(c_num / total)
                        for c_num in class_list])
    if condition is not None:
        condition_entropy = sum(D.groupby(condition).apply(
            lambda x: len(x)/len(D) * H(x)))
        return entropy - condition_entropy
    else:
        return entropy


def create_data():
    datasets = [['青年', '否', '否', '一般', '否'],
                ['青年', '否', '否', '好', '否'],
                ['青年', '是', '否', '好', '是'],
                ['青年', '是', '是', '一般', '是'],
                ['青年', '否', '否', '一般', '否'],
                ['中年', '否', '否', '一般', '否'],
                ['中年', '否', '否', '好', '否'],
                ['中年', '是', '是', '好', '是'],
                ['中年', '否', '是', '非常好', '是'],
                ['中年', '否', '是', '非常好', '是'],
                ['老年', '否', '是', '非常好', '是'],
                ['老年', '否', '是', '好', '是'],
                ['老年', '是', '否', '好', '是'],
                ['老年', '是', '否', '非常好', '是'],
                ['老年', '否', '否', '一般', '否'],
                ]
    labels = [u'age', u'work', u'house', u'credit', 'class']
    # 返回数据集和每个维度的名称
    return datasets, labels


class Node:
    def __init__(self, is_leaf, class_type):
        self.son_nodes = []
        self.is_leaf = is_leaf
        self.class_type = str(class_type)
        if is_leaf:
            self.class_type += str(random.randint(1,1000))
        self.edges = []

    def __str__(self):
        return "{} {}".format(self.is_leaf, self.class_type)


def create_disicion_tree_by_id3(D, A, delta, class_label='class'):
    class_num = len(D.groupby(class_label).size())
    most_frequence_class = D[class_label].value_counts().keys()[0]
    
    if class_num == 1:
        return Node(True, most_frequence_class)
    if len(A) == 0:
        return Node(True, most_frequence_class)

    entropy_list = []
    for feature in A:
        entropy_list.append(H(D, condition=feature, class_label=class_label))

    idx = np.argmax(entropy_list)
    selected_feature = A[idx]
    max_entropy = entropy_list[idx]
    if max_entropy < delta:
        return Node(True, most_frequence_class)

    base = Node(False, selected_feature)
    for group in D.groupby(selected_feature):
        base.son_nodes.append(create_disicion_tree_by_id3(group[1], list(
            set(A) - set([selected_feature])), delta))
        base.edges.append(group[0])
    return base


datasets, labels = create_data()
train_data = pd.DataFrame(datasets, columns=labels)
train_data['class'] = train_data['class'] == '是'
root = create_disicion_tree_by_id3(train_data, [
    u'age', u'work', u'house', u'credit'], 0.0)
G = nx.Graph()
queue = [root]
G.add_node(root.class_type)
while len(queue) > 0:
    head = queue.pop(0)
    for son in head.son_nodes:
        G.add_node(son.class_type)
        G.add_edge(head.class_type, son.class_type)
        queue.append(son)
    print(head.class_type)

pos = nx.spring_layout(G)
nx.draw(G, pos,with_labels=True)
plt.show()

# %%

在这里插入图片描述

C4.5

和ID3的区别在于使用信息增益比作为特征选择标准

CART

分类回归树(classification and regression tree,CART)是给定随机变量X条件下,输出随机变量Y的条件概率分布的学习方法。CART假设决策树是二叉树。也即是在计算现有特征A,对其所有可能取到的每一个值a,根据样本点对A=a的测试为”是“或者”否“,将训练数据集D切分为D1和D2,样本分割位置叫样本切分点。再利用公示X计算A=a的时候的基尼指数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值