基于WEKA的C45算法代码实现及其详解

本文介绍了基于WEKA的C45算法的自定义实现,详细讲解了C45算法的建树过程,包括根节点创建、节点分裂属性选择、实例集划分以及后剪枝处理。提供的MyC45类包含建树和预测两部分,简化了源代码的复杂性,便于理解C45的工作原理。
摘要由CSDN通过智能技术生成

1.概述

C45算法在weka已经有具体的实现,即weka中的J48.java。不过J48.java中的具体代码牵扯到较多的类和其他东西,直接看源代码比较容易混乱,且需要了解的东西较多,有比较多和C45算法本身没有太大关系而是为了方便代码实现的类、变量和方法等。
本文是基于C45算法思想和对J48源代码的详细解读,自己写了一个C45算法的代码(之后均称为MyC45)。该代码只含有两个类(99%的代码只在一个类中实现),需要了解的结构相对简单,算法的实现过程相对清晰,算法的效果和J48.java相差无几,写在这里权作参考。
weka中的每个分类器的类文件都实现了buildClassifier和distributionForInstance两个算法,前者是构建分类器,后者是根据构建的分类器对每个实例进行类标记预测。所以,MyC45算法中主要分为建树(buildClassifier)和预测(distributionForInstance)两部分,其中建树(buildClassifier)是主体部分,预测(distributionForInstance)只是简单的利用前面构建好的树对每个实例进行预测。
特别说明,本文所使用的实例集均已进行数据预处理,所以在MyC45中没有J48中对缺失值的处理、判断J48能否处理该实例集等等对实例集的处理。

2.类及其变量说明

MyC45包括两个类,一个是MyC45,另一个是MyClassifierTree,它们的具体功能和变量说明如下:
1.MyC45:实现C45算法的类。
变量:
m_Root:C45决策树的根节点。
2.MyClassifierTree:具体实现C45算法中的建树和预测实例类标记两大部分的功能。
变量:
int[] m_AttributeList: 当前节点的可选分裂属性集合,以整数形式保存.-1表示当前节点不能选择该属性作为分裂属性。
int m_SplitAttribute:当前节点的分裂属性,以整数的形式表示。
int m_NumAttributes:训练实例集中属性的个数(包括类属性)。
MyCLassifierTree[] m_Sons:当前节点的儿子节点。
Instances m_Instances:当前节点对应的实例集。
int m_MinInstances:最小实例数,若当前节点对应的实例集的实例数小于该值,则当前节点只能作为叶节点。

注:以上是关键变量说明,类中其他变量并不是很重要就没有特别说明,在后面的代码中出现时会有说明。

3.伪代码

输入:训练实例集D,可选属性列表m_AttributeList,最小实例数m_MinInstances。
1.创建根节点m_root,m_AttributeList初始化为全0.
2.if D中的所有实例类标记都一样,则将m_root标记为叶节点并返回m_root。
3.if m_AttributeList为空,则将m_root标记为叶节点并返回m_root。
4.if m_Instances的实例数小于m_MinInstances,则将m_root标记为叶节点并返回m_root。
5.根据getBestSplitAttribute方法,在m_AttributeList中找出增益率最大的属性作为当前节点的分裂属性m_SplitAttribute。
6.根据m_SplitAttribute的属性值将当前节点的实例集m_Instances划分成多个子集,也就是当前节点的儿子节点 m_Sons。
7.对m_Sons中的每个节点递归地循环2-6的步骤以构建子树。
8.决策树构建好后,需要对其进行collapse处理和prune处理。前者是折叠子树过程,后者是后剪枝过程,具体说明在后面。
4.函数调用流程图

以下是各个部分的主要函数调用流程图,后面将对这些主要函数进行详细说明。


图1. buildClassifier部分的主要函数调用流程图

在MyC45类中的buildClassifier函数中,先初始化可选属性列表m_AttributeList和最小实例数m_MinInstances,然后用这两个参数初始化m_Root,之后再用m_Root调用MyClassifierTree类中的buildeClassifier函数即可。

这里写图片描述
图2. distributionForInstance部分的主要函数调用流程图

在MyC45类中的distributionForInstance函数中,直接用m_Root调用MyClassifierTree类中的distributionForInstance函数即可。

这里写图片描述
图3. 建树(buildTree)的主要函数调用流程图

建树首先根据isAllTheSame和canSplit两个函数和其他条件判断当前节点是否为叶节点;若可以分裂则调用getBestSplitAttribute函数求出最佳的分裂属性(也就是增益率最大的属性),getBestSplitAttribute函数中对每个可选属性分别调用beforeSplit、afterSplit和computeSplitInfo函数以求出该可选属性的增益率;随后将当前节点对应的实例集根据最佳分裂属性(即当前节点的分裂属性)分裂出多个子集,这些子集即为当前节点的子节点的实例集;然后对每个子集调用getNewTree函数以构建相应的子树,getNewTree函数中即调用buildTree函数,从而递归地构建决策树。

这里写图片描述
图4. 折叠子树(collapse)的主要函数调用流程图

collapse是对非叶节点进行操作,对于非叶节点,调用getCurrentTraningErrors求出当前节点的实例集上误分实例数,再调用getSubTraningErrors求出所有子树上实例集上误分实例数;如果后者大于前者,说明这些子树并不能提高这颗树的准确度,则把这些子树删除。否则在每个子树上递归的collapse。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值