You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用未观测保留数据均值更新Party/Partykit模型终端节点估计

基于evtree实现诚实决策树(Honesty)的节点更新方案

我需要在数据子集上用evtree构建决策树(evtree处理大数据集时运行速度极慢),之后用未观测的保留数据更新模型终端节点的估计值。这和GRF包中的「诚实(honesty)」概念类似,目的是抵消抽样带来的模型构建偏差,最终得到偏差更低、训练速度更快(训练输入更小)且方差更低的模型,同时要能使用更新后的模型对新数据做推理。


示例(基于mtcars数据集)

先用ctree演示核心逻辑:

library(partykit)
mtcars
set.seed(12)
train = sample(nrow(mtcars), nrow(mtcars)/1.5)
sample_tree = ctree(mpg ~. , data = mtcars[train, ])
sample_tree %>% as.simpleparty

运行后得到的初始树结构:

Fitted party:
[1] root
| [2] cyl <= 6: 23.755 (n = 11, err = 224.8)
| [3] cyl > 6: 15.380 (n = 10, err = 42.1)

用保留数据计算终端节点的新估计值:

data.frame(node = predict(sample_tree, newdata = mtcars[-train, ], type = 'node'),
           prediction = mtcars[-train, ]$mpg) %>%
group_by(node) %>%
summarize(mpg = mean(prediction)) %>% as.list

输出的新节点估计值:

$node
[1] 2 3
$mpg
[1] 24.31429 14.40000

需要将树的节点2、3的估计值分别更新为24.31429和14.40000。


已尝试的方法

  • 多次咨询ChatGPT
  • 大量搜索相关资料
  • 尝试直接获取并修改终端节点值

补充方法(改编自Achim Zeileis的回答,原理未完全明确,需谨慎使用)

# library(evtree)
set.seed(123)
train = sample(nrow(diamonds), nrow(diamonds)/20)
diamonds_evtree =  evtree("price ~ .", data = (diamonds %>% select(any_of(c("carat", "depth", "table", "price"))))[train, ],
                          maxdepth = 3L, niterations = 101)

diamonds_ctree = ctree(price ~ ., data = (diamonds %>% select(any_of(c("depth", "table", "price", "x", "y", "y"))))[train, ])

refit_constparty(as.constparty(diamonds_evtree), diamonds[-train,]) # 执行失败
refit_constparty(diamonds_ctree, diamonds[-train,]) # 执行成功

as.constparty(diamonds_evtree)


refit_simpleparty <- function(object, newdata) {
  stopifnot(inherits(object, "constparty") | inherits(object, "simpleparty"))
  if(any(abs(object$fitted[["(weights)"]] - 1) > 0)) {
    stop("weights not implemented yet")
  }
  d <- model.frame(terms(object), data = newdata)
  ret <- party(object$node,
               data = d,
               fitted = data.frame(
                 "(fitted)" = fitted_node(object$node, d),
                 "(response)" = d[[1L]],
                 "(weights)" = 1L,
                 check.names = FALSE),
               terms = terms(object))
  as.simpleparty(ret)
}

# 可用于任意数据
refit_simpleparty(diamonds_ctree %>% as.simpleparty, newdata = diamonds)

内容的提问来源于stack exchange,提问作者internet_geek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 20:22:46