决策树算法

1.特性

优点:可读性、分类速度快

缺点:对未知数据集泛华能力弱,容易发生过拟合现象

特点:划分数据集后,数据纯度变大的过程

分类:离散型决策树、连续型决策树

与KNN的区别:KNN的缺点是无法给出数据内在含义,而决策树在数据形式上易于理解

2.构建过程

创建决策树三个过程:特征选择,建立树、裁剪(解决过拟合现象)

递归选择熵值最大的特征进行分类,以最快速度降低数据集不确定程度

根据特征选择指标的不同,分为ID3/CART/C4.5

(1)计算当前分类信息熵(经验熵)

H = -\sum_{i=1}^np(xi)\log_2 p(xi)                 n:分类次数; p(xi):该分类出现的概率

(2)求当前每个特征分类后的条件熵

H(Y|X) = \sum_{i=1}^np(xi)H(Y|X=xi)

条件熵:我们假设以某个特征进行分类(条件概率),在已知该特征值分类情况下的分类结果Y计算熵(该特征每个取值的概率乘以一直该取值下的信息熵)

(3)求信息增益/信息增益比/基尼系数(增益:衡量划分数据前后信息发生的变化)

信息增益最大(ID3):仅用于二分类离散属性问题

g(D,A) = H(D) - H(D|A)

信息增益比最大(C4.5):可处理连续值属性问题(取连续属性中值作为划分标准)

g_{R}(D,A) = \frac{g(D,A)}{H( D)}

基尼系数最小(CART):CART必须是二叉树,分类和回归都可运用,但更偏向于连续属性,不作对数运算,更加高效:

Gini(D) = 1 - \sum_{i=1}^n \frac{(|C_{i} |}{| D|})^2    K:分类类别   |D|样本个数  |Ci|该类别个数

Gini(D,A) = \frac{|D1|}{D}  Gini(D1) + \frac{|D2|}{D}  Gini(D2)  D1  D2为该特征的分类,CART都是二分

(4)择信息增益/信息增益比最大的特征进行当次划分,然后取出该列特征。

(5)对于整棵树的构造,使用递归原则处理数据集

3.几种衡量对比


4.剪枝

剪枝:考虑决策树的复杂度,不出现过拟合现象,对决策树进行修剪;从已经生成的树上裁掉一些子树或叶节点,并将其根节点或父节点作为新的叶子节点,从而简化分类树模型

1.预剪枝:构造结点钱判断是否构建该结点对泛化能力有所提升,运算简单但可能欠拟合,适用于大规模问题

四种简单方式判断:

(1) 决策树到达一定高度

(2) 结点下的实例少于一定个数

(3)信息增益、信息增益比低于某个阈值

2.后剪枝:先构建整树,自底向上对非叶节点进行泛化能力判断,通过极小化决策树整体的损失函数或代价函数来实现的

后剪枝CCP:(CART/GBDT中所用的剪枝方法),代价复杂度剪枝

依次剪枝计算误差,选择误差最小的那棵树

注:关于剪枝部分  以后来补充

5.基本代码实现(来自机器学习实战)

(1)计算香农熵

from math import log

from numpy import *

# 给定样本集,计算该样本集的熵,样本集最后一列为分类

def cal_entropy(data):

    # 样本个数

    entries_num = len(data)

    # 存储每个分类出现的次数

    label_count = {}

    for vec in data:

        cur_label = vec[-1]

        label_count[cur_label] = label_count.get(cur_label,0) + 1

    # 熵

    Entropy = 0.0

    # 计算信息熵

    for key in label_count:

        prob = float(label_count[key]) / entries_num

        Entropy += prob * math.log(prob, 2) #此处使用numpy.math

    return (0-Entropy)

(2)计算信息增益,给出最优特征

# -*- coding: utf-8 -*-

from Cal_Entropy import *

# 返回拆分后的数据集

def Split_Data(dataset, axis, value):

    new_subset = []

    for vec in dataset:

        if vec[axis] == value:

            feature_split = vec[:axis]

            feature_split.extend(vec[axis + 1:])

            new_subset.append(feature_split)

    return new_subset

# 传入数据集,返回最优特征(计算每个特征信息增益)

def Split_by_entropy(dataset):

    # 记录当前有多少个特征

    feature_num = len(dataset[0]) - 1

    # 当前数据集信息熵

    ent_old = cal_entropy(dataset)

    # 最大信息增益

    best_gain = 0.0

    # 最好特征列

    best_feature = -1

    # 对每一个特征进行遍历

    for i in range(feature_num):

        feature_list = [x[i] for x in dataset]

        uniVal = set(feature_list)

        ent_new = 0.0

        for value in uniVal:

            sub_set = Split_Data(dataset, i, value)

            prob = len(sub_set) / float(len(dataset))

            ent_new += prob * (0 - cal_entropy(sub_set))

        Info_gain = ent_old - ent_new

        if(Info_gain > best_gain):

            best_gain = Info_gain

            best_feature = i

    return best_feature

(3)主函数,递归构建决策树

# -*- coding: utf-8 -*-

import operator

from Split_by_entropy import *

# 该方法输入一组分类值,返回最多的分类结果

def Majority_vote(classList):

    classcount = {}

    for vote in classList:

        classcount[vote] = classcount.get(vote,0) + 1

    sorted_count = sorted(classcount.items(), key = operator.itemgetter(1),reverse = True)

    return sorted_count[0][0]

# 该方法用于递归构建决策树

def Create_Tree(dataset,labels):

    # 分类结果集

    classList = [x[-1] for x in dataset]

    # 如果该结点下所有数据都为同一分类,则返回该分类作为最终分类

    if classList.count(classList[0]) == len(classList):

        return classList[0]

    # 如果已经分到最后一个特征但是该特征下还是有多个分类,选择最多的那个分类作为最终分类

    if len(dataset[0]) == 1:

        return Majority_vote(classList)

    # 通过计算每个特征信息增益,选择最优特征及特征名

    best_feature = Split_by_entropy(dataset)

    best_labels = labels[best_feature]


    # 特征列表删除该特征(已经进行了分类)

    subLabels=labels[:]

    del(subLabels[best_feature])

    myTree = {best_labels:{}}

    # 选取数据集中最优特征列去重后进行分类,继续递归生成子树

    f_val = [x[best_feature] for x in dataset]

    uni_val = set(f_val)

    for value in uni_val:

        # 递归创建子树并返回

        myTree[best_labels][value] = Create_Tree(Split_Data(dataset\

              ,best_feature,value), subLabels)

    return myTree

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容