决策树
-
决策树是一种基本的分类与回归方法。这里主要讨论决策树用于分类。
-
决策树模型是描述对样本进行分类的树形结构。树由结点和有向边组成:
- 内部结点表示一个特征或者属性。
- 叶子结点表示一个分类。
- 有向边代表了一个划分规则。
-
决策树从根结点到子结点的的有向边代表了一条路径。决策树的路径是互斥并且是完备的。
-
用决策树分类时,对样本的某个特征进行测试,根据测试结果将样本分配到树的子结点上。此时每个子结点对应该特征的一个取值。
递归地对样本测试,直到该样本被划分叶结点。最后将样本分配为叶结点所属的类。
-
决策树的优点:可读性强,分类速度快。
-
决策树学习通常包括3个步骤:
- 特征选择。
- 决策树生成。
- 决策树剪枝。
不纯度 |
---|
决策树的每个叶子节点中都会包含一组数据,在这组数据中,如果有某一类标签占有较大的比例,我们就说叶子节点“纯”,分枝分得好。某一类标签占的比例越大,叶子就越纯,不纯度就越低,分枝就越好。如果没有哪一类标签的比例很大,各类标签都相对平均,则说叶子节点”不纯“,分枝不好,不纯度高。 |
计算不纯度的三种方法
决策树最终的优化目标是使得叶节点的总不纯度最低,即对应衡量不纯度的指标最低
N = ∣ D ∣ , N k = ∣ C k ∣ N=|D|,N_k=|C_k| N=∣D∣,Nk=∣Ck∣
ID3算法
李航ppt中有个十分详细的ID3例子
基本公式
- 经验熵称为信息熵
- 经验条件熵称为加权信息熵
对训练数据集(或子集)D,计算其每个特征的信息增益,并比较它们的大小,选择信息增益最大的特征
ID3
生成算法:
-
输入:
- 训练数据集 D D D
- 特征集合 A ˉ = A 1 , A 2 , . . . , A n \bar{A}={A_1,A_2,...,A_n} Aˉ=A1,A2,...,An
- 特征信息增益阈值 ε > 0 \varepsilon>0 ε>0
-
输出:决策树
-
算法步骤:
-
若 D D D中所有样本均属于同一类 C k C_k Ck,则 T T T为单结点树,并将$C_k $作为该结点的类标记,算法终止。
-
若 A ˉ = ϕ \bar{A}=\phi Aˉ=ϕ,则 T T T为单结点树,将 D D D中样本数最大的类 C k C_k Ck 作为该结点的类标记,算法终止。
-
否则计算 g ( D , A j ) , j = 1 , 2 , . . , n g(D,A_j),j=1,2,..,n g(D,Aj),j=1,2,..,n,选择信息增益最大的特征 A g A_g Ag:
-
若 g ( D , A g ) < ε g(D,A_g)<\varepsilon g(D,Ag)<ε,则置T为单结点树,将 D D D中样本数最大的类 C k C_k Ck作为该结点的类标记,算法终止 。
-
若 g ( D , A j ) > = ε g(D,A_j)>=\varepsilon g(D,Aj)>=ε,则对 A g A_g Ag 特征的每个可能取值 a i , i = 1 , 2 , . . , n g a_i,i=1,2,..,n_g ai,i=1,2,..,ng,根据 A g = a i A_g=a_i Ag=ai将 D D D划分为若干个非空子集 。
将 D i D_i Di中样本数最大的类作为该子集的标记,构建子结点。
-
-
对第 i i i个子结点, 以 D i D_i Di为训练集, 以 A ˉ − A g \bar{A}-A_g Aˉ−Ag为特征集,递归地调用前面的步骤来构建子树。
即 D n e w = D i , A ˉ n e w = A ˉ o l d − A g D^{new}=D_i,\bar{A}^{new}=\bar{A}^{old}-A_g Dnew=Di,Aˉnew=Aˉold−Ag
-
注:上面的 A ˉ \bar{A} Aˉ为特征的集合, A j A_j Aj为单个的特征;
第二次分枝
一个属性只能用一次:当这个属性被当做父节点后,则其子节点就不会再用这个属性了,因为每个子节点的这个属性都是一致的,不能进行划分了.但和其同一层的节点还是可以进行划分的。
青年节点的经验熵的计算如下:
这是按照年龄进行分裂后的一个子树,所以在这个子树上的年龄属性都是一致的,没有计算年龄属性的必要了。只能用剩余的三个属性进行计算。且其余子树也是用剩下的三个属性进行计算==.每颗子树之间的计算不会影响.==或许所有的子树都会按照收入这个属性进行分裂也是可能的。
下面做的就是将这颗子树当做父节点进行计算.而且经验熵的计算不会乘以384/1025(这棵树的样本为384,总样本数量为1025),其实这个经验熵在上一步计算经验条件熵时已经计算过了。
第二次分枝时的 H ( D ) H(D) H(D)为第一次分枝时计算年龄的信息增益中的 H ( D 1 ) H(D_1) H(D1)
见下,第一次分枝时计算年龄的信息增益,先计算青年的 H ( D 1 ) H(D_1) H(D1) ,
计算中年的 H ( D 2 ) = 0 H(D_2)=0 H(D2)=0,与老年的 H ( D 3 ) = 0.9157 H(D_3)=0.9157 H(D3)=0.9157,接下来根据上面得到的三个 H ( D i ) H(D_i) H(Di)计算经验条件熵,也就是图中的平均信息期望$E(年龄) $,得到E后,可以计算年龄的信息增益了。
ID3其局限性主要有以下几点:
- 分支度越高(分类水平越多)的离散变量往往子节点的总信息熵会更小,ID3是按照某一列进行切分,有一些列的分类可能不会对我需要的结果有足够好的指示。极限情况下取ID作为切分字段,每个分类的纯度都是100%,因此这样的分类方式是没有效益的。
- 不能直接处理连续型变量,若要使用ID3处理连续型变量,则首先需要对连续变量进行离散化。
- 对缺失值较为敏感,使用ID3之前需要提前对缺失值进行处理。
- 没有剪枝的设置,容易导致过拟合,即在训练集上表现很好,测试集上表现很差。
- 上面的例子就是已经将特征离散化后的干净数据集
C4.5
选择信息增益率大的产生决策树的节点
用信息增益比率(gain ratio)来作为选择分支的准则
g R ( D , A ) = g ( D , A ) / H A ( D ) g_R(D,A)=g(D,A)/H_A(D) gR(D,A)=g(D,A)/HA(D)
分母表示训练数据集D关于特征A的熵
IV的计算
也称为分支度(IV:Information Value)
I V = H A ( D ) = − ∑ i = 1 n ∣ D i ∣ ∣ D ∣ l o g 2 ∣ D i ∣ ∣ D ∣ IV=H_A(D)=-\sum_{i=1}^{n}\frac{|D_i|}{|D|}log_2\frac{|D_i|}{|D|} IV=HA(D)=−∑i=1n∣D∣∣Di∣log2∣D∣∣Di∣
n是特征A的取值个数.
这种计算方法其实和经验熵的计算是一致的,只不过经验熵是根据标签进行计算的.而这是根据属性进行计算的。
IV相当于一个惩罚项,如果以ID进行划分的话,IV值为 l o g 2 ∣ D ∣ log_2|D| log2∣D∣会非常大。所以IV值会随着叶子节点上样本量的变小而逐渐变大,这就是说一个特征中如果标签分类太多,每个叶子上的IV值就会非常大.
算法流程
C4.5
生成算法与 ID3
算法相似,但是 C4.5
算法在生成过程中用信息增益比来选择特征
输入:训练数据集
D
D
D,特征
A
A
A,阈值
ε
\varepsilon
ε
输出:决策树
T
T
T
- 若 D D D中所有实例属于同一类 C k C_{k} Ck,则 T T T为单结点树,并将类 C k C_{k} Ck作为该结点的类标记,返回 T T T;
- 若 A = ∅ A = \emptyset A=∅,则 T T T为单结点树,并将 D D D中实例数最大的类 C k C_{k} Ck作为该结点的类标记,返回 T T T;
- 否则,计算
A
A
A中各特征
D
D
D的信息增益,选择信息增益比最大的特征
A
g
A_{g}
Ag
$\begin{align*} \ & A_{g} = \arg \max_{A} g_{R} \left( D, A \right) \end{align*} $ - 如果 A g A_{g} Ag的信息增益小于阈值 ε \varepsilon ε,则置 T T T为单结点树,并将 D D D中实例数量最大的类 C k C_{k} Ck作为该结点的类标记,返回 T T T;
- 否则,对 A g A_{g} Ag的每一个可能值 a i a_{i} ai,依 A g = a i A_{g}=a_{i} Ag=ai将 D D D分割为若干非空子集 D i D_{i} Di,将 D i D_{i} Di中实例数对大的类作为标记,构建子结点,由结点及其子结点构成树 T T T,返回 T T T;
- 对第 i i i个子结点,以 D i D_{i} Di为训练集,以 A − { A g } A-\left\{A_{g}\right\} A−{Ag}为特征集,递归地调用步1.~步5.,得到子树 T i T_{i} Ti,返回 T i T_{i} Ti。
处理连续变量
在C4.5中,同样还增加了针对连续变量的处理手段。如果输入特征字段是连续型变量,则有下列步骤:
- 算法首先会对这一列数进行从小到大的排序
- 选取相邻的两个数的中间数作为切分数据集的备选点,若一个连续变量有N个值,则在C4.5的处理过程中将产生N-1个备选切分点,并且每个切分点都代表着一种二叉树的切分方案,例如
这里需要注意的是,此时针对连续变量的处理并非是将其转化为一个拥有N-1个分类水平的分类变量,而是将其转化成了N-1个二分方案,而在进行下一次的切分过程中,这N-1个方案都要单独带入考虑,其中每一个切分方案和一个离散变量的地位均相同(一个离散变量就是一个单独的多路切分方案).
决策树的剪枝
-
决策树生成算法生成的树往往对于训练数据拟合很准确,但是对于未知的测试数据分类却没有那么准确。即出现过拟合现象。
过拟合产生得原因是决策树太复杂。解决的办法是:对决策树剪枝,即对生成的决策树进行简化。
-
决策树的剪枝是从已生成的树上裁掉一些子树或者叶结点,并将根结点或者其父结点作为新的叶结点。
剪枝的依据是:极小化决策树的整体损失函数或者代价函数。
-
决策树生成算法是学习局部的模型,决策树剪枝是学习整体的模型。即:生成算法仅考虑局部最优,而剪枝算法考虑全局最优。
设树
T
T
T的叶结点个数为
∣
T
∣
\left| T \right|
∣T∣,
t
t
t是树
T
T
T的叶结点,该叶结点有
N
t
N_{t}
Nt个样本点,其中属于
c
k
c_k
ck类的样本点有
N
t
k
N_{tk}
Ntk个,
k
=
1
,
2
,
⋯
 
,
K
k=1,2,\cdots,K
k=1,2,⋯,K,
H
t
(
T
)
H_{t}\left(T\right)
Ht(T)为叶结点
t
t
t上的经验熵, 则决策树的损失函数
KaTeX parse error: No such environment: align* at position 8: \begin{̲a̲l̲i̲g̲n̲*̲}̲ \\ & C_{\alpha…
其中,
α
≥
0
\alpha \geq 0
α≥0为参数,经验熵
KaTeX parse error: No such environment: align* at position 8: \begin{̲a̲l̲i̲g̲n̲*̲}̲ \\ & H_{t} \le…
- 叶结点个数越多,表示决策树越复杂,则损失函数越大。
- 叶结点经验熵越大,表示叶结点的样本类别分布很分散,则损失函数越大。
- 叶结点经验熵还需要加权,权重为叶结点大小。即:越大的叶结点,其分类错误的影响越大。
损失函数中,记
KaTeX parse error: No such environment: align* at position 8: \begin{̲a̲l̲i̲g̲n̲*̲}̲ \\ & C \left( …
则
KaTeX parse error: No such environment: align* at position 8: \begin{̲a̲l̲i̲g̲n̲*̲}̲ \\ & C_{\alpha…
其中,
C
(
T
)
C \left( T \right)
C(T)表示模型对训练数据的预测误差,即模型与训练数据的拟合程度,
∣
T
∣
\left| T \right|
∣T∣表示模型复杂度,参数
α
≥
0
\alpha \geq 0
α≥0控制两者之间的影响。
C ( T ) = 0 C(T)=0 C(T)=0 意味着 N t k = N t N_{tk}=N_t Ntk=Nt,即每个结点 t t t内的样本都是纯的,即单一的分类。
决策树划分得越细致,则树 T T T 的叶子结点越多。当叶结点的数量等于样本集的数量时,树 T T T的每个叶子结点只有一个样本点。此时每个叶结点内的样本都是纯的,从而 C ( T ) = 0 C(T)=0 C(T)=0 。
这样的决策树其实是没有什么实用价值的,所以必须使用正则化项来约束决策树的复杂程度。
参数 α \alpha α控制预测误差与模型复杂度之间的关系。
- 较大的 α \alpha α 会选择较简单的模型 。
- 较小的 α \alpha α 会选择较复杂的模型。
- α = 0 \alpha=0 α=0只考虑对训练集的拟合,不考虑模型复杂度。
决策树剪枝的准则是:考虑当 α \alpha α确定时, C α ( T ) C_\alpha(T) Cα(T) 最小化。这等价于正则化的极大似然估计。
树的剪枝算法:
输入:决策树 T T T,参数 α \alpha α
输出:修剪后的子树 T α T_{\alpha} Tα
-
计算每个结点的经验熵
-
递归地从树的叶结点向上回缩
设一组叶结点回缩到其父结点之前与之后的整体树分别为 T B T_{B} TB与 T A T_{A} TA,其对应的损失函数值分别是 C α ( T B ) C_{\alpha} \left( T_{B} \right) Cα(TB)与 C α ( T A ) C_{\alpha} \left( T_{A} \right) Cα(TA),如果
KaTeX parse error: No such environment: align* at position 9: \begin{̲a̲l̲i̲g̲n̲*̲}̲ \\ & C_{\alpha…
则进行剪枝,即将父结点变为新的叶结点。 -
返回2.,直到不能继续为止,得到损失函数最小的子树 T α T_{\alpha} Tα
CART-二叉树
二叉树不是二分类树
基尼系数
基尼指数(基尼不纯度):表示在样本集合中一个随机选中的样本被分错的概率
注意: Gini指数越小表示集合中被选中的样本被分错的概率越小,也就是说集合的纯度越高,反之,集合越不纯。
即 基尼指数(基尼不纯度)= 样本被选中的概率 * 样本被分错的概率
KaTeX parse error: No such environment: align* at position 8: \begin{̲a̲l̲i̲g̲n̲*̲}̲ \\ & Gini \lef…
则样本集D的基尼指数为
(其中
K
K
K为样本的类别总数,当为二分类问题时,K为2;为多分类问题时,K大于2)
G
i
n
i
(
D
)
=
1
−
∑
k
=
1
K
(
∣
C
k
∣
D
)
2
Gini(D)=1-\sum_{k=1}^{K}(\frac{|C_k|}{D})^2
Gini(D)=1−k=1∑K(D∣Ck∣)2
根据特征A进行划分
写法1:
写法2:
KaTeX parse error: No such environment: align* at position 8: \begin{̲a̲l̲i̲g̲n̲*̲}̲ \\ & Gini \lef…
这里的A为单个的特征
需要说明的是CART是个二叉树,也就是当使用某个特征划分样本集合只有两个集合:
- 等于给定的特征值 的样本集合 D 1 D_1 D1
- 不等于给定的特征值 的样本集合 D 2 D_2 D2
因而对于一个具有多个取值(超过2个)的特征,需要计算以每一个取值作为划分点,对样本D划分之后子集的纯度Gini(D,A=s),(其中A=s 表示特征A的可能取值)
然后从所有的可能划分的Gini(D,A=s)中找出Gini指数最小的划分,这个划分的划分点,便是使用特征A对样本集合D进行划分的最佳划分点。
CART树算法流程
流程中的Aj就是一个特征,可以取不同的值
例如Aj为年龄,可以取到的值为{老,中,青}
CART 树与ID3 决策树和 C4.5 决策树的重要区别:
- CART 树是二叉树,而后两者是N 叉树。
由于是二叉树,因此 CART 树的拆分不依赖于特征的取值数量。因此CART 树也就不像ID3 那样倾向于取值数量较多的特征。
- CART 树的特征可以是离散的,也可以是连续的。
而ID3的特征是离散的。如果是连续的特征,则需要执行分桶来进行离散化。
CART 树处理连续特征时,也可以理解为二分桶的离散化。
CART树会计算每个特征的每种可能的取值的基尼指数[需要两个循环,第一个循环是取到每个特征,第二个循环是取每个特征的每个可能的取值],而后两者都是对每个特征进行计算信息增益,而不会取到每个特征中的取值[只有一个循环]
CART树剪枝
CART剪枝算法:
输入:CART决策树 T 0 T_{0} T0
输出:最优决策树 T α T_{\alpha} Tα
-
设 k = 0 , T = T 0 k=0, T=T_{0} k=0,T=T0
-
设 α = + ∞ \alpha=+\infty α=+∞
-
自下而上地对各内部结点 t t t计算$ C\left(T_{t}\right),\left| T_{t} \right|$,以及
KaTeX parse error: No such environment: align* at position 9: \begin{̲a̲l̲i̲g̲n̲*̲}̲ \\ & g\left(t\…
其中, T t T_{t} Tt表示以 t t t为根结点的子树,$ C\left(T_{t}\right) 是 对 训 练 数 据 的 预 测 误 差 , 是对训练数据的预测误差, 是对训练数据的预测误差,\left| T_{t} \right| 是 是 是T_{t}$的叶结点个数。 -
自下而上地访问内部结点 t t t,如果有 g ( t ) = α g\left(t\right)=\alpha g(t)=α,则进行剪枝,并对叶结点 t t t以多数表决法决定其类别,得到树 T T T
-
设 k = k + 1 , α k = α , T k = T k=k+1, \alpha_{k}=\alpha, T_{k}=T k=k+1,αk=α,Tk=T
-
如果 T T T不是由根结点单独构成的树,则回到步骤4.
-
采用交叉验证法在子树序列 T 0 , T 1 , ⋯   , T n T_{0},T_{1},\cdots,T_{n} T0,T1,⋯,Tn中选取最优子树 T α T_{\alpha} Tα
Classification and Regression Trees, CART
(1)CART既能是分类树,又能是分类树; (2)当CART是分类树时,采用GINI值作为节点分裂的依据; 当CART是回归树时,采用样本的最小方差作为节点分裂的依据; (3)CART是一棵二叉树。
CART如何选择分裂的属性?
分裂的目的是为了能够让数据变纯,使决策树输出的结果更接近真实值。 那么CART是如何评价节点的纯度呢?如果是分类树,CART采用GINI值衡量节点纯度; 如果是回归树,采用样本方差衡量节点纯度。节点越不纯,节点分类或者预测的效果就越差。
CART算法流程与C4.5算法相类似:
- 1若满足停止分裂条件(样本个数小于预定阈值,或Gini指数小于预定阈值 (样本基本属于同一类,或没有特征可供分裂),则停止分裂;
- 2否则,选择最小Gini指数进行分裂;
- 3递归执行1-2步骤,直至停止分裂。
首先我们看看决策树算法的优点:
1)简单直观,生成的决策树很直观。
2)基本不需要预处理,不需要提前归一化,处理缺失值。
3)使用决策树预测的代价是O(log2m)。 m为样本数。
4)既可以处理离散值也可以处理连续值。很多算法只是专注于离散值或者连续值。
5)可以处理多维度输出的分类问题。
6)相比于神经网络之类的黑盒分类模型,决策树在逻辑上可以得到很好的解释
7)可以交叉验证的剪枝来选择模型,从而提高泛化能力。
8) 对于异常点的容错能力好,健壮性高。
我们再看看决策树算法的缺点:
1)决策树算法非常容易过拟合,导致泛化能力不强。可以通过设置节点最少样本数量和限制决策树深度来改进。
2)决策树会因为样本发生一点点的改动,就会导致树结构的剧烈改变。这个可以通过集成学习之类的方法解决。
3)寻找最优的决策树是一个NP难的问题,我们一般是通过启发式方法,容易陷入局部最优。可以通过集成学习之类的方法来改善。
4)有些比较复杂的关系,决策树很难学习,比如异或。这个就没有办法了,一般这种关系可以换神经网络分类方法来解决。
5)如果某些特征的样本比例过大,生成决策树容易偏向于这些特征。这个可以通过调节样本权重来改善
CART树计算
以属性“职业”为例,一共有三个离散值,“学生”、“老师”、“上班族”。该属性有三种划分的方案,分别为{“学生”}、{“老师”、“上班族”},{“老师”}、{“学生”、“上班族”},{“上班族”}、{“学生”、“老师”},分别计算三种划分方案的子节点GINI值或者样本方差,选择最优的划分方法,如下图所示:
第一种划分方法:{“学生”}、{“老师”、“上班族”}
预测是否已婚(分类):
预测年龄(回归):
第二种划分方法:{“老师”}、{“学生”、“上班族”}
预测是否已婚(分类):
预测年龄(回归):
第三种划分方法:{“上班族”}、{“学生”、“老师”}
预测是否已婚(分类):
预测年龄(回归):
综上,如果想预测是否已婚,则选择{“上班族”}、{“学生”、“老师”}的划分方法,如果想预测年龄,则选择{“老师”}、{“学生”、“上班族”}的划分方法。
剪枝处理
从决策树的构造流程中我们可以直观地看出:不管怎么样的训练集,决策树总是能很好地将各个类别分离开来,这时就会遇到之前提到过的问题:过拟合(overfitting),即太依赖于训练样本。剪枝(pruning)则是决策树算法对付过拟合的主要手段,剪枝的策略有两种如下:
- 预剪枝(prepruning):在构造的过程中先评估,再考虑是否分支[设定剪枝的阈值]。
- 后剪枝(post-pruning):在构造好一颗完整的决策树后,自底向上,评估分支的必要性。
评估指的是性能度量,即决策树的泛化性能。之前提到:可以使用测试集作为学习器泛化性能的近似,因此可以将数据集划分为训练集和测试集。预剪枝表示在构造数的过程中,对一个节点考虑是否分支时,首先计算决策树不分支时在测试集上的性能,再计算分支之后的性能,若分支对性能没有提升,则选择不分支(即剪枝)。后剪枝则表示在构造好一颗完整的决策树后,从最下面的节点开始,考虑该节点分支对模型的性能是否有提升,若无则剪枝,即将该节点标记为叶子节点,类别标记为其包含样本最多的类别。
上图分别表示不剪枝处理的决策树、预剪枝决策树和后剪枝决策树。预剪枝处理使得决策树的很多分支被剪掉,因此大大降低了训练时间开销,同时降低了过拟合的风险,但另一方面由于剪枝同时剪掉了当前节点后续子节点的分支,因此预剪枝“贪心”的本质阻止了分支的展开,在一定程度上带来了欠拟合的风险。而后剪枝则通常保留了更多的分支,因此采用后剪枝策略的决策树性能往往优于预剪枝,但其自底向上遍历了所有节点,并计算性能,训练时间开销相比预剪枝大大提升。
连续值与缺失值处理
对于连续值的属性,若每个取值作为一个分支则显得不可行,因此需要进行离散化处理,常用的方法为二分法,基本思想为:给定样本集D与连续属性α,二分法试图找到一个划分点t将样本集D在属性α上分为≤t与>t。
- 首先将α的所有取值按升序排列,所有相邻属性的均值作为候选划分点(n-1个,n为α所有的取值数目)。
- 计算每一个划分点划分集合D(即划分为两个分支)后的信息增益。
- 选择最大信息增益的划分点作为最优划分点。
现实中常会遇到不完整的样本,即某些属性值缺失。有时若简单采取剔除,则会造成大量的信息浪费,因此在属性值缺失的情况下需要解决两个问题:(1)如何选择划分属性。(2)给定划分属性,若某样本在该属性上缺失值,如何划分到具体的分支上。假定为样本集中的每一个样本都赋予一个权重,根节点中的权重初始化为1,则定义:
对于(1):通过在样本集D中选取在属性α上没有缺失值的样本子集,计算在该样本子集上的信息增益,最终的信息增益等于该样本子集划分后信息增益乘以样本子集占样本集的比重。即:
对于(2):若该样本子集在属性α上的值缺失,则将该样本以不同的权重(即每个分支所含样本比例)划入到所有分支节点中。该样本在分支节点中的权重变为:
决策树可视化
import pydotplus
from sklearn.tree import DecisionTreeClassifier, export_graphviz
model = DecisionTreeClassifier()
model.fit(x_train, y_train.astype('int'))
# 输出决策树可视化文件
dot_data = export_graphviz(model, out_file=None, feature_names=list(dataframe.columns)[:6])
graph = pydotplus.graph_from_dot_data(dot_data)
graph.write_pdf('./tree.pdf')
#Image(graph.create_png()) #jupyter里可以显示,pycharm显示不出
graph.write_png(r'DT_show.png')
# 第五章中的决策树
from sklearn.tree import DecisionTreeClassifier as DTC
dtc = DTC(criterion='entropy') # 建立决策树模型,基于信息熵
dtc.fit(x, y) # 训练模型
# 导入相关函数,可视化决策树。
# 导出的结果是一个dot文件,需要安装Graphviz才能将它转换为pdf或png等格式。
from sklearn.tree import export_graphviz
with open("tree.dot", 'w') as f:
f = export_graphviz(dtc, feature_names=x.columns, out_file=f)
# show tree.dot
# $dot -Tpdf tree.dot -o tree.pdf 转换成pdf文件,但中文无法识别
# 菜菜sklearn中的决策树
feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸']
import graphviz
dot_data = tree.export_graphviz(clf
,out_file = None
,feature_names= feature_name
,class_names=["琴酒","雪莉","贝尔摩德"]
,filled=True
,rounded=True
)
graph = graphviz.Source(dot_data)