Python学习——决策树中纯度算法的实现

决策树

  • 决策树算法是机器学习中的一个基础算法,该算法有着诸多的优点。在python中实现决策树,现阶段都已经集成中到了机器学习库sklearn中,没有必要去一行一行的代码实现,可以直接调用。
  • 但是为了更高的理解决策树算法,决定动手自己实践来实现决策树。
    而决策数的判断条件,就是根据样本集前后的纯度差异,挑选出最佳的特征,使得分类前后,样本的纯度达到最大化的提升。
  • 因此,在实现决策树之前,十分有必要,了解纯度算法的实现。
  • 当然,自己码的决策树模型在MATALB上进行了实现,空闲时,会进行整理,并同内置的决策树训练函数作对比,再发出。而在python上,目前只实现了纯度算法

纯度

  • 在决策树中,计算样本的纯度,一般而言有三种方法,分别为信息熵信息熵增益以及基尼系数。在本篇中,主要实现了以基尼系数为基础的纯度计算。
  • 无论是计算信息熵还是计算基尼系数,都存在一个难点,那就是需要知道样本的概率分布。对于离散型的样本,其概率分布,十分好求。但样本若是连续型的,则难点就在于此。
  • 为了解决这一难题,通用的解法是,采用二分法bi-partition对连续特征进行离散化处理。

二分bi-partition

该方法的思路是,首先对某特征的M个样本进行以小到大的顺序排序,之后选取M-1个划分点,他们分别是每两个样本的中点。接着根据划分点对连续变量离散化,计算其概率分布,再根据概率分布计算基尼系数。对于M-1个划分点,就有M-1个概率分布,则有M-1个基尼系数,挑选出最小的基尼系数所对应的划分点,则为最佳划分点。(基尼系数越小,表示样本越纯净)

Python实现

为此随机设计了一组有13个样本的值为[0,1,5,4,3,4,5,6,8,7,9,0],它们依次对应的标签为[1,1,1,1,2,2,2,2,3,3,3,3]。

import numpy as np

def Impurity(X,Label,ClassNum = 3):
    Len = np.size(X)
    sX = np.sort(X)
    Tha = np.zeros(Len-1)
    gi = np.zeros(Len-1)
    for i in range(Len-1):
        Th = (sX[i] + sX[i+1])/2
        Tha[i] = Th
        idx1 = np.where(X < Th)
        idx2 = np.where(X >= Th)
        p = np.zeros([2,ClassNum])
        g = np.zeros([1,2])
        ww = np.zeros([2,1])
        for Ti in range(2):
            if Ti == 1:
                idxTP = idx1
            else:
                idxTP = idx2
            Lab = Label[idxTP]
            for cs in np.arange(1,ClassNum+1):
                if np.size(idxTP) == 0:
                    p[Ti,cs-1] = 0
                else:                        
                    p[Ti,cs-1] = np.size(np.where(Lab == cs)) / np.size(idxTP)
            g[0,Ti] = gini(p[Ti,:])
            ww[Ti,0] = np.size(idxTP) / Len
            gi[i] = np.dot(g,ww)
            del idxTP,Lab
    idxa = np.argmin(gi)
    ThA = Tha[idxa]
    impur = gi[idxa]
    return impur,ThA

def gini(p):
# 基尼系数计算公式
    if np.all(p == 0):
        g = 0
    else:
        g = 1 - np.sum(np.square(p))
    return g           

X = np.array([0,1,5,4,3,4,5,6,8,7,9,0])
Label = np.array([1,1,1,1,2,2,2,2,3,3,3,3])
impur,ThA = Impurity(X,Label)
print("impurity=",impur,"Best dividing point:",ThA)

最终输出的结果

impurity= 0.444444444444 Best dividing point 6.5

为了验证以上结果的准确性,在MATLAB中也进行了检验。(先完成的MATLAB代码,并且在MATLAB中已经实现了这个决策树模型)

MATLAB实现

function [impur,ThA] = Impurity(X,Label,ClassNum,method)
%% 不纯都计算子程序
% ===============================Iuput=====================================
% X: 节点样本特征
% Label: 节点样本对应的标签
% ClassNum: 分类数 (默认 3)
% Method: 计算不纯度的方法 (gini:基尼系数...除此之外还有熵增等。默认 gini)
% ===============================Output====================================
% impur:各特征的不纯度
% ThA:对于连续特征的最佳分割点
% ===============================Info======================================
% Written by XuJiaCheng, 2017.10.08
% =========================================================================
if nargin <4,method = 'gini';end
if nargin <3,ClassNum = 2;end
Len = length(X);
sX = sort(X);
for ii = 1:Len-1
    Th = ( sX(ii) + sX(ii+1) )/2;
    Tha(ii) = Th;
    idx1 = find(X > Th) ;
    idx2 = find(X <= Th) ;
    for Ti = 1 : 2
        clear idxTp
        switch Ti
            case 1
                idxTp = idx1;
            case 2
                idxTp = idx2;
        end
        clear Lab
        Lab = Label(idxTp);
        for kk = 1 :ClassNum
            p(kk,Ti) = length( find( Lab == kk)) ./ length(idxTp) ;
        end
    end
    switch method
        case 'gini'
            w = [length(idx1) length(idx2)] ./ Len;
            gi = [gini(p(:,1));gini(p(:,2))];
            imp(ii) = w * gi;
        case 'entropy'
            
    end
end
switch method
    case 'gini'
        [impur, I] = min(imp);
        ThA = Tha(I);
    case 'entropy'
        impur = max(imp);
end
end

function gi = gini(p)
%% 基尼系数计算子程序
% ===============================Iuput=====================================
% p: 概率分布
% ===============================Ouput=====================================
% gi:基尼系数
% ===============================Info======================================
% Written by XuJiaCheng, 2017.10.08
% =========================================================================
if all(p==0)
    gi = 0;
else
    gi = 1 - sum(power(p,2));
end
end

输出结果:

disp(['基尼系数=',num2str( impur ),'  最佳划分点:',num2str(ThA)])
基尼系数=0.44444  最佳划分点:6.5

参考文章

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

推荐阅读更多精彩内容