(接上篇)
一、剪枝过程
上篇分析完了tree节点的构建过程,在REPTree.buildClassifier之后如果设置了剪枝选项,则还有一个剪枝和backfit过程。
if (!m_NoPruning) {
m_Tree.insertHoldOutSet(prune);
m_Tree.reducedErrorPrune();
m_Tree.backfitHoldOutSet();
}
重点卡一下reducedErrorPrune和backfitHoldOutSet过程。
二、Tree.reducedErrorPrune
protected double reducedErrorPrune() throws Exception {
<span style="white-space:pre"> </span>//这个函数会返回该树及其子树的一个错误情况,如果是枚举类型返回的是分错的instance数量,数值类型返回的是与正确值的偏差的平方和
// 如果是叶子节点就不做任何操作
if (m_Attribute == -1) {
return m_HoldOutError;//简单的说一下这个error怎么计算来的,使用<span style="font-size:18px;">insertHoldOutSet传入数据时会根据原先训练时的分布,来预测出传入数据的class,然后根据这个结果和真正的class值进行比对,就知道是否分的正确了</span>
}
//计算一下所有的子树的偏差
double errorTree = 0;
for (int i = 0; i < m_Successors.length; i++) {
errorTree += m_Successors[i].reducedErrorPrune();
}
if (errorTree >= m_HoldOutError) {
m_Attribute = -1;//如果子树偏差大于本身的偏差,那子树就没啥存在的意义了,直接去掉。
m_Successors = null;
return m_HoldOutError;
} else {
return errorTree;
}
}
可以看出,这个剪枝过程和J48相比还是简单不