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. 数据挖掘十大算法之决策树详解

你可能感兴趣的:(Python学习——决策树中纯度算法的实现)