如何拟合响应变量介于 0 和 1 之间的混合模型?

机器算法验证 r 物流 混合模式 咕噜咕噜 lme4-nlme
2022-01-23 06:52:42

我正在尝试使用lme4::glmer()非二元的因变量来拟合二项式广义混合模型(GLMM),而是在零和一之间的连续变量。可以将此变量视为概率;事实上,这人类受试者报告的概率(在我帮助分析的实验中)。即它不是一个“离散”分数,而是一个连续变量。

我的glmer()电话没有按预期工作(见下文)。为什么?我能做些什么?

稍后编辑:我下面的答案比这个问题的原始版本更笼统,所以我修改了这个问题也更笼统。


更多细节

显然,逻辑回归不仅可以用于二元 DV,还可以用于 0 到 1 之间的连续 DV。确实,当我跑步时

glm(reportedProbability ~ a + b + c, myData, family="binomial")

我收到一条警告信息

Warning message:
In eval(expr, envir, enclos) : non-integer #successes in a binomial glm!

但是一个非常合理的拟合(所有因素都是分类的,所以我可以很容易地检查模型预测是否接近跨学科均值,并且确实如此)。

但是,我真正想要使用的是

glmer(reportedProbability ~ a + b + c + (1 | subject), myData, family="binomial")

它给了我同样的警告,返回了一个模型,但是这个模型显然很不合适;glm()固定效应的估计与那些和跨主题均值相差甚远。(而且我需要包含glmerControl(optimizer="bobyqa")glmer调用中,否则它根本不会收敛。)

1个回答

从一个没有随机效应的简单案例开始是有意义的。

有四种方法可以处理表现为分数或概率的连续零对一响应变量(这是我们关于该主题的最规范/赞成/查看的线程,但不幸的是,此处并未讨论所有四个选项):

  1. 如果是分数p=m/n两个整数和所有ns 是已知的,那么可以使用标准逻辑回归,也就是二项式 GLM。在 R 中对其进行编码的一种方法是(假设它nN每个数据点的值):

    glm(p ~ a+b+c, myData, family="binomial", weights=n)
    
  2. 如果p不是两个整数的分数,那么可以使用 beta 回归。这只有在观察到的情况下才有效p永远不等于0或者1. 如果是这样,那么更复杂的零/一膨胀 beta 模型是可能的,但这变得更加复杂(参见这个线程)。

    betareg(p ~ a+b+c, myData)
    
  3. Logit 变换响应并使用线性回归。通常不建议这样做。

    lm(log(p/(1-p)) ~ a+b+c, myData)
    
  4. 拟合二项式模型,然后在考虑过度分散的情况下计算标准误差。标准误差可以通过多种方式计算:


    (a) 和 (b) 不相同(请参阅此评论,以及本书中的第 3.4.1 和 3.4.2 节,以及此 SO 帖子以及),但往往会给出相似的结果。选项 (a) 的实现glm方式如下:

    glm(p ~ a+b+c, myData, family="quasibinomial")
    

相同的四种方式可用于随机效果。

  1. 使用weights参数():

    glmer(p ~ a+b+c + (1|subject), myData, family="binomial", weights=n)
    

    根据上面的第二个链接,模拟过度分散可能是一个好主意,请参见那里(以及下面的#4)。

  2. 使用 beta 混合模型:

    glmmadmb(p ~ a+b+c + (1|subject), myData, family="beta")
    

    或者

    glmmTMB(p ~ a+b+c + (1|subject), myData, 
            family=list(family="beta",link="logit"))
    

    如果响应数据中有精确的零或一,则可以使用 中的零/一膨胀 beta 模型glmmTMB

  3. 使用响应的 logit 变换:

    lmer(log(p/(1-p)) ~ a+b+c + (1|subject), myData)
    
  4. 考虑二项式模型中的过度分散。这使用了不同的技巧:为每个数据点添加随机效果:

    myData$rowid = as.factor(1:nrow(myData))
    glmer(p ~ a+b+c + (1|subject) + (1|rowid), myData, family="binomial",
          glmerControl(optimizer="bobyqa"))
    

    由于某种原因,这不能正常工作,因为glmer()抱怨非整数p并产生无意义的估计。我想出的一个解决方案是使用假常量weights=k并确保它p*k始终是整数。这需要四舍五入p,但通过选择k足够大的值,它应该无关紧要。结果似乎不取决于 的值k

    k = 100
    glmer(round(p*k)/k ~ a+b+c + (1|subject) + (1|rowid), myData, 
          family="binomial", weights=rowid*0+k, glmerControl(optimizer="bobyqa"))
    

    稍后更新(2018 年 1 月):这可能是一种无效的方法。请参阅此处的讨论我必须对此进行更多调查。


在我的特定情况下,选项 #1 不可用。

选项#2 非常慢,并且存在收敛问题:glmmadmb运行需要五到十分钟(并且仍然抱怨它没有收敛!),而lmer在瞬间运行并且glmer需要几秒钟。 更新:glmmTMB按照@BenBolker 评论中的建议进行了尝试,它的运行速度几乎与 一样快glmer,没有任何收敛问题。所以这就是我将使用的。

选项 #3 和 #4 产生非常相似的估计值和非常相似的 Wald 置信区间(用 获得confint)。我不是#3的忠实粉丝,因为它有点作弊。#4 感觉有点老套。

非常感谢@Aaron,他在评论中将我指向#3 和#4。