基于模型的两层交互分段树构建:mob()与lmtree()适配问题
我来帮你搞定这个带“两层交互”的模型树问题!你遇到的参数兼容问题,核心是mob()和lmtree()的定位差异——lmtree()是专门为线性模型打造的模型树工具,而mob()是通用框架,需要自定义拟合函数适配它的接口。下面我用可复现的例子一步步给你解决:
先补全可复现的数据集
首先我把你没写完的数据集补全,模拟a和b的关系依赖d以及b的分段情况:
library("partykit") set.seed(321) b <- runif(200) d <- sample(1:2, 200, replace = TRUE) # 构造a:d=1时a和b正相关;d=2时,b<0.5则负相关,b>=0.5则正相关 a <- ifelse(d == 1, 2*b + rnorm(200, sd=0.1), ifelse(b < 0.5, -3*b + rnorm(200, sd=0.1), 3*(b - 0.5) + rnorm(200, sd=0.1))) dat <- data.frame(a, b, d)
方案1:用lmtree()直接实现两层交互(推荐)
因为你是线性模型场景,lmtree()是mob()的线性模型专用封装,完全能满足你的“两层交互”需求,而且不需要自定义函数。
比如你想先按d分裂树,再在每个节点内对b进行分段拟合,直接用公式语法就能实现:
# 公式含义:以d作为树的分裂变量,每个节点内拟合a~b的线性模型 tree1 <- lmtree(a ~ b | d, data = dat) plot(tree1) summary(tree1)
如果想让树自动选择分裂变量(比如先分裂b再分裂d,或者反过来),只需要调整公式里的分裂变量部分:
# 让树自动在b和d中选择分裂变量,实现多层交互 tree2 <- lmtree(a ~ b + d | b + d, data = dat) plot(tree2) summary(tree2)
方案2:自定义拟合函数适配mob()
如果你必须用mob()(比如要适配非线性模型),需要给它一个符合要求的拟合函数——这个函数要返回包含对数似然、系数、协方差矩阵的模型对象,还要支持logLik()、coef()、vcov()这些方法。
针对线性模型,我写一个适配的函数:
# 自定义线性模型拟合函数,给mob用 lm_mob <- function(formula, data, ...) { mod <- lm(formula, data = data, ...) # mob需要模型有明确的loglik属性,所以手动加上 attr(mod, "loglik") <- as.numeric(logLik(mod)) return(mod) } # 用mob构建模型树,指定拟合函数为我们写的lm_mob tree3 <- mob(a ~ b | d, data = dat, fit = lm_mob) plot(tree3) summary(tree3)
关键提醒
- 线性模型场景优先用
lmtree(),它已经帮你封装好了所有适配mob()的细节,不用自己写函数。 - 如果用
mob(),自定义拟合函数必须满足:能接收formula和data参数,返回的模型对象能被logLik()、coef()、vcov()提取信息——这是mob()计算分裂准则的核心依据。
内容的提问来源于stack exchange,提问作者MassCorr
相关产品推荐
相关产品推荐

