Я пытаюсь построить дерево на основе моделей с типом «двухуровневого взаимодействия», где модели в узлах дерева снова сегментируются.
Я использую функцию 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) для поиска каждого взаимодействия, но есть ли способ использовать в качестве функции fitmob()lmtree()?





Нет, но да ;-)
Нет, lmtree() не может быть легко использован в качестве установщика для mob().
Размер внутреннего дерева (lmtree()) не фиксирован, то есть вы можете получить дерево без какого-либо раздела или со многими подгруппами, и это может сбить с толку внешнее дерево (mob()).
Даже если бы кто-то обошел проблему размерности или исправил ее, всегда заставляя один разрыв, потребовалось бы больше работы, чтобы настроить правильный вектор коэффициентов, матрицу оценочных функций и т. д. Это также непросто, потому что скорость сходимости (и, следовательно, вывод) отличается, если заданы точки останова (например, для двоичного фактора) или должны быть оценены (например, для ваших числовых переменных b).
Как вы настроили функцию fit(), внутренний lmtree() не знает, где найти b. Все, что у него есть, это числовой вектор y и числовая матрица x, но не исходные данные.
Но да, я думаю, что все эти проблемы можно решить, изменив представление с подгонки «двухслойного» дерева к подгонке «сегментированной» модели внутри дерева. У меня сложилось впечатление, что вы хотите соответствовать модели 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)
Практическое введение в segmented доступно в: Muggeo VMR (2008). «сегментированный: пакет R для соответствия моделям регрессии с ломаной связью». Новости R, 8 (1), 20-25. https://CRAN.R-project.org/doc/Rnews/
Для базовой методологической основы см .: Muggeo VMR (2003). «Оценка регрессионных моделей с неизвестными точками разрыва». Статистика в медицине, 22 (19), 3055-3071. DOI: 10.1002 / sim.1545
Спасибо @AchimZeileis. Собственно, поначалу я использовал именно такой подход (сегментированная функция для подгонки). Но я отказался от своих реальных данных, так как это занимает несколько дней ... В любом случае еще раз спасибо за помощь.
@MassCorr Сильно ли отличается проблема синхронизации для mob(y ~ x | ..., fit = segtree) от lmtree(y ~ x | ...)? Если последнее также занимает очень много времени, может потребоваться огрубление некоторых регрессоров или факторов, чтобы облегчить поиск точки разделения, увеличить минимальный размер сегмента, ограничить глубину дерева и т. д.
@AchimZeileis mob + segmented занимает гораздо больше времени, чем lmtree
Хорошо, я вижу. Насколько приблизительно? Возможно, можно поиграться со стартовыми значениями и т. д., Возможно, возможно некоторое ускорение. Спросить Вито тоже может быть полезно ...
@AchimZeileis Ну даже для самой простой модели с выборкой данных >> 100 x. Я думаю (но вы это знаете лучше меня), что мафии сложно сходиться с такой регрессией (особенно с зашумленными данными)
Кроме того, у самой сегментированной функции иногда возникают трудности с конвергенцией.
Вероятно, значительная часть этого времени уходит на обработку формул и / или проблемы сходимости. Это может помочь связать с seg.lm.fit(...), а не с segmented(lm(...)), а затем вручную установить лучшие начальные значения (например, используя информацию от материнского узла), ослабить критерии сходимости и т. д.
Это очень хорошая идея использовать информацию от материнского узла! Я могу попробовать это
В mob_control() для этого есть параметр restart. Затем функция fit получает параметры от материнского узла через аргумент start. Однако при его использовании необходимо соблюдать осторожность. Мой опыт показывает, что иногда это приводит к ускорению, а иногда нет ... или даже приводит к проблемам сходимости. Таким образом, функция fit должна обратить на это внимание.
Хорошо, расскажу, как это происходит
Спасибо :-) Я был удивлен, насколько легко это было собрать! Но
segmentedВито был достаточно дружелюбным, чтобы поставляться со всеми необходимыми нам строительными блоками. Теперь мне любопытно посмотреть, насколько хорошо это работает с реальными данными ...