视频地址:https://www.bilibili.com/video/BV17J411C7zZ?
知识整理如下一棵决策树包含:一个根结点、若干个内部结点、若干个叶结点
仅根据信息增益来决定选择怎样的分类属性带来的问题:按照属性 a a a划分时,若分支结点仅包含一个样本,这些分支结点的纯度已达最大,此时 a a a的信息增益远大于其他划分属性的,这样的决策数不具有泛化能力。
增益率定义
G a i n _ r a t i o ( D , a ) = G a i n ( D , a ) I V ( a ) Gain\_ratio(D,a)=\frac{Gain(D,a)}{IV(a)} Gain_ratio(D,a)=IV(a)Gain(D,a)其中
I V ( a ) = − ∑ v = 1 V ∣ D v ∣ ∣ D ∣ l o g 2 ∣ D v ∣ ∣ D ∣ IV(a)=-\sum^{V}_{v=1}\frac{|D_v|} {|D|} log_2\frac{|D_v|} {|D|} IV(a)=−v=1∑V∣D∣∣Dv∣log2∣D∣∣Dv∣称为属性 a a a的固有值,属性 a a a的分支越多( V V V越大), I V ( a ) IV(a) IV(a)的值通常越大。
(此处参考百科“Decision tree learning”中对Gini impurity (基尼不纯度)的解释)
CART (classification and regression tree) 算法中的分类树中,基尼不纯度是衡量如果从集合中随机选择一个元素(这个元素是根据子集中标签的分布情况,随机被贴上标签的),这个元素被错误标注的概率。换一种说法,基尼不纯度表示一个随机选中的样本在子集中被分错的可能性。
基尼不纯度可以这样计算:一个样本被选中的概率 p i p_i pi(标签为 i i i)乘以它被分错的概率 ∑ k ≠ i p k = 1 − p i \sum_{k\neq i}p_k=1-p_i ∑k=ipk=1−pi,再进行加和(因为一个样本可以落在 p 1 , p 2 , . . . p J p_1,p_2,...p_J p1,p2,...pJ)。设分为 J J J类,其中 i ∈ { 1 , 2 , . . . , J } i \in \{1,2,...,J\} i∈{1,2,...,J} ,令 p i p_i pi为集合中标为第 i i i类的类别所占的份额。
I G ( p ) = ∑ i = 1 J ( p i ∑ k ≠ i p k ) = ∑ i = 1 J p i ( 1 − p i ) = ∑ i = 1 J ( p i − p i 2 ) = ∑ i = 1 J p i − ∑ i = 1 J p i 2 = 1 − ∑ i = 1 J p i 2 \mathrm{I}_{G}(p)=\sum_{i=1}^{J}\left(p_{i} \sum_{k \neq i} p_{k}\right)=\sum_{i=1}^{J} p_{i}\left(1-p_{i}\right)=\sum_{i=1}^{J}\left(p_{i}-p_{i}^{2}\right)=\sum_{i=1}^{J} p_{i}-\sum_{i=1}^{J} p_{i}^{2}=1-\sum_{i=1}^{J} p_{i}^{2} IG(p)=i=1∑J⎝⎛pik=i∑pk⎠⎞=i=1∑Jpi(1−pi)=i=1∑J(pi−pi2)=i=1∑Jpi−i=1∑Jpi2=1−i=1∑Jpi2基尼不纯度越小,数据集的纯度越高。
最后加权平均求基尼指数(Gini index),因为属性 a a a有 V V V个子集(分类),基尼指数计算为 G i n i _ i n d e x ( D , a ) = ∑ v = 1 V ∣ D v ∣ ∣ D ∣ I G v ( p ) Gini\_index(D,a)=\sum_{v=1}^{V}\frac{|D_v|} {|D|} \mathrm{I}_{G_v}(p) Gini_index(D,a)=v=1∑V∣D∣∣Dv∣IGv(p)
在候选属性集合 A A A中选择使划分后基尼指数最小的属性 a a a作为最优划分属性。
以西瓜书中西瓜数据集2.0为例
计算基尼指数代码实现如下:
# 计算基尼不纯度Gini impurity,此处决策结果只有好瓜g和坏瓜b之分
def gini_impurity(g,b):
gini_impurity = 1 - (((g/(g+b))**2) + ((b/(g+b))**2))
return round(gini_impurity,3)
# 求基尼指数Gini index
# 对分成三类的属性求基尼指数
def gini_index(a,b,c,d,e,f):
class1 = gini_impurity(a,b) #a,b分别代表正例,反例
class2 = gini_impurity(c,d)
class3 = gini_impurity(e,f)
sum = a+b+c+d+e+f
gini_index = (a+b)/sum*class1 + (c+d)/sum*class2 + (e+f)/sum*class3
return round(gini_index,3)
# 对只分成两类的属性求基尼指数
def gini_index2(a,b,c,d):
class1 = gini_impurity(a,b)
class2 = gini_impurity(c,d)
sum = a+b+c+d
gini_index2 = (a+b)/sum*class1 + (c+d)/sum*class2
return round(gini_index2,3)
# 对“色泽”属性(青绿,乌黑,浅白)求基尼指数
feature1 = gini_index(3,3,4,2,1,4)
# 对“根蒂”属性(蜷缩,稍蜷,硬挺)求基尼指数
feature2 = gini_index(5,3,3,4,0,2)
# 对“敲声”属性(沉闷,浊响,清脆)求基尼指数
feature3 = gini_index(2,3,6,4,0,2)
# 对“纹理”属性(清晰,稍糊,模糊)求基尼指数
feature4 = gini_index(7,2,1,4,0,3)
# 对“脐部”属性(凹陷,稍凹,平坦)求基尼指数
feature5 = gini_index(5,2,3,3,0,4)
# 对“触感”属性(硬滑,软粘)求基尼指数
feature6 = gini_index2(6,6,2,3)
print(feature1,feature2,feature3,feature4,feature5,feature6)