Post-Pruning in partykit: the size of mob() tree

I am trying to build a multiple regression model while partitioning my data into subgroups based on additional set of covariates. While I implemented lmtree() or mob() in the "partykit" package, I tried to understand post-pruning strategies using AIC and BIC criterion, but I need some helps!

In the lmtree(), we can see the functions below:

"aic" = {
function(objfun, df, nobs) (nobs[1L] * log(objfun[1L]) + 2 * df[1L]) < (nobs[1L] * log(objfun[2L]) + 2 * df[2L])
}, "bic" = {
function(objfun, df, nobs) (nobs[1L] * log(objfun[1L]) + log(nobs[2L]) * df[1L]) < (nobs[1L] * log(objfun[2L]) + log(nobs[2L]) * df[2L])
}, "none" = {
NULL

To understand how these functions cut some child nodes, I first grow a very large tree with control = mob_control(verbose=TRUE, ordinal = "L2", alpha=0.5) and save the results of AIC, nobs, logLik, and df values of each of the nodes (I saved these values to calculate the above AIC function manually): Then, I fit another lmtree() function with mob_control(verbose=TRUE, ordinal = "L2", alpha=0.5, prune="AIC") to see which child nodes were cut. This results in a smaller tree without the nodes 4,5,8,9,10,11,14,15,19,20,24,25,26,27 from the first large tree.

I tried to calculate the AIC criterion value with the above table, e.g., starting from nodes 19 and 20, comparing node 18. However, as I kept pruning the tree from the bottom, it seems that the calculation in lmtree() are not always correct... Can you clearly explain what are the objfun, nobs, and df in the AIC and BIC functions? For example, after I cut the nodes 10 and 11, how I can decide to keep the nodes 8 and 9 comparing with node 7?

Disclaimer: I can't use your example because it is not reproducible and it isn't clear to me how exactly you have set up the table with the log-likelihoods. It seems that the log-likelihoods are all evaluated at the full parameter values (of the large tree) and not the restricted parameter values in the inner nodes. But, again, I cannot verify this with the information provided.

For a reproducible example consider the following simple example on the cars data:

library("partykit")
m <- lmtree(dist ~ 1 | speed, data = cars, alpha = 0.5, prune = "AIC")
plot(m)

And we extract the models in all nodes of the tree:

ms <- refit.modelparty(m)

Now let's check why the split of node 2 into nodes 3 and 4 is kept. The AIC of the model in node 2 is:

AIC(ms[["2"]])
##  265.2902
-2 * as.numeric(logLik(ms[["2"]])) + 2 * 2
##  265.2902

The AIC of the combined nodes 3 and 4 is:

-2 * as.numeric(logLik(ms[["3"]]) + logLik(ms[["4"]])) + 2 * (2 + 1 + 1)
##  247.7727

Thus, the split improves the model and is not pruned. Note that the parameters of the 3/4 models use two separate means, a single error variance, and one additional estimated breakpoint. One could compute this differently, e.g., with two variance or a different penalty for the additional breaks etc. The partykit package offers a couple of variants for this.

• Thank you so much for your very clear answer! I also saw the equation that you showed here in cran.r-project.org/web/packages/partykit/vignettes/mob.pdf, p. 12, but I was wondering the term "nobs[1L]" or "nobs[2L]" in the lmtree() in the partykit package. Nov 14 '17 at 15:32
• For each split these quantities are computed as follows: objfun, nobs and df are simply the objective function, sample size, and number of estimated parameters in the mother node. objfun is the sum of the objective functions across daughter nodes. Similarly, df is the sum of number of estimated parameters (optionally plus a penalty for the split itself). And nobs is the sum of sample sizes (which, of course, is just the sample size of the mother node). Nov 16 '17 at 11:44