每个内部结点选择一个离散特征,按取值把样本分到不同子结点,叶子给出类别。划分特征用信息增益来选:增益越大越好;增益相同则选下标更小的特征。每个特征在从根到叶的一条路径上最多使用一次。
当前子集的标签如果已经全部相同,或者没有剩余特征,就把该结点做成叶子。叶子类别取出现次数最多的标签,次数并列时取数值较小的标签。预测时按测试样本的取值往下走;若这个取值在当前结点的训练子集里没有出现,就输出该结点的多数类,并列规则与叶子相同。
实现上先统计标签频率并计算熵,只把实际出现的类别算进去,这样单一类别的熵是 0。对每个候选特征按取值分组,用组的大小做权重,父集熵减去加权熵就是信息增益。候选特征按下标从小到大尝试,只有新的增益比当前最优超出一个很小的容差才替换,因此数值上相等时会留下更小的下标。选中后按取值拆开子集,删掉该特征再递归。预测从根结点出发,沿分支走到叶子,或在未见取值处返回结点上预先保存的多数类。
信息熵表示数据集的不确定性:
H(S)=−i=1∑cpilog2(pi)数据集 S 中有 c 个类别,pi 为第 i 类的出现频率。
按特征 A 划分后,不确定性减少的量是信息增益:
IG(S,A)=H(S)−v∈A∑∣S∣∣Sv∣H(Sv)其中 Sv 是 A 取值为 v 的样本子集。信息增益越大,越适合用该特征分裂。
请实现按信息增益建树的决策树分类器。每条训练样本形如
[feature_1, feature_2, ..., feature_m, label]
特征与类别标签都用整数表示。特征从左到右的下标为 0,1,…,m−1。
建树从根结点开始,规则如下:
预测时从根结点向下。若测试样本在当前特征上的取值没有出现在该结点的训练子集中,则输出该结点的多数标签(次数相同取较小标签)。
下列表格只帮助理解划分过程。真正的输入全部是整数,不需要把单词换成数字。
| Outlook | Wind | Play |
|---|---|---|
| Sunny | Weak | No |
| Sunny | Strong | No |
| Overcast | Weak | Yes |
| Rain | Weak | Yes |
| Rain | Strong | No |
得到的决策树为:
Outlook
├── Sunny → No
├── Overcast → Yes
└── Rain
├── Weak → Yes
└── Strong → No
Outlook 划分后的信息增益最大,所以放在根结点。
第一行一个整数 m,表示特征数。
第二行一个整数 n,表示训练样本数。
接下来 n 行,每行 m+1 个整数,以空格分隔,依次是 m 个特征值和 1 个类别标签。
接下来一行一个整数 k,表示测试样本数。
接下来 k 行,每行 m 个整数,以空格分隔,表示一条测试样本的特征值。
输出 k 行,每行一个整数,为对应测试样本的预测类别。
输入
2
5
0 0 0
0 1 0
1 0 1
1 1 0
2 0 1
4
0 1
1 0
1 1
2 0
输出
0
1
0
1
说明
五条训练样本的标签为 0,0,1,0,1。
按特征 0 划分:取值 0 的标签是 {0,0},取值 1 的标签是 {1,0},取值 2 的标签是 {1}。加权熵为 52。
按特征 1 划分:取值 0 的标签是 {0,1,1},取值 1 的标签是 {0,0}。前者熵约为 0.918,加权熵约为 0.551。
父集熵相同,特征 0 的信息增益更大,根结点选用特征 0。
输入
2
5
0 0 1
1 1 0
1 1 0
1 2 0
1 2 0
2
0 9
1 1
输出
1
0
说明
特征 0 与特征 1 都能把样本划成纯子集,条件熵都是 0,信息增益相同。应选择下标较小的特征 0。
特征 0 为 0 的子集标签是 1,为 1 的子集标签全是 0。样本 (0,9) 预测 1,样本 (1,1) 预测 0。
若改选特征 1,样本 (0,9) 的取值 9 在训练集中没有出现,只能输出根结点的多数类 0,与正确类别 1 不同。
1≤m≤50
1≤n≤2000
k≥1
特征值和类别标签均为整数。
© CodeFun2000 · 使用条款
Scan the QR code below with WeChat to sign in
First-time scan will create your account automatically
请使用微信扫描下方二维码完成注册