机器学习十大算法C4.5中文翻译
1.什么是C4.5
C4.5是一套算法,这套算法主要用于对机器学习和数据挖掘中的分类问题。它是一种有监督的学习,也就是说对于该算法我们需要先给它提供一个数据集,这个数据集包含多个实例,每个实例都包含多个属性,该实例用这些属性进行描述,根据属性取值的不同被划分到不同的互斥类中,C4.5从提供的数据集中学习到如何将不同属性值的实例划分到不同类的映射,当我们提供全新的一套属性值的时候,它能够通过学到的映射对新的属性值进行分类。例如,查看图1-1这组训练数据,每一行对应于一个实例,属性值包括对天气的展望(对应于一个三值变量,也就是说该数据的取值只能是设置的三种情况的一种),温度(一个连续取值的变量),湿度(一个连续取值的变量)和是否有风(二进制值),所有的实例被划分为两类也就是是否适合打高尔夫。我们的目的就是从训练数据中学到一个映射,这个映射可以用于对在图中未出现的实例属性取值情况进行有效分类。
C4.5是由J.Ross Quinlan提出的,由于它是ID3(一种著名的决策树归纳算法)的后续版本,因此被如此命名。决策树的决策结点是一系列系统化安排的问题,这些问题用于测试某一具体属性(例如:对天气的展望outlook),对每个结点上问题的不同测试输出产生不同的分支,最后会达到叶子结点。叶子结点的值也就是最终的划分类别(如:是否打高尔夫)。决策树就像我们汽车的维修手册一样,我们对每一个检修问题进行排查最终确定我们的汽车什么出了问题。除了推演树,C4.5还可以将决策树用表示规则形式表示。然而对规则后剪枝操作将导致无法很好的将规则转化为决策树。
从C4.5的历史线索我们可以看出许多小团体或多或少的聚集在了一些解决思路相似的分类方法上。ID3的发展独立于Friedman设计的原始树归纳算法,这种原始树归纳算法经过Breiman,Olsen和Stone三人的改进之后变为我们熟知的CART算法。虽然上文中说ID3独立于原始树归纳算法,但是从诸多的有关CART的参考文献中我们可以看到在C4.5的设计决策的部分似乎受到了CART的影响或者由CART改进而来,例如处理特殊属性的部分。同时Quinlan本人也承认在设计ID3和C4.5的时候受到了概念学习系统CLS的影响。如今,C4.5已经完全由一种由Rulequest Reasearch,Inc提供的商业产品See5/C5.0取代。
10大算法中的两个算法是基于树的算法充分证实了这种机器学习算法在数据挖掘中的流行性。以前决策树被用于具有面值或分类数据的领域,然而如今决策树被用于具有数值的,
标记符号的以及混合类型的属性值的多种领域例如临床决策制定,制造业,文本分析,生物信息学,空间数据建模,和一些特定领域,这些领域的决策制定能够表示为一个决策树或规则的形式。
2.算法描述
C4.5并不是单单的指一个算法而是一套算法-C4.5,C4.5-no-pruning和C4.5-rules-具备很多功能。我们首先给出基本的C4.5算法,然后再讨论这些功能。
算法1.1给出了C4.5是如何运行的大体描述。该算法的框架表述还是比较清晰的,从根节点开始不断得分治,递归,生长,直至得到最后的结果。根节点代表整个训练样本集,通过在每个节点对某个属性的测试验证,算法递归得将数据集分成更小的数据集.某一节点对应的子树对应着原数据集中满足某一属性测试的部分数据集.这个递归过程一直进行下去,直到某一节点对应的子树对应的数据集都属于同一个类为止。
----------------------------------------------------------------------------------------------------------------- 算法1.1 C4.5(D)
----------------------------------------------------------------------------------------------------------------- 输入:一个属性值集合D
1:Tree={}
2:if D 无法继续划分为不同的子集 or 遇到其它停止的准则 then
3: 中止
4:end if
5:for all attribute a∈D do
6: 计算属性a的信息论度量
7:end for
8:a=根据度量值选择最适宜作为根结点的属性
9:Tree=建立一个以属性a作为决策结点的根结点
10:Dv=基于a从D中归纳出子数据集
11:for all Dv do
12: Treev=C4.5(Dv)
13: 将Treev连接到Tree的相应分支上
14:end for
15:return Tree
------------------------------------------------------------------------------------------------------------------
图1.1给出了Golf数据集,用于作为算法的输入。就如先前陈述的一样,我们的目标是预测一天的天气状况是否适宜打高尔夫。在图1.1中样本的部分属性取值是离散的,部分又是连续取值的。
图1.2是高尔夫数据集对应的决策树。下面就让我们来分析一下构造该决策树可能遇到的问题。
1.分类树中的测试是怎样的?
从如1.2可以看出,C4.5并没有对结点限制最多产生两条分支而是可以产生两种或更多种结果。如果属性是布尔类型的,将产生两条测试分支。对于属性取值为离散变量,这很简单,离散变量对应着多个值,每个值就对应着测试的一个分支,测试就是验证样本对应的属性值对应哪个分支。这样数据集就会被分成几个小组。对于连续变量,所有连续变量的测试分支都是2条,其测试分支分别对应着{=t?},t对应着分支阈值。
2.如何选择测试?
C4.5根据信息论标准来选择测试,比如增益(在信息论中,熵对应着某一分布的平均信息量,其值同时也对应着要完全无损表示该分布所需要的最小的比特数,本质上熵对应着不确定性,可能的变化的丰富程度。所谓增益,就是指在应用了某一测试之后,其对应的可能性丰富程度下降,不确定性减小,这个减小的幅度就是增益,其实质上对应着分类带来的好处)或者增益比(这个指标实际上就等于增益/熵,之所以采用这个指标是为了克服采用增益作为衡量标准的缺点,采用增益作为衡量标准会导致分类树倾向于优先选择那些具有比较多的分支的测试,这种倾向需要被抑制)。我们通常将增益比作为默认的标准。算法在进行Tree-Growth时,总是“贪婪得”选择那些信息论标准最高的那些测试。
3.如何选择连续变量的阈值?
就像前面所表述的那样,对于离散性和布尔型的属性,只需要对属性的所有可能取值进行测试就够了。然而连续型变量需要确定一个阈值,将其划分为两个范围。这阈值如何确定呢?很简单,把需要处理的样本(对应根节点)或样本子集(对应子树)按照连续变量的大小从小到大进行排序,假设该属性对应的不同的属性值一共有N个,那么总共有N-1个可能的候选分割阈值点,每个候选的分割阈值点的值为上述排序后的属性值链表中两两前后连
续元素的中点,那么我们的任务就是从这个N-1个候选分割阈值点中选出一个,使得前面提到的信息论标准最大。举个例子,对于Golf数据集,我们来处理温度属性,来选择合适的阈值。首先按照温度大小对对应样本进行排序如下:
----------------------------------------------------------------------------------
64 65 68 69 70 71 72 72 75 75 80 81 83 85
-----------------------------------------------------------------------------------
那么可以看到有13个可能的候选阈值点,比如middle[64,65], middle[65,68]….,middle[83,85]。那么最优的阈值该选多少呢?通过计算信息熵的方式计算每种候选阈值点的熵值,选取熵值最小的阈值点,熵值越小,增益越大,后面我们会详细的介绍熵与增益。对于临近的变量Vi与Vi+1如果取值为Vi的所有样本和取值Vi+1的所有样本属于相同的分类,选取他们之间的值作为阈值点将无法增加信息增益或增益比。通过这种方法可以减少阈值点的测试。
4.Tree-Growing如何终止?
前面提到Tree-Growing实际上是一个递归过程,那么这个递归什么时候到达终止条件退出递归呢?有两种方式,第一种方式是如果某一节点的分支所覆盖的样本都属于同一类的时候,那么递归就可以终止,该分支就会产生一个叶子节点.还有一种方式就是,如果某一分支覆盖的样本的个数如果小于一个阈值,那么也可产生叶子节点,从而终止Tree-Growing。
5.如何确定叶子结点的类?
前面提到Tree-Growing终止的方式有2种,对于第一种方式,叶子节点覆盖的样本都属于同一类,那么这种情况下叶子节点的类自然不必多言。对于第二种方式,叶子节点覆盖的样本未必属于同一类,直接一点的方法就是,该叶子节点所覆盖的样本哪个类占大多数,那么该叶子节点的类别就是那个占大多数的类。
我们将现在来详细的介绍如何由图1.1得到图1.2中的树。这就涉及到测试的选择问题,前面《如何选择测试?》提到测试的选择是依据信息论标准,信息论标准有两种,一种是增益,一种是增益比。首先来看看增益Gain的计算。假设随机变量x,它可能属于c个类中
的任何一个,通过样本的统计,它分别属于各个类的概率分别为
想把某一样本进行归类所需要的熵就为:
,那么要
根据这个公式可以计算出playGolf?的熵:
所以它的熵值为0.940。它的信息论含义就是我要想把PlayGolf?这个信息传递给别人话,平均来讲我至少需要0.940个bit来传递这个信息。C4.5的目标就是经过分类来减小这个熵。那么我们来依次考虑各个属性测试,通过某一属性测试我们将样本分成了几个子集,这使得样本逐渐变得有序,那么熵肯定变小了。这个熵的减小量就是我们选择属性测试的依据。还是以Golf数据集为例,Outlook的增益Gain(Outlook),其公式如下:
它的实质是把数据集D根据某一属性测试分成v个子集,这使得数据集D变得有序,使得
数据集D的熵变小了。分组后的熵其实就是各个子集的熵的权重和。下面我们给出一个增益的具体计算过程:
通过计算我们得到Gain(Outlook)=0.940-0.694=0.246,依据同样的方法我们可以计算出其它属性对应的信息增益。可以得到第一个测试属性是Outlook。这是一个贪婪的选择只考虑眼前的最大并不考虑对将来决策的影响。,就像前面阐述的一样,当子数据集为空也就是说所有的子数据集属于同一类别落在同一叶子节点上时树的增长就停止了,我们观察到对于outlook等于overcast的样本对应的结果都是yes,所以在属性取值为overcast的方向上的树的增长就停止了。然而,对于另外两个分支,样本对应的结果并不唯一,所以需要继续递归,但是outlook属性不能再作为划分标准。对于不同的分支需要选择不同的测试属性。
到这里似乎一切都很完美,增益这个指标非常得make sense,但是其实增益这个指标有一个缺点。我们来考虑Golf数据集中的Day这个属性(我们假设它是一个真属性,实际上很可能大家不会把他当做属性),Day有14个不同的值,那么Day的属性测试节点就会有14个分支,很显然每个分支其实都覆盖了一个“纯”数据集(所谓“纯”,指的就是所覆盖的数据集都属于同一个类),那么其熵增益显然就是最大的,那么Day就默认得作为第一个属性。之所以出现这样的情况,是因为增益这个指标天然得偏向于选择那些分支比较多的属性,也就是那些具有的值比较多的那些属性。这种偏向性是我们希望克服的,我们希望公正地评价所有的属性。因此又一个指标被提出来了 Gain Ratio-增益比。某一属性A的增益比计算公式如下:
Entropy(A)实际上就是属性A的熵,只不过这个熵有所不同,他不是样本最终分类{PlayGolf?}的熵,而是对应属性分组{A?}的熵,它反映的是属性A本身的信息量。下面我给出一个计算增益比GainRatio(Outlook)的例子:
1:已知Gain(Outlook)=0.246
2:属性Outlook的熵Entropy:
Sunny概率:5/14 Overcast:4/14 Rainy:5/14
Entropy=-5/14log2(5/14) -4/14log2(4/14) -5/14log2(5/14) #注意与上面熵计算方法的不同
通过计算我们很容易得到GainRatio(Outlook)=0.246/1.577=0.156。增益比实际上就是对增益进行了归一化,这样就避免了指标偏向分支多的属性的倾向。
1.3 C4.5的功能
1.3.1 树的剪枝
决策树为什么要剪枝?原因就是避免决策树“过拟合”样本。前面的算法生成的决策树非常的详细而庞大,每个属性都被详细地加以考虑,决策树的树叶节点所覆盖的训练样本都是“纯”的。因此用这个决策树来对训练样本进行分类的话,你会发现对于训练样本而言,这个树表现堪称完美,它可以100%完美正确得对训练样本集中的样本进行分类(因为决策树本身就是100%完美拟合训练样本的产物)。但是这会带来一个问题,如果训练样本中包含了一些错误,按照前面的算法,这些错误也会100%一点不留得被决策树学习了,这就是“过拟合”。C4.5的缔造者昆兰教授很早就发现了这个问题,他作过一个试验,在某一个数据集中, 过拟合的决策树的错误率比一个经过简化了的决策树的错误率要高。那么现在的问题就来了,如何在原生的过拟合决策树的基础上,通过剪枝生成一个简化了的决策树?
第一种方法,也是最简单的方法,称之为基于误判的剪枝。这个思路很直接,完全的决策树不是过度拟合么,我再搞一个测试数据集来纠正它。对于完全决策树中的每一个非叶子节点的子树,我们尝试着把它替换成一个叶子节点,该叶子节点的类别我们用子树所覆盖训练样本中存在最多的那个类来代替,这样就产生了一个简化决策树,然后比较这两个决策树在测试数据集中的表现,如果简化决策树在测试数据集中的错误比较少,并且该子树里面没有包含另外一个具有类似特性的子树(所谓类似的特性,指的就是把子树替换成叶子节点后,其测试数据集误判率降低的特性),那么该子树就可以替换成叶子节点。该算法以bottom-up的方式遍历所有的子树,直至没有任何子树可以替换使得测试数据集的表现得以改进时,算法就可以终止。
第一种方法很直接,但是需要一个额外的测试数据集,能不能不要这个额外的数据集呢?为了解决这个问题,于是就提出了悲观剪枝。悲观剪枝是C4.5的一种创新。该方法剪枝的依据是训练样本集中的样本误判率。我们知道一颗分类树的每个节点都覆盖了一个样本集,根据算法这些被覆盖的样本集往往都有一定的误判率,因为如果节点覆盖的样本集的个数小于一定的阈值,那么这个节点就会变成叶子节点,所以叶子节点会有一定的误判率。而每个节点都会包含至少一个的叶子节点,所以每个节点也都会有一定的误判率。悲观剪枝就是递归得估算每个内部节点所覆盖样本节点的误判率。剪枝后该内部节点会变成一个叶子节点,该叶子节点的类别为原内部节点的最优叶子节点所决定。然后比较剪枝前后该节点的错误率来决定是否进行剪枝。该方法和前面提到的第一种方法思路是一致的,不同之处在于如何估计剪枝前分类树内部节点的错误率。
悲观剪枝的思路非常巧妙。把一颗子树(具有多个叶子节点)的分类用一个叶子节点来替代的话,在训练集上的误判率肯定是上升的(这是很显然的,同样的样本子集,如果用子树分类可以分成多个类,而用单颗叶子节点来分的话只能分成一个类,多个类肯定要准确一些)。于是我们需要把子树的误判计算加上一个经验性的惩罚因子。对于一颗叶子节点,它覆盖了N个样本,其中有E个错误(也就是说本不应该划分到这个类的样本,样本中却将其划分到了该类,这就是错误),那么该叶子节点的错误率为(E+0.5)/N。这个0.5就是惩罚因子,那么一颗子树,它有L个叶子节点,那么该子树的误判率估计
为
。现在,假设我们用最优叶子节点替换掉了子树,我们
通过测试数据的测试发现它误判的次数为J,当J+0.5在范围内时,
悲观剪枝就用这个最优叶子节点替换掉子树。
这个方法可以被扩展为基于期望置信区间的剪枝。我们可以将叶子节点的误差率e建模成伯努利随机变量。对于一个给定的显著性因子CL,对于一个上界emax我们有e
那么一棵树错误分类一个样本值为1,正确分类一个样本值为0,该树错误分类的概率(误判率)为e(e为分布的固有属性,可以通过统计出来),那么树的误判次数就是伯努利分布,我们可以估计出该树的误判次数均值和标准差:
把子树替换成叶子节点后,该叶子的误判次数也是一个伯努利分布,其概率误判率e为(E+0.5)/N,因此叶子节点的误判次数均值为
使用训练数据,子树总是比替换为一个叶节点后产生的误差小,但是使用校正后有误差计算方法却并非如此,当子树的误判个数大过对应叶节点的误判个数一个标准差之后,就决定剪枝:
这个条件就是剪枝的标准。
当并不一定非要大一个标准差,可以给定任意的置信区间,我们设定一定的显著性因子,就可以估算出误判次数的上下界。
比如T4这棵子树的误差率:
子树误差率的标准误差:
子树替换为一个叶节点后,其误差率为:
因为,所以决定将子树T4替换这一个叶子节点。
1.3.2 连续值属性的改进
相对于那些离散值属性,分类树算法倾向于选择那些连续值属性,因为连续值属性会有更多的分支,熵增益也最大。算法需要克服这种倾向。还记得前面讲得如何克服分类树算法倾向于离散值较多的离散属性么?对了,我们利用增益率来克服这种倾向。增益率也可以用来克服连续值属性倾向。增益率作为选择属性的依据克服连续值属性倾向,这是没有问题的。但是如果利用增益率来选择连续值属性的分界点,会导致一些副作用。分界点将样本分成两个部分,这两个部分的样本个数之比也会影响增益率。根据增益率公式,我们可以发现,当分界点能够把样本分成数量相等的两个子集时(我们称此时的分界点为等分分界点),增益率的抑制会被最大化,因此等分分界点被过分抑制了。子集样本个数能够影响分界点,显然不合理。因此在决定分界点是还是采用增益这个指标,而选择属性的时候才使用增益率这个 指标。这个改进能够很好得抑制连续值属性的倾向。当然还有其它方法也可以抑制这种倾向,比如MDL,有兴趣的读者可以自己阅读相关文章。
1.3.3 处理缺失属性
如果有些训练样本或者待分类样本缺失了一些属性值,那么该如何处理?要解决这个问题,需要考虑个问题:i)当开始决定选择哪个属性用来进行分支时,如果有些训练样本缺失了某些属性值时该怎么办?ii)一个属性已被选择,那么在决定分支的时候如果有些样本缺失了该属性该如何处理?iii)当决策树已经生成,但待分类的样本缺失了某些属性,这些属性该如何处理?针对这三个问题,昆兰提出了一系列解决的思路和方法。
对于问题i),计算属性a的增益或者增益率时,如果有些样本没有属性a,那么可以有这么几种处理方式:(I)忽略这些缺失属性a的样本。(C)给缺失属性 a的样本赋予属性a一个均值或者最常用的的值。(R)计算增益或者增益率时根据缺失属性样本个数所占的比率对增益/增益率进行相应的“打折”。(S)根据 其他未知的属性想办法把这些样本缺失的属性补全。
对于问题ii),当属性a已经被选择,该对样本进行分支的时候,如果有些样本缺失了属性a,那么:(I)忽略这些样本。(C)把这些样本的属性a赋予一个均值或者最常出现的值,然后再对他们进行处理。(R)把这些属性缺失样本,按照具有属性a的样本被划分成的子集样本个数的相对比率,分配到各个子集中去。至于哪些缺失的样本被划分到子集1,哪些被划分到子集2,这个没有一定的准则,可以随机而动。(A)把属性缺失样本分配给所有的子集,也就是说每个子集都有这些属性缺失样本。(U)单独为属性缺失的样本划分一个分支子集。(S)对于缺失属性a的样本,尝试着根据其他属性给他分配一个属性a的值,然后继续处 理将其划分到相应的子集。
对于问题iii),对于一个缺失属性a的待分类样本,有这么几种选择:(U)如果有单独的确实分支,依据此分支。(c)把待分类的样本的属性a值分配一个 最常出现的a的属性值,然后进行分支预测。(S)根据其他属性为该待分类样本填充一个属性a值,然后进行分支处理。(F)在决策树中属性a节点的分支上,遍历属性a节点的所有分支,探索可能所有的分类结果,然后把这些分类结果结合起来一起考虑,按照概率决定一个分类。(H)待分类样本在到达属性a节点时就终止分类,然后根据此时a节点所覆盖的叶子节点类别状况为其分配一个发生概率最高的类。
1.3.4 推理规则
C4.5决策树能够根据决策树生成一系列规则集,我们可以把一棵决策树看成一系列规
则的组合。一个规则对应着从根节点到叶子节点的路径,该规则的条件是路径上的条件,结果是叶子节点的类别。C4.5首先根据决策树的每个叶子节点生成一个规则集,对于规则集中的每条规则,算法利用“爬山”搜索来尝试是否有条件可以移除,由于移除一个条件和剪枝一个内部节点本质上是一样的,因此前面提到的悲观剪枝算法也被用在这里进行规则简化。MDL准则在这里也可以用来衡量 对规则进行编码的信息量和对潜在的规则进行排序。简化后的规则数目要远远小于决策树的叶子节点数。根据简化后的规则集是无法重构原来的决策树的。规则集相比决策树而言更具有可操作性,因此在很多情况下我们需要从决策树中推理出规则集。C4.5有个缺点就是如果数据集增大了一点,那么学习时间会有一个迅速地增长。