决策树(注意与规划论中的决策树的区别)是重要的基础算法之一,其中一条发展路径为由“树”到“森林”(如,随机森林算法)。 这里围绕该“树”进行讨论:由样本属性取不同的值产生“分裂”,从而分叉形成“树”,树需要剪枝修整。
决策树算法
基本算法
【西瓜书图4.2】描述了决策树的基本算法,为理解该算法,我们作如下说明。
1.树的生长:属性个数 d d d决定树的深度,每一次向下生长(倒树)一层消耗掉一个属性 a ∗ a_* a∗(第8句及第14句体现),这一层的宽度(分叉数)由该属性 a ∗ a_* a∗的取值数决定(第9句体现)。 宽度用“ f o r \mathrm{for} for循环”实现(第9句),而深度由递归实现(第14句)。
2.树的叶子:在树的生长过程中,遇到叶子则为该方向的递归终结,叶子有三种情况,对应于算法中的三个 r e t u r n \mathrm{return} return(分别在第3、6、12句),三种情况的解释在【西瓜书图4.2】下面的一段文字中。
3.决策点:在树的生长过程中,每一次向下生长都要“决策”消耗掉哪个属性 a ∗ a_* a∗(第8句),称为“划分选择”,而不是随便选择一个属性。 故该树称为“决策树”。
4.局部图:树的非叶结点由一个数据集和未使用的属性集组成,我们设待分裂的结点为 ( D , A ) (D,A) (D,A),这里是为方便而记: ( D , A ) (D,A) (D,A)为任一待分裂结点中的情形(变量),而不是指算法初始的 ( D , A ) (D,A) (D,A),实际上它为初始集的子集(因分裂而减少)。 当然,你也可以将这里改为 ( D ′ , A ′ ) (D',A') (D′,A′)以示区别。
将树的生长点展开为两个步骤:选择属性 a ∗ a_* a∗和依该属性的值 a ∗ 1 , a ∗ 2 , ⋯ , a ∗ v a_*^1,a_*^2,\cdots,a_*^v a∗1,a∗2,⋯,a∗v横向扩展分支,得到结果如图4.1所示。
其中,对 D D D依该属性的值作了划分: D = D 1 ⋃ D 2 ⋃ ⋯ ⋃ D v D=D^1\bigcup D^2\bigcup\cdots\bigcup D^v D=D1⋃D2⋃⋯⋃Dv。
基于“栈”或“队列”
本小节从编程角度讨论决策树基本算法的变形。
(1)基于“栈”的深度优先搜索。
我们先将上述图4.1变为如下图4.2。
决策树基本算法是递归算法,它实际上是深度优先树搜索,下面我们先看看等效的“栈”方法表达的深度优先树搜索。
针对图4.2,我们需要构造针对结点操作的“入栈”和“出栈”函数,之后再用如下递归函数(伪代码)进行决策树的生成:
对应的意义如图4.2所示。
上述算法中需要“栈”(stack)有一定的容量(深度):当为二叉树时,每向一下层(while一次)的“栈”操作为pop一次、push两次(for语句)(直到最后叶子不push),这两操作相抵后在“栈”中占位为1,即“栈”的深度为树的深度;当树为多叉树时,for语句使得“栈”的深度大大地大于树的深度(push的次数更多)。 即当“栈”设置过浅时,会产生溢出。
(2)基于“队列”的广度优先搜索。
在上述算法中,将stack(栈)改为queue(队列),则对应的stack.push改为queue.in(入队列)、stack.pop改为queue.out(出队列)。
由于队列是“先进先出”的方式,故while是对“层”进行扫描形成新的“层”,即它是广度优先算法。
在上述广度优先算法的基础上,增加对树的深度控制阈值 M a x D e p t h \mathrm{MaxDepth} MaxDepth,生成结点时标上其深度:
(1)出队的结点 D D D(设深度为 l l l)为“for产生的结点”的父结点,故结点 D a k D_a^k Dak的深度为 l + 1 l+1 l+1;
(2)判断是否是叶子结点,增加一个为叶子的条件:深度达到 M a x D e p t h \mathrm{MaxDepth} MaxDepth的百叶子结点强制改为叶子结点。
为加强控制溢出,在上述广度优先算法中增加结点计数器 c o u n t \mathrm{count} count及其阈值 M a x N o d e \mathrm{MaxNode} MaxNode,作如下修改:
(1)while之前,对计数器初始化 c o u n t = 1 \mathrm{count}=1 count=1;
(2)for中生成结点 D a k D_a^k Dak时计数器 c o u n t \mathrm{count} count加1;
(3)计数器 c o u n t \mathrm{count} count加1时判断是否达到阈值 M a x N o d e \mathrm{MaxNode} MaxNode,一旦达到,则跳出循环while;
(4)跳出循环while后,将队列中的元素全部视为叶子结点处理。
特点:在多叉树时,由于宽度各层不固定,故 M a x D e p t h \mathrm{MaxDepth} MaxDepth不易控制所需容量,而直接对结点个数计数,其阈值 M a x N o d e \mathrm{MaxNode} MaxNode可直接控制所需内存容量。
本文为原创,您可以:
- 点赞(支持博主)
- 收藏(待以后看)
- 转发(他考研或学习,正需要)
- 评论(或讨论)
- 引用(支持原创)
- 不侵权
上一篇:3.4 纠错输出码(奇想:用编码来分类)
下一篇:4.2 划分选择与剪枝(此事“信息量好大”,暗指该事件不平常)