文章记录的内容是参加DataWhale的组队学习统计学习方法(第二版)习题解答过程中的笔记与查缺补漏!参考解答地址:决策树。
1. 根据表5.1所给的训练数据集,利用信息增益比(C4.5算法)生成决策树。
解答思路:
- 列出C4.5的生成算法;
- 使用sklearn的DecisionTreeClassifier类构建决策树,并使用graphviz包展示,默认是Gini,这里可以作为自编程的验证;
- 通过自编程实现C4.5算法生成决策树,并进行特征选择。
先看看 C4.5 算法生成决策树的过程:
输入:训练数据集 \(D\),特征集 \(A\) 阈值 \(\epsilon\);
输出:决策树 \(T\)。
(1)如果 \(D\) 中所有实例属于同一类 \(C_k\),则置 \(T\) 为单结点树,并将 \(C_k\) 作为该结点的类,返回 \(T\);
(2)如果 \(A = \emptyset\),则置 \(T\) 为单结点树,并将\(D\)中实例数最大的类 \(C_k\) 作为该结点的类,返回 \(T\);
(3)否则,按式 \(\displaystyle g_R(D,A)=\frac{g(D,A)}{H_A(D)}\) 计算 \(A\) 中各特征对 \(D\) 的信息增益比,选择信息增益比最大的特征 \(A_g\);
(4)如果 \(A_g\) 的信息增益比小于阈值 \(\epsilon\),则置 \(T\) 为单结点树,并将 \(D\) 中实例数最大的类 \(C_k\) 作为该结点的类,返回 \(T\);
(5)否则,对 \(A_g\) 的每一可能值 \(a_i\),依 \(A_g=a_i\) 将 \(D\) 分割为子集若干非空 \(D_i\),将 \(D_i\) 中实例数最大的类作为标记,构建子结点,由结点及其子结点构成树 \(T\),返回 \(T\);
(6)对结点 \(i\),以 \(D_i\) 为训练集,以 \(A-\{A_g\}\) 为特征集,递归地调用步(1)~步(5),得到子树 \(T_i\),返回 \(T_i\)
其中一个比较重要的部分就是信息增益比的 \(g_R(D,A)\) 的计算。于 ID3 算法不同,C4.5 使用的是信息增益比作为数据集划分时特征选择的准则(ID3 和 C4.5 的作者是同一个人,ID3 先于 C4.5 被提出,但是 ID4 被其他人占用了)。看一下信息增益比的计算方式:
其中 \(g(D, A)\) 是信息增益,\(H_A(D)\) 是数据集 \(D\) 关于特征 \(A\) 的值的熵,即以 \(A\) 的值的不确定性,看看这两个值分别是怎么算的:
上式中 \(C_k\) 表示 \(D\) 类别为 \(k\) 的样本集合,\(D_i\) 表示按照 \(A\) 的 \(n\) 个取值对 \(D\) 进行划分时的一个子集。\(H(D \mid A)\) 表示 \(A\) 对 \(D\) 的经验条件熵。
可以看到 \(H(D \mid A)\) 和 \(H_A(D)\) 很像,
- \(H(D \mid A)\) :\(A\) 对 \(D\) 的经验条件熵,表示把 \(D\) 按照 \(A\) 的取值划分后的子集的熵,相当于只使用 \(A\) 来分类时的熵;
- \(H_A(D)\) :\(D\) 关于 \(A\) 的值的熵,相当于把 \(A\) 当作数据集的标签后,再衡量 \(D\) 的熵。也可以看成衡量 \(D\) 中,\(A\) 这个特征取值的不确定性,如果 \(A\) 的取值越多,则熵越大,可以避免信息增益中偏向特征取值多的问题。
具体的过程参考这里。注意 ID3 和 C4.5 是多叉树哦!
2. 已知如表5.2所示的训练数据,试用平方误差损失准则生成一个二叉回归树。
解答思路:
- 根据书中第81页平方误差损失准则,列出最小二乘回归树生成算法(算法5.5);
- 编写代码,实现算法,并用表5.2训练数据进行验证。
这里要求用决策树来解决一个回归问题。其实不管是分类问题还是回归问题,都遵循相似的过程:
- 指定一个特征选择的准则,停止条件;
- 给定一个数据集 \(D\),特征集合;
- 通过准则找到一个特征,将 \(D\) 划分成多个小的数据集 \(D_i\),并得到一个新的特征集合,新的特征集合去除了刚刚使用的特征;
- 回到第2步,直至满足停止条件。
CART(Classfication and Regression Tree)决策树的生成就是递归地构建二叉决策树的过程,对回归树用平方误差最小化准则,对分类树用基尼指数(Gini index)最小化准则,进行特征选择,生成二叉树。
算法5.5(最小二乘回归树生成算法)
输入:训练数据集\(D\)
输出:回归树\(f(x)\)
在训练数据集所在的输入空间中,递归地将每个区域划分为两个子区域并决定每个子区域上的输出值,构建二叉决策树;
(1)选择最优切分变量\(j\)与切分点\(s\),求解\[\min_{j,s} \left[ \min_{c_1} \sum_{x_i \in R_1(j,s)} (y_i - c_1)^2 + \min_{c_2} \sum_{x_i \in R_2(j,s)} (y_i - c_2)^2\right] \]遍历变量\(j\),对固定的切分变量\(j\)扫描切分点\(s\),选择使得上式达到最小值的对\((j,s)\)
(2)用选定的对\((j,s)\)划分区域并决定相应的输出值:\[R_1(j,s)=\{x|x^{(j)}\leqslant s\}, R_2(j,s)=\{x|x^{(j)} > s\} \\ \hat{c}_m = \frac{1}{N_m} \sum_{x_i \in R_m(j,s)} y_i, x \in R_m, m=1,2 \](3)继续对两个子区域调用步骤(1),(2),直至满足停止条件
(4)将输入空间划分为\(M\)个区域\(R_1,R_2,\cdots,R_M\),生成决策树:\[f(x)=\sum_{m=1}^M \hat{c}_m I(x \in R_m) \]
注意,在回归树中,每次特征选择不仅选择特征,还需在这个特征的取值中找到最优的切分点。在分类树中,选择完特征后,不一定要选择特征的切分点,如 ID3 和 C4.5 中,只是按照特征的取值对数据集进行划分,但是在 CART 中,也会选择特征的切分点(测试特征的每一个取值,按照是否将数据集划分成两部分)。
具体过程参考这里。
3. 证明 CART 剪枝算法中,当 \(\alpha\) 确定时,存在唯一的最小子树 \(T_{\alpha}\) 使损失函数 \(C_{\alpha}\) 最小。
解答思路:
- 列出 CART 剪枝算法;
- 列出树的剪枝算法;
- 采用反证法,假设存在两棵子树使得损失函数最小。
既然要剪枝,那肯定是有一个是否剪枝的准则的,那就是决策树的损失。先介绍以下怎么衡量决策树的损失:
其中 \(T\) 是一棵决策树,\(C(T)\) 是 \(T\) 在训练数据上的误差,\(T\) 表示决策树的叶节点数目,\(\alpha\) 是计算损失时的一个参数,用于权衡训练数据上的误差于模型复杂度的重要性。在剪枝的过程中,逐步测试每一个内部结点 \(t\),在两种情况下计算 \(C_\alpha\),
- 以 \(t\) 作为根节点的子树 \(T_t\),计算 \(C_\alpha(T_t) = C(T_t) + \alpha |T_t|\);
- 以 \(t\) 作为叶节点,即把 \(T_t\) 合并为一个叶节点,计算 \(C_\alpha(t) = C(t) + \alpha |t| = C(t) + \alpha\)。
注意此时 \(\alpha\) 并未指定,因此对于每一个内部节点 \(t\) 都可以通过这样的方式求出 \(\alpha\):
可以得到 \(\alpha = \frac{ C(t) - C(T_t) }{ |T_t| - 1 }\),选择所有最小的 \(\alpha\) 中对应的内部节点,对其进行剪枝。这样我们就完成了一次剪枝,接下来就可以在剪枝后的树上继续剪枝了。
关于 CART 的剪枝,可以参考我的这篇博客:CART剪枝过程。
具体证明请参考这里。
4. 证明 CART 剪枝算法中求出的子树序列\(\{T_0,T_1,\cdots,T_n\}\)分别是区间\(\alpha \in [\alpha_i,\alpha_{i+1})\)的最优子树\(T_{\alpha}\),这里\(i=0,1,\cdots,n,0=\alpha_0 < \alpha_1 < \cdots, \alpha_n < +\infty\)。
解答思路:
- 对题目重新进行表述;
- 证明当 \(\alpha=0\) 和 \(\alpha= + \infty\) 时的最优子树;
- 证明 \(T_1\) 为区间 \([\alpha_1,\alpha_2)\) 的最优子树。
具体证明过程参考这里。