决策树算法(C4.5)
ID3具有一定的局限性,即信息增益倾向于选择取值比较多的特征(特征越多,条件熵(特征划分后的类别变量的熵)越小,信息增量就越大),C4.5通过选择最大的信息增益率 gain ratio 来选择节点可以解决该问题。并且C4.5算法可以处理连续和有缺失值的数据。
C4.5与ID3在实现过程中,不同之处在于将计算信息增益的函数改为计算信息增益率。
譬如,对于上一个例子中的湿度这一项的取值改为:
Day |
Outlook |
Temperature |
Humidity |
Wind |
PlayTennis |
1 |
Sunny |
Hot |
85 |
Weak |
No |
2 |
Sunny |
Hot |
90 |
Strong |
No |
3 |
Overcast |
Hot |
78 |
Weak |
Yes |
4 |
Rain |
Mild |
96 |
Weak |
Yes |
5 |
Rain |
Cool |
80 |
Weak |
Yes |
6 |
Rain |
Cool |
70 |
Strong |
No |
7 |
Overcast |
Cool |
65 |
Strong |
Yes |
8 |
Sunny |
Mild |
95 |
Weak |
No |
9 |
Sunny |
Cool |
70 |
Weak |
Yes |
10 |
Rain |
Mild |
80 |
Weak |
Yes |
11 |
Sunny |
Mild |
70 |
Strong |
Yes |
12 |
Overcast |
Mild |
90 |
Strong |
Yes |
13 |
Overcast |
Hot |
75 |
Weak |
Yes |
14 |
Rain |
Mild |
80 |
Strong |
No |
Gain(Wind) = Entropy(S) – (8/14)* Entrogy(weak)-(6/14)* Entrogy(strong) = 0.048
weak = 8;Strong = 6
Feature(Wind) = -8/14*log(8/14)-6/14*log(6/14) = 0.9852
RatioGain(Wind) = Gain(Wind)/Feature (Wind) = 0.0487
同理:RatioGain(Outlook) = 0.247/1.577 = 0.1566
RatioGain(Temperature)= 0.029/1.556 = 0.018
其中,对于连续值的计算:
1. 对特征的取值进行升序排序
2. 两个特征取值之间的中点作为可能的分裂点,将数据集分成两部分,计算每个可能的分裂点的信息增益(InforGain)。优化算法就是只计算分类属性发生改变的那些特征取值。
3. 选择修正后信息增益(InforGain)最大的分裂点作为该特征的最佳分裂点
4. 计算最佳分裂点的信息增益率(Gain Ratio)作为特征的Gain Ratio。注意,此处需对最佳分裂点的信息增益进行修正:减去log2(N-1)/|D|(N是连续特征的取值个数,D是训练数据数目,此修正的原因在于:当离散属性和连续属性并存时,C4.5算法倾向于选择连续特征做最佳树分裂点)
故,划分为:{ 65、70、75、78、80、85、90、95、96 } 这几个特征。
65 |
70 |
75 |
78 |
80 |
85 |
90 |
95 |
96 |
||||||||||
≤ |
> |
≤ |
> |
≤ |
> |
≤ |
> |
≤ |
> |
≤ |
> |
≤ |
> |
≤ |
> |
≤ |
> |
|
Yes |
1 |
8 |
3 |
6 |
4 |
5 |
5 |
4 |
7 |
2 |
7 |
2 |
8 |
1 |
8 |
1 |
9 |
0 |
No |
0 |
5 |
1 |
4 |
1 |
4 |
1 |
4 |
2 |
3 |
3 |
2 |
4 |
1 |
5 |
0 |
5 |
0 |
Entropy |
0 |
0.961 |
0.811 |
0.971 |
0.722 |
0.991 |
0.65 |
1 |
0.764 |
0.971 |
0.881 |
1 |
0.918 |
1 |
0.961 |
0 |
0.94 |
0 |
Gain |
0.048 |
0.015 |
0.045 |
0.090 |
0.102 |
0.025 |
0.011 |
0.048 |
0 |
此时,可以看到当特征小于等于80时,信息增益最大,选取该取值区间作为湿度属性的信息增益。
即Gain(Humidity) = 0.102
Feature(Humidity) = -9/14*log(9/14) - 5/14*log(5/14) = 0.940(两个分支,大于80的和小于等于80的)
RatioGain(Humidity) = 0.102/0.940 = 1.085
//------------------------------------------------
对于ID3算法局限性的理解:
X = [['sunny', 'hot', 'h_85', 'weak'],
['sunny', 'hot', 'h_90', 'strong'],
['overcast', 'hot', 'h_78', 'weak'],
['rain', 'mild', 'h_96', 'weak'],
['rain', 'cool', 'h_80', 'weak'],
['rain', 'cool', 'h_70', 'strong'],
['overcast', 'cool', 'h_65', 'strong'],
['sunny', 'mild', 'h_95', 'weak'],
['sunny', 'cool', 'h_70', 'weak'],
['rain', 'mild', 'h_80', 'weak'],
['sunny', 'mild', 'h_70', 'strong'],
['overcast', 'mild', 'h_90', 'strong'],
['overcast', 'hot', 'h_75', 'weak'],
['rain', 'mild', 'h_80', 'strong'],
]
对于ID3算法的输入改为,可以看到生成的决策树为:
可以看到,此时就会出现过拟合的现象。
而采用信息增益率作为判决条件的话:
estimator = Id3Estimator(gain_ratio=1)
获得的决策树为:
因此,对于使用信息增益作为分类准则和使用信息增益率的区别如上所示。
//-----------------------------------
对于处理数值的理解:
解读python的第三方库,ID3模块(decision-tree-id3)
在其中id3.py模块中:
Id3Estimator类的fit函数中
for i in range(self.n_features):
if check_input and check_numerical_array(X_[:, i]):
self.is_numerical[i] = True
X_tmp[:, i] = X_[:, i]
else:
X_tmp[:, i] = self.X_encoders[i].fit_transform(X_[:, i])
这里会判断一下传递的特征是名字还是数字,判断的方法在checks.py中:
def check_numerical_array(array):
""" Check if all values in a 1d array are numerical. Raises error if array
is more than 1d. Parameters
----------
array : nparray
containing the class names Returns
-------
result : bool
True if all values in array are numerical, otherwise false
"""
try:
if array.ndim > 1:
raise ArithmeticError("Found array with dim {}. Expected = 1."
.format(array.ndim))
array.astype(np.float64)
return True
except ValueError:
return False
此处会做一个类型转换,如果输入的是数字、字符串形式的数字都会被转为float类型。
(此次我觉得不太妥当,字符串形式的数字不应该转化为数字,说不定人家就是想这样输入作为feature呢,譬如我上面的输入数字的开头还要加一个 ‘h_’)
当特征为数字的时候计算方法在splitter.py文件中:
def _info_numerical(self, x, y):
""" Info for numerical feature feature_values
sort values then find the best split value Parameters
----------
x : np.array of shape [n remaining examples]
containing feature values
y : np.array of shape [n remaining examples]
containing relevent class Returns
-------
: float
information for remaining examples given feature
: float
pivot used set1 < pivot <= set2
"""
n = x.size
sorted_idx = np.argsort(x, kind='quicksort')
sorted_y = np.take(y, sorted_idx, axis=0)
sorted_x = np.take(x, sorted_idx, axis=0)
min_info = float('inf')
min_info_pivot = 0
min_attribute_counts = np.empty(2)
for i in range(1, n):
if sorted_x[i - 1] != sorted_x[i]:
tmp_info = i * self._entropy(sorted_y[0: i]) + \
(n - i) * self._entropy(sorted_y[i:])
if tmp_info < min_info:
min_attribute_counts[SplitRecord.LESS] = i
min_attribute_counts[SplitRecord.GREATER] = n - i
min_info = tmp_info
min_info_pivot = (sorted_x[i - 1] + sorted_x[i]) / 2.0
return CalcRecord(CalcRecord.NUM,
min_info * np.true_divide(1, n),
pivot=min_info_pivot,
attribute_counts=min_attribute_counts)
可以看到,其计算过程和上述对于数值的计算过程一样,其min_info为选取的最小的分类后的信息熵,为了得到最大的信息增益。
而对于是否使用信息增益率的判断在splitter.py文件中:
def _is_better(self, calc_record1, calc_record2):
"""Compares CalcRecords using gain ratio if present otherwise
using the information. Parameters
----------
calc_record1 : CalcRecord
calc_record2 : CalcRecord Returns
-------
: bool
if calc_record1 < calc_record2
"""
if calc_record1 is None:
return True
if calc_record2 is None:
return False
if self.gain_ratio:
if calc_record1.gain_ratio is None:
calc_record1.gain_ratio = self._gain_ratio(calc_record1)
if calc_record2.gain_ratio is None:
calc_record2.gain_ratio = self._gain_ratio(calc_record2)
if self._is_close(calc_record1.gain_ratio,
calc_record2.gain_ratio):
return calc_record1.info > calc_record2.info
else:
return calc_record1.gain_ratio < calc_record2.gain_ratio
else:
return calc_record1.info > calc_record2.info
故,对于C4.5算法,同样可以使用ID3模块,只不过设置参数:gain_ratio=True即可。
得到的决策树为:
下面我们验证在sunny情况下,humidity的划分便准是否正确:
Day |
Outlook |
Temperature |
Humidity |
Wind |
PlayTennis |
1 |
Sunny |
Hot |
85 |
Weak |
No |
2 |
Sunny |
Hot |
90 |
Strong |
No |
8 |
Sunny |
Mild |
95 |
Weak |
No |
9 |
Sunny |
Cool |
70 |
Weak |
Yes |
11 |
Sunny |
Mild |
70 |
Strong |
Yes |
首先计算humidity:
70 |
85 |
90 |
95 |
|||||
≤ |
> |
≤ |
> |
≤ |
> |
≤ |
> |
|
Yes |
2 |
0 |
2 |
0 |
2 |
0 |
2 |
0 |
No |
0 |
3 |
1 |
2 |
2 |
1 |
3 |
0 |
Entropy |
0 |
0 |
0.756 |
0 |
0.846 |
0 |
0.971 |
0 |
Gain |
0.971 |
0.517 |
0.294 |
0 |
Gain(humidity) = 0.971
Feature(humidity) = -2/5*log(-2/5) - 3/5*log(3/5) = 0.971(分两组,小于等于70的有2个数据,大于70的有3个数据)
RatioGain(humidity) = 1
Gain(Temperature) = 0.971 - (-log(0.5) * 2/5) = 0.571
Feature(Temperature) = -2/5*log(-2/5)*2 - 1/5*log(1/5) = 1.522(分三组,分别有2、2、1个数据)
RatioGain(Temperature) = 0.375
Gain(Wind) = 0.971 - (3/5*(-1/3*log(1/3)-2/3*log(2/3)) + 2/5( -1/2*log(1/2)-1/2*log(1/2)))= 0.02
Feature(Wind) = 0.971
RatioGain(Wind) = 0.02
因此,程序得到的结果是对的。
决策树算法(C4.5)的更多相关文章
- 机器学习回顾篇(7):决策树算法(ID3、C4.5)
.caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px so ...
- R_Studio(决策树算法)鸢尾花卉数据集Iris是一类多重变量分析的数据集【精】
鸢尾花卉数据集Iris是一类多重变量分析的数据集 通过花萼长度,花萼宽度,花瓣长度,花瓣宽度4个属性预测鸢尾花卉属于(Setosa,Versicolour,Virginica)三个种类中的哪一类 针对 ...
- [转]机器学习——C4.5 决策树算法学习
1. 算法背景介绍 分类树(决策树)是一种十分常用的分类方法.它是一种监管学习,所谓监管学习说白了很简单,就是给定一堆样本,每个样本都有一组属性和一个类别,这些类别是事先确定的,那么通过学习得到一个分 ...
- 决策树算法原理(ID3,C4.5)
决策树算法原理(CART分类树) CART回归树 决策树的剪枝 决策树可以作为分类算法,也可以作为回归算法,同时特别适合集成学习比如随机森林. 1. 决策树ID3算法的信息论基础 1970年昆兰找 ...
- ID3和C4.5分类决策树算法 - 数据挖掘算法(7)
(2017-05-18 银河统计) 决策树(Decision Tree)是在已知各种情况发生概率的基础上,通过构成决策树来判断其可行性的决策分析方法,是直观运用概率分析的一种图解法.由于这种决策分支画 ...
- scikit-learn决策树算法类库使用小结
之前对决策树的算法原理做了总结,包括决策树算法原理(上)和决策树算法原理(下).今天就从实践的角度来介绍决策树算法,主要是讲解使用scikit-learn来跑决策树算法,结果的可视化以及一些参数调参的 ...
- 就是要你明白机器学习系列--决策树算法之悲观剪枝算法(PEP)
前言 在机器学习经典算法中,决策树算法的重要性想必大家都是知道的.不管是ID3算法还是比如C4.5算法等等,都面临一个问题,就是通过直接生成的完全决策树对于训练样本来说是“过度拟合”的,说白了是太精确 ...
- ID3决策树算法原理及C++实现(其中代码转自别人的博客)
分类是数据挖掘中十分重要的组成部分.分类作为一种无监督学习方式被广泛的使用. 之前关于"数据挖掘中十大经典算法"中,基于ID3核心思想的分类算法C4.5榜上有名.所以不难看出ID3 ...
- R语言 决策树算法
定义: 决策树(Decision Tree)是在已知各种情况发生概率的基础上,通过构成决策树来求取净现值的期望值大于等于零的概率,评价项目风险,判断其可行性的决策分析方法,是直观运用概率分析的一种图解 ...
- 决策树算法原理(CART分类树)
决策树算法原理(ID3,C4.5) CART回归树 决策树的剪枝 在决策树算法原理(ID3,C4.5)中,提到C4.5的不足,比如模型是用较为复杂的熵来度量,使用了相对较为复杂的多叉树,只能处理分类不 ...
随机推荐
- Oracle嵌套表
一.介绍 1.定义 嵌套表是表中之表.一个嵌套表是某些行的集合,它在主表中表示为其中的一列.对主表中的每一条记录,嵌套表可以包含多个行.在某种意义上,它是在一个表中存储一对多关系的一种方法. ...
- JavaScript中函数参数的值传递和引用传递
结论: 对于数字.字符串等基本类型变量,是将它们的值传递给了函数参数,函数参数的改变不会影响函数外部的变量. 对于数组和对象等是将对象(数组)的变量的值传递给了函数参数,这个变量保存的指向对象(数组) ...
- DRM学习总结(1)--- DRM框架介绍
一.DRM 简介 In computing, the Direct Rendering Manager (DRM), a subsystem of the Linux kernel, interfac ...
- c# List 所有操作方法例子
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Ref ...
- spring单元测试的基本配置
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:trade.ap ...
- 26 About the go command go命令行
About the go command go命令行 Motivation Configuration versus convention Go's conventions Getting star ...
- Flask:使用jsonify()转换为JSON的数据在Chrome显示为Unicode编码
Chrome 66,Flask 1.0.2,MongoDB 3.6.3, 创建了一个Flask应用,在将MongoDB中的数据使用PyMongo包获取后,再使用jsonify转换为JSON格式发送回请 ...
- Maven3 生命周期与插件(笔记五)
第一节:Maven 生命周期 Maven 生命周期简介:Maven 通过插件的方式完成一系列过程来实现功能. Maven 拥有三套独立的生命周期: Clean 清理项目 Default 构建项目 Si ...
- performance 判断页面是以哪种方式进入的
if (window.performance) { console.info("window.performance is supported"); console.log(per ...
- sql server 2000系统表sysproperties在SQL 2008中无效的问题
Sqlserver有一个扩展属性系统表sysproperties,因为只接触过MSSQL2005及以后的版本,在生产库2008版本及联机文档上搜了下都找不到这个系统表,后来发现这个系统表在2005版本 ...