使用 partykit::mob() 和 mlogit 时出现错误:未指定合适的拟合函数

我在尝试使用 mlogit::mlogit() 来拟合条件逻辑回归模型,应用于 MOB 算法 partykit::mob() 生成的树的末端叶子节点。显然,无法直接使用 partykit::mob() 函数来实现(以下是我的尝试)。然而,我找到了 LORET 算法,但我找不到任何带有示例的文档,因此我试图从源代码中猜测需要哪个函数,但不幸的是,我无法让它工作。

你知道(1)在哪里可以找到 LORET 库的示例,以及(2)是否有可能将 partykit:mob() 函数与 mlogit::mlogit 一起使用吗?提前感谢。


示例数据

为了说明,请考虑以下数据。数据来自 5 个个体(id_ind),他们在 3 个选择中进行选择(altern)。每个个体选择了三次,因此我们有 15 个选择情况(id_choice)。每个选择由两个通用属性(x1x2)表示,选择记录在 y 中(如果选择为 1,否则为 0)。最后,z1 是一个候选分区变量。

df <- read.table(header = TRUE, text = "id_ind id_choice altern           x1          x2 y1       1         1      1  1.586788801  0.11887832 12       1         1      2 -0.937965347  1.15742493 03       1         1      3 -0.511504401 -1.90667519 04       1         2      1  1.079365680 -0.37267925 05       1         2      2 -0.009203032  1.65150370 16       1         2      3  0.870474033 -0.82558651 07       1         3      1 -0.638604013 -0.09459502 08       1         3      2 -0.071679538  1.56879334 09       1         3      3  0.398263302  1.45735788 110      2         4      1  0.291413453 -0.09107974 011      2         4      2  1.632831160  0.92925495 012      2         4      3 -1.193272276  0.77092623 113      2         5      1  1.967624379 -0.16373709 114      2         5      2 -0.479859282 -0.67042130 015      2         5      3  1.109780885  0.60348187 016      2         6      1 -0.025834772 -0.44004183 017      2         6      2 -1.255129594  1.10928280 018      2         6      3  1.309493274  1.84247199 119      3         7      1  1.593558740 -0.08952151 020      3         7      2  1.778701074  1.44483791 121      3         7      3  0.643191170 -0.24761157 022      3         8      1  1.738820924 -0.96793288 023      3         8      2 -1.151429915 -0.08581901 024      3         8      3  0.606695064  1.06524268 125      3         9      1  0.673866953 -0.26136206 026      3         9      2  1.176959443  0.85005871 127      3         9      3 -1.568225496 -0.40002252 028      4        10      1  0.516456176 -1.02081089 129      4        10      2 -1.752854918 -1.71728381 030      4        10      3 -1.176101700 -1.60213536 031      4        11      1 -1.497779616 -1.66301234 032      4        11      2 -0.931117325  1.50128532 133      4        11      3 -0.455543630 -0.64370825 034      4        12      1  0.894843784 -0.69859139 035      4        12      2 -0.354902281  1.02834859 036      4        12      3  1.283785176 -1.18923098 137      5        13      1 -1.293772990 -0.73491317 038      5        13      2  0.748091387  0.07453705 139      5        13      3 -0.463585127  0.64802031 040      5        14      1 -1.946438667  1.35776140 041      5        14      2 -0.470448172 -0.61326604 142      5        14      3  1.478763383 -0.66490028 043      5        15      1  0.588240775  0.84448489 144      5        15      2  1.131731049 -1.51323232 045      5        15      3  0.212145247 -1.01804594 0")df$z1 <- rnorm(n= nrow(df),mean = 0,sd = 1)

mlogit + partykit::mob()

library(mlogit)library(partykit)mo <-  mlogit(formula =  y ~ x1 + x2 ,               data =  df,              idx  =  c("id_choice", "altern"))# Coefficients:#   (Intercept):2  (Intercept):3             x1             x2  #        0.036497       0.293254       0.821173       1.062794mlogit_function <-  function(y, x,                             offset = NULL,                             ...){ mlogit(y ~  x ,                                          data =  df)}formula <-  y ~ x1 + x2 | z1 mob(formula = formula,    data    = df,    fit     = mlogit_function,    control = mob_control(minsize = 10,                           alpha = 0.01))# Error in mob(formula = formula, data = df, fit = mlogit_function, control = mob_control(minsize = 10,  # no suitable fitting function specified

mlogit + loret::multinomtree()

这个函数可以运行树,但这不是我想要的,因为缺少了选项 2 的常数项。

loret::multinomtree(formula = formula,                    data = df)# Model-based recursive partitioning (NULL)# Model formula:#   y ~ x1 + x2 | z1# # Fitted party:#   [1] root: n = 45# 1:(Intercept)          1:x1          1:x2 # -1.1046317     0.7663315     1.0418296  # # Number of inner nodes:    0# Number of terminal nodes: 1# Number of parameters per node: 3# Objective function: 22.62393

mlogit + loret::clmtree()

loret::clmtree(formula = formula,               data = df)# Error in clm.fit.default(y = c(1L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 1L, 0L,  : #                                  is.list(y) is not TRUE

回答:

我没有完整的解决方案,但希望提供的反馈能让你开始:

  • 重要的是要区分所谓的“条件逻辑”模型与替代特定变量(您感兴趣的)和经典的“多项逻辑模型”与仅主体特定(或个体特定)变量。mlogit::mlogit() 可以拟合两者(以及混合版本),而 nnet::multinom() 仅支持后者。

  • 对于拟合条件逻辑模型,您可以将数据设置为长格式或宽格式。您以长格式指定了数据,并且还有一个替代特定的分割变量 z1。这意味着来自同一个个体的数据可能会出现在树的不同节点,这将相当尴尬。

  • 相反,最好将数据设置为宽格式,使每一行对应一个个体,然后您可以只考虑个体特定的变量进行分割。这也符合已拟合的 mlogit 对象的 $gradient 元素的视图,它提供了个体特定的梯度贡献。(这是 sandwich::estfun() 提取的信息,它反过来是 partykit::mob() 的基本信息。)

  • 基于替代特定变量进行合理的递归分区也可能是可行的,但我很难看出这会产生什么样的模型以及这些模型的意义。在任何情况下,您都必须编写自己的代码来从拟合模型对象中提取 estfun,它提供了完全分解的替代特定梯度贡献。

  • loret 包有些未完成,并且已经有一段时间没有更新了。因此,我不建议目前在“生产”中使用它。此外,nnet::multinom()(基础 loret::multinomtree())不适合您需要的模型(如上所述),而 ordinal::clm()(基础 loret::clmtree())是用于完全不同的模型的。

  • 我们希望在 loret 中构建的一个特定方面,但尚未完成的,是在逻辑模型中自动检测(准)完全分离,并在树中适当处理它。

  • 您的 mlogit + partykit::mob() 方法不起作用,因为拟合函数没有正确的接口(您被正确告知)。请参阅 vignette("mob", package = "partykit") 以了解支持的两种接口。

  • 为了编写适当的接口,您需要确保在每个子集中都有您需要的所有变量。请注意,响应变量加上回归矩阵是不够的,您还需要索引变量!我建议通过 partykit::mob() 指定的公式的 y 变量或 x 变量来包含这些变量。然后在 mob_control() 中,您可以设置 ytype = "data.frame"xtype = "data.frame"。然后,yx 都作为 data.frame 对象提供,并且可以在调用 mlogit::mlogit() 之前再次组合。在下面的示例中,我已经对 formulaidx 参数进行了硬编码。

基于您的示例的说明:您可以设置一个模型拟合函数 my_fit(),它期望 yx 是数据框,然后使用 formula = y ~ x1 + x2idx = c("id_choice", "altern") 来拟合 mlogit() 模型。

my_fit <- function(y, x = NULL, start = NULL, weights = NULL, offset = NULL, ...) {  mlogit::mlogit(formula = y ~ x1 + x2, data = cbind(y, x), idx = c("id_choice", "altern"))}

为了指定树,您需要通过 mob() 公式的 x 变量传递 mlogit() 模型所需的所有变量:

tr <- mob(y ~ x1 + x2 + id_choice + altern | z1, data = df, fit = my_fit,  control = mob_control(ytype = "data.frame", xtype = "data.frame"))

表面上看,这是可行的。至少它在根节点中拟合了所需的模型,您可以通过检查 coef(tree) 来查看。然而,它之所以工作,唯一的原因是它甚至没有尝试进行任何分区,因为与参数数量相比,样本大小被认为太小了。

但是,当您在 mob_control() 中额外设置 minsize = 10 时,分区过程将失败。其原因是分割变量的长度为 45,但 mlogit() 的梯度/estfun 的长度只有 15。这是长替代特定格式与短个体特定格式的区别。

因此,为了使事情正常工作,您必须使用宽格式的数据,然后相应地调整 mob() 公式和 my_fit() 中的 mlogit() 调用。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注