如何使用路径遍历rpart对象的树结构以手动清除某些节点?

我在使用rpart构建分类树。我希望基于叶节点的某些标准开发自己的修剪函数。例如,如果某个叶节点在某些标准上表现不佳(在我这里是参数估计的稳定性),我想在树结构中向上查找该叶节点的父节点(即使这个节点不是终端节点)。为此,我想使用路径遍历树,我需要获取叶节点及其父节点,以便在必要时向上遍历树。

让我们看一个例子:

fit <- rpart(Kyphosis ~ Age + Number + Start, data = kyphosis)> fitn= 81 node), split, n, loss, yval, (yprob) * denotes terminal node1) root 81 17 absent (0.79012346 0.20987654) 2) Start>=8.5 62 6 absent (0.90322581 0.09677419) 4) Start>=14.5 29 0 absent (1.00000000 0.00000000) *5) Start< 14.5 33 6 absent (0.81818182 0.18181818) 10) Age< 55 12 0 absent (1.00000000 0.00000000) *11) Age>=55 21 6 absent (0.71428571 0.28571429) 22) Age>=111 14 2 absent (0.85714286 0.14285714) *23) Age< 111 7 3 present (0.42857143 0.57142857) *3) Start< 8.5 19 8 present (0.42105263 0.57894737) *

通过fit$frame,我可以获取关于叶节点的信息:

fit$frame var n wt dev yval complexity ncompete nsurrogate yval2.V1 yval2.V2 yval2.V3 yval2.V4 yval2.V51 Start 81 81 17 1 0.17647059 2 1 1.00000000 64.00000000 17.00000000 0.79012346 0.209876542 Start 62 62 6 1 0.01960784 2 2 1.00000000 56.00000000 6.00000000 0.90322581 0.096774194 <leaf> 29 29 0 1 0.01000000 0 0 1.00000000 29.00000000 0.00000000 1.00000000 0.000000005 Age 33 33 6 1 0.01960784 2 2 1.00000000 27.00000000 6.00000000 0.81818182 0.1818181810 <leaf> 12 12 0 1 0.01000000 0 0 1.00000000 12.00000000 0.00000000 1.00000000 0.0000000011 Age 21 21 6 1 0.01960784 2 0 1.00000000 15.00000000 6.00000000 0.71428571 0.2857142922 <leaf> 14 14 2 1 0.01000000 0 0 1.00000000 12.00000000 2.00000000 0.85714286 0.1428571423 <leaf> 7 7 3 2 0.01000000 0 0 2.00000000 3.00000000 4.00000000 0.42857143 0.571428573 <leaf> 19 19 8 2 0.01000000 0 0 2.00000000 8.00000000 11.00000000 0.42105263 0.57894737

我可以使用fit$where获取数据表中各行的对应叶节点:

现在我想获取叶节点的父节点。我知道path.rpart可以给我所有为了得到叶节点而进行的分裂。例如,对于叶节点23:

> path.rpart(fit, 23)node number: 23  root Start>=8.5 Start< 14.5 Age>=55 Age< 111

我想得到的是节点23的父节点的路径编号?我该如何进行这种关联?

提前感谢您。


回答:

您不需要关于树的任何信息,因为所有节点都有相同的模式。让我们拟合一个更有趣的树:

(fit <- rpart(Kyphosis ~ Age + Number + Start, data = kyphosis,             cp = .0001, minsplit = 5))# n= 81 # # node), split, n, loss, yval, (yprob)#       * denotes terminal node# #   1) root 81 17 absent (0.79012346 0.20987654)  #     2) Start>=8.5 62  6 absent (0.90322581 0.09677419)  #       4) Start>=14.5 29  0 absent (1.00000000 0.00000000) *#       5) Start< 14.5 33  6 absent (0.81818182 0.18181818)  #        10) Age< 55 12  0 absent (1.00000000 0.00000000) *#        11) Age>=55 21  6 absent (0.71428571 0.28571429)  #          22) Age>=98 16  2 absent (0.87500000 0.12500000) *#          23) Age< 98 5  1 present (0.20000000 0.80000000) *#     3) Start< 8.5 19  8 present (0.42105263 0.57894737)  #       6) Age< 11.5 2  0 absent (1.00000000 0.00000000) *#       7) Age>=11.5 17  6 present (0.35294118 0.64705882)  #        14) Start< 5.5 12  6 absent (0.50000000 0.50000000)  #          28) Age>=130.5 2  0 absent (1.00000000 0.00000000) *#          29) Age< 130.5 10  4 present (0.40000000 0.60000000)  #            58) Age< 93 6  2 absent (0.66666667 0.33333333)  #             116) Number< 4.5 3  0 absent (1.00000000 0.00000000) *#             117) Number>=4.5 3  1 present (0.33333333 0.66666667) *#            59) Age>=93 4  0 present (0.00000000 1.00000000) *#        15) Start>=5.5 5  0 present (0.00000000 1.00000000) *

如果可能,每个节点将被分成两个,并编号为node * 2 + 0:1,所以如果您有一个编号为5的节点,它的子节点将是5 * 2 + 0:1。还要注意,使用这种模式,偶数编号的节点不会有子节点。

因此,给定任何节点编号,我们可以回溯找到父节点:

parent(23)# [1]  1  2  5 11 23## 同一节点的子节点应该有相同的路径identical(head(parent(28), -1), head(parent(29), -1))# [1] TRUEparent <- function(x) {  if (x[1] != 1)    c(Recall(if (x %% 2 == 0L) x / 2 else (x - 1) / 2), x) else x}

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注