基于模型的分区"two-layer interaction"(分段模型)
Model-based partitioning with "two-layer interaction" (segmented models)
我正在尝试构建一个类型为 "two-layer interaction" 的基于模型的树,其中树节点中的模型再次被分割。
我正在使用 mob()
函数来达到这个目的,但我无法使 fit
函数的参数与 lmtree()
函数一起使用。
在下面的示例中,a
是 b
的函数,a
和 b
之间的关系取决于 d
和 b | d
.
library("partykit")
set.seed(321)
b <- runif(200)
d <- sample(1:2, 200, replace = TRUE)
a <- jitter(ifelse(d == 1, 2 * b - 1, 4 * b - 1.2), amount = .1)
a[b < .5 & d == 1] <- jitter(rep(0, length(a[b < .5 & d == 1])))
a[b < .3 & d == 2] <- jitter(rep(0, length(a[b < .3 & d == 2])))
fit <- function(y, x, start = NULL, weights = NULL, offset = NULL, ..., estfun = FALSE, object = FALSE)
{
x <- x[, 2]
l <- lmtree(y ~ x | b)
return(l)
}
m <- mob(a ~ b | d, fit = fit) # not working
当然,通过这个简单的示例,我可以使用 lmtree(a ~ b | d + b)
来查找每个交互,但是有没有一种方法可以用作 mob()
和 lmtree()
的 fit
函数?
不是,但是是 ;-)
否,lmtree()
不能轻易用作 mob()
.
的装配工
内层树的维度(lmtree()
)是不固定的,也就是说,你可能会得到一棵没有任何分区或有很多子组的树,这对外层树来说会造成混淆树 (mob()
).
即使解决维度问题或通过总是强制中断来解决它,也需要更多工作来设置正确的系数向量、估计函数矩阵等。这也是并不简单,因为如果给定断点(例如,对于二进制因子)或必须估计(例如对于您的数字变量 b
)。
,收敛速度(以及推理)是不同的
你设置你的fit()
函数的方式,里面的lmtree()
不知道去哪里找b
。它只有一个数字向量 y
和一个数字矩阵 x
但不是原始数据。
但是是的,我认为如果将视图从拟合 "two-layer" 树更改为拟合 "segmented" 模型,所有这些问题都可以得到解决一棵树里面。我的印象是您想拟合一个模型 y ~ x
(或您的示例中的 a ~ b
),其中分段线性函数与 x
中的附加断点一起使用。如果假设分段线性函数在 x
中是连续的,那么可以很容易地使用 segmented
包。如果不是,则可以利用 strucchange
。假设你想要前者(因为你已经像这样模拟了你的数据),我在下面包含了一个有效的 segmented
示例(并且还稍微修改了你的问题以反映这一点)。
稍微更改名称和代码,您的数据 d
具有 y ~ x
的分段线性关系,其系数取决于组变量 g
。
set.seed(321)
d <- data.frame(
x = runif(200),
g = factor(sample(1:2, 200, replace = TRUE))
)
d$y <- jitter(ifelse(d$g == "1",
pmax(0, 2 * d$x - 1),
pmax(0, 4 * d$x - 1.2)
), amount = 0.1)
然后我可以在树的每个节点中拟合一个模型 segmented(lm(y ~ x))
,它带有适合 coef()
、logLik()
、estfun()
等的提取器。因此,流氓功能很简单:
segfit <- function(y, x, start = NULL, weights = NULL, offset = NULL, ...)
{
x <- as.numeric(x[, 2])
segmented::segmented(lm(y ~ x))
}
(注意:我还没有尝试过 segmented()
是否也支持 lm()
带有 weights
和 offset
的对象。)
有了这个我们就可以得到完整的树,在这个基本例子中简单地分裂成g
:
library("partykit")
segtree <- mob(y ~ x | g, data = d, fit = segfit)
plot(segtree, terminal_panel = node_bivplot, tnex = 2)
hands-on 对 segmented
的介绍可在:Muggeo VMR (2008) 中找到。 “segmented:用于拟合具有 Broken-Line 关系的回归模型的 R 包。” R 新闻, 8(1), 20-25。 https://CRAN.R-project.org/doc/Rnews/
有关基本方法论背景,请参阅:Muggeo VMR (2003)。 "Estimating Regression Models with Unknown Break-Points." 医学统计学, 22(19), 3055-3071。 doi:10.1002/sim.1545
我正在尝试构建一个类型为 "two-layer interaction" 的基于模型的树,其中树节点中的模型再次被分割。
我正在使用 mob()
函数来达到这个目的,但我无法使 fit
函数的参数与 lmtree()
函数一起使用。
在下面的示例中,a
是 b
的函数,a
和 b
之间的关系取决于 d
和 b | d
.
library("partykit")
set.seed(321)
b <- runif(200)
d <- sample(1:2, 200, replace = TRUE)
a <- jitter(ifelse(d == 1, 2 * b - 1, 4 * b - 1.2), amount = .1)
a[b < .5 & d == 1] <- jitter(rep(0, length(a[b < .5 & d == 1])))
a[b < .3 & d == 2] <- jitter(rep(0, length(a[b < .3 & d == 2])))
fit <- function(y, x, start = NULL, weights = NULL, offset = NULL, ..., estfun = FALSE, object = FALSE)
{
x <- x[, 2]
l <- lmtree(y ~ x | b)
return(l)
}
m <- mob(a ~ b | d, fit = fit) # not working
当然,通过这个简单的示例,我可以使用 lmtree(a ~ b | d + b)
来查找每个交互,但是有没有一种方法可以用作 mob()
和 lmtree()
的 fit
函数?
不是,但是是 ;-)
否,lmtree()
不能轻易用作 mob()
.
内层树的维度(
lmtree()
)是不固定的,也就是说,你可能会得到一棵没有任何分区或有很多子组的树,这对外层树来说会造成混淆树 (mob()
).即使解决维度问题或通过总是强制中断来解决它,也需要更多工作来设置正确的系数向量、估计函数矩阵等。这也是并不简单,因为如果给定断点(例如,对于二进制因子)或必须估计(例如对于您的数字变量
,收敛速度(以及推理)是不同的b
)。你设置你的
fit()
函数的方式,里面的lmtree()
不知道去哪里找b
。它只有一个数字向量y
和一个数字矩阵x
但不是原始数据。
但是是的,我认为如果将视图从拟合 "two-layer" 树更改为拟合 "segmented" 模型,所有这些问题都可以得到解决一棵树里面。我的印象是您想拟合一个模型 y ~ x
(或您的示例中的 a ~ b
),其中分段线性函数与 x
中的附加断点一起使用。如果假设分段线性函数在 x
中是连续的,那么可以很容易地使用 segmented
包。如果不是,则可以利用 strucchange
。假设你想要前者(因为你已经像这样模拟了你的数据),我在下面包含了一个有效的 segmented
示例(并且还稍微修改了你的问题以反映这一点)。
稍微更改名称和代码,您的数据 d
具有 y ~ x
的分段线性关系,其系数取决于组变量 g
。
set.seed(321)
d <- data.frame(
x = runif(200),
g = factor(sample(1:2, 200, replace = TRUE))
)
d$y <- jitter(ifelse(d$g == "1",
pmax(0, 2 * d$x - 1),
pmax(0, 4 * d$x - 1.2)
), amount = 0.1)
然后我可以在树的每个节点中拟合一个模型 segmented(lm(y ~ x))
,它带有适合 coef()
、logLik()
、estfun()
等的提取器。因此,流氓功能很简单:
segfit <- function(y, x, start = NULL, weights = NULL, offset = NULL, ...)
{
x <- as.numeric(x[, 2])
segmented::segmented(lm(y ~ x))
}
(注意:我还没有尝试过 segmented()
是否也支持 lm()
带有 weights
和 offset
的对象。)
有了这个我们就可以得到完整的树,在这个基本例子中简单地分裂成g
:
library("partykit")
segtree <- mob(y ~ x | g, data = d, fit = segfit)
plot(segtree, terminal_panel = node_bivplot, tnex = 2)
hands-on 对 segmented
的介绍可在:Muggeo VMR (2008) 中找到。 “segmented:用于拟合具有 Broken-Line 关系的回归模型的 R 包。” R 新闻, 8(1), 20-25。 https://CRAN.R-project.org/doc/Rnews/
有关基本方法论背景,请参阅:Muggeo VMR (2003)。 "Estimating Regression Models with Unknown Break-Points." 医学统计学, 22(19), 3055-3071。 doi:10.1002/sim.1545