C4.5算法较之ID3算法主要有4点改进:
- 采用信息增益率作为最优划分属性。
- 能够处理连续值类型的属性。
- 能够处理缺失值属性。
- 增加了剪枝处理,从而避免过拟合。
其中第2、3、4点在之前文章中都详细讨论过,此文主要补充说明第一点信息增益率准则,并对C4.5算法给出完整的Python代码。
一、信息增益率
ID3算法中的信息增益准则对取值数目较多的属性有所偏好,例如西瓜数据集中,如果把“编号”也作为候选划分属性,它的信息增益为0.998,但是如果用“编号”作为划分属性显然是不合理的。为了减少这种偏好可能带来的不利影响,C4.5决策树算法中使用增益率(gain ratio)来选择最优划分属性。
IV(a)称为属性a的固有值,属性a的可能取值数目越多,则IV(a)的值通常会越大。因此,增益率准则对可取值数目较少的属性有所偏好,因此,C4.5算法并不是直接选择增益率最大的候选划分属性,而是先从候选划分属性中找出信息增益高于平均水平的属性,再从中选择增益率最高的。
主要Python代码:
def calcGainRatio(dataSet, labelIndex, labelPropertyi):
"""
type: (list, int, int) -> float, int
计算信息增益率,返回信息增益率和连续属性的划分点
dataSet: 数据集
labelIndex: 特征值索引
labelPropertyi: 特征值类型,0为离散,1为连续
"""
baseEntropy = calcShannonEnt(dataSet, labelIndex) # 计算根节点的信息熵
featList = [example[labelIndex] for example in dataSet] # 特征值列表
uniqueVals = set(featList) # 该特征包含的所有值
newEntropy = 0.0
bestPartValuei = None
IV = 0.0
totalWeight = 0.0
totalWeightV = 0.0
totalWeight = calcTotalWeight(dataSet, labelIndex, True) # 总样本权重
totalWeightV = calcTotalWeight(dataSet, labelIndex, False) # 非空样本权重
if labelPropertyi == 0: # 对离散的特征
for value in uniqueVals: # 对每个特征值,划分数据集, 计算各子集的信息熵
subDataSet = splitDataSet(dataSet, labelIndex, value)
totalWeightSub = 0.0
totalWeightSub = calcTotalWeight(subDataSet, labelIndex, True)
if value != 'N':
prob = totalWeightSub / totalWeightV
newEntropy += prob * calcShannonEnt(subDataSet, labelIndex)
prob1