为什么R在融合失败时自动进入浏览器模式?

为什么R在融合失败时自动进入浏览器模式?,r,rstudio,plyr,lme4,purrr,R,Rstudio,Plyr,Lme4,Purrr,我在R中进行基于模拟的功率分析。我通过RStudio(0.98.932)运行R,使用函数plyr::rdply和lme4::glmer分别生成数据和拟合模型(参见下面的R环境和软件包版本的可再现示例的末尾) 该过程是随机生成给定参数化的数据集,并将模型拟合到该数据集。然而,该模型时不时地无法收敛。当出现以下警告时 [1] “无法计算缩放梯度” [2] “模型未能收敛:具有1个负特征值的退化Hessian” R进入浏览器模式,我必须手动干预(例如按c)才能返回模拟循环。这是一个真正的痛苦,因为我需

我在R中进行基于模拟的功率分析。我通过RStudio(0.98.932)运行R,使用函数
plyr::rdply
lme4::glmer
分别生成数据和拟合模型(参见下面的R环境和软件包版本的可再现示例的末尾)

该过程是随机生成给定参数化的数据集,并将模型拟合到该数据集。然而,该模型时不时地无法收敛。当出现以下警告时

[1] “无法计算缩放梯度”
[2] “模型未能收敛:具有1个负特征值的退化Hessian”

R进入浏览器模式,我必须手动干预(例如按
c
)才能返回模拟循环。这是一个真正的痛苦,因为我需要在几天内运行数千次迭代,但每次遇到这个特定的收敛错误,它都会停止,直到我按下一个键

有没有办法避免R进入浏览器模式?我存储了每次模拟中出现的所有警告,因此我唯一的问题是,当发生这种特定的收敛失败时,我必须手动干预。我已经尝试过悄悄地使用
purr::和
purr::safety
函数,但没有成功(请参见下面代码中的示例)

这是一个在我的电脑上工作的MWE(我使用
set.seed
进行再现,所以我希望它能独立于软件包版本等产生相同的结果)。在本例中,我应用了与实际模拟相同的逻辑,但不同且更简单的参数化:

library(lme4)
library(plyr)
library(purrr)

# function to generate data that will lead to convergence failure
mini_simulator <- function() {
  nb_items <- 10  # observations per subject
  nb_subj <- 10  # subjects per group
  generate_data <- function() {
    A <- rbinom(nb_items * nb_subj, 1, .99)
    B <- rbinom(nb_items * nb_subj, 1, .8)
    simdata <- data.frame(
      Group = rep(c("A", "B"), each = nb_items * nb_subj),
      Subj = rep(1 : (nb_subj * 2), each = nb_items),
      Items = 1:nb_items,
      Response = c(A, B)
      )
  }
}

# Sanity check that the function is generating data appropriately.
# d should be a dataframe with 200 obs. of 4 variables
d <- mini_simulator()()
head(d, 3)
# Group Subj Items Response
# 1     A    1     1        1
# 2     A    1     2        1
# 3     A    1     3        1
rm(d)

## Functions to fit model

# basic function to fit model on simulated data
fit_model <- function(data_sim) {
  fm <- glmer(
    formula = Response ~ Group + (1|Subj) + (1|Items),
    data = data_sim, family = "binomial")
  out <- data.frame(summary(fm)$coef)
  out
}

# similar but using purrr::quietly (also tried purrr::safely with no success)
# see http://r4ds.had.co.nz/lists.html section "Dealing with failure"
fit_model_quietly <- function(data_sim) {
  purrr_out <- purrr::quietly(glmer)(
    formula = Response ~ Group + (1|Subj) + (1|Items),
    data = data_sim, family = "binomial")
  fm <- purrr_out$result
  out <- data.frame(summary(fm)$coef)
  # keeps track of convergence failures and other warnings
  out$Warnings <- paste(unlist(purrr_out$warnings), collapse = "; ")
  out
}

# this seed creates the problematic convergence failure on the first evaluation
# of rdply
set.seed(2)
# When I run the next line R goes into Browse mode and I need to enter "c"
# in order to continue
simulations <- plyr::rdply(.n = 3, fit_model(mini_simulator()()))
simulations

# problem persists using the quietly adverb from purrr
set.seed(2)
simulations <- plyr::rdply(.n = 3, fit_model_quietly(mini_simulator()()))
simulations

# sessionInfo()

# R version 3.1.2 (2014-10-31)
# Platform: i386-w64-mingw32/i386 (32-bit)
# 
# locale:
#   [1] LC_COLLATE=Swedish_Sweden.1252  LC_CTYPE=Swedish_Sweden.1252    LC_MONETARY=Swedish_Sweden.1252
# [4] LC_NUMERIC=C                    LC_TIME=Swedish_Sweden.1252    
# 
# attached base packages:
#   [1] stats     graphics  grDevices utils     datasets  methods   base     
# 
# other attached packages:
#   [1] purrr_0.2.1  plyr_1.8.1   lme4_1.1-8   Matrix_1.1-4
# 
# loaded via a namespace (and not attached):
#   [1] grid_3.1.2      lattice_0.20-29 magrittr_1.5    MASS_7.3-35     minqa_1.2.4     nlme_3.1-118    nloptr_1.0.4   
# [8] Rcpp_0.11.3     splines_3.1.2   tools_3.1.2    
library(lme4)
library(plyr)
library(purrr)

options(error=NULL)

## Function to generate data
# Generates data that will lead to convergence failure
mini_simulator <- function() {
  nb_items <- 10  # observations per subject
  nb_subj <- 10  # subjects per group
  generate_data <- function() {
    A <- rbinom(nb_items * nb_subj, 1, .99)
    B <- rbinom(nb_items * nb_subj, 1, .8)
    simdata <- data.frame(
      Group = rep(c("A", "B"), each = nb_items * nb_subj),
      Subj = rep(1 : (nb_subj * 2), each = nb_items),
      Items = 1:nb_items,
      Response = c(A, B)
    )
  }
}

## Function to fit model
# Fits model on simulated data with purrr::quietly to capture warnings
# (http://r4ds.had.co.nz/lists.html section "Dealing with failure")
fit_model_quietly <- function(data_sim) {
  purrr_out <- purrr::quietly(glmer)(
    formula = Response ~ Group + (1|Subj) + (1|Items),
    data = data_sim, family = "binomial")
  fm <- purrr_out$result
  out <- data.frame(summary(fm)$coef)
  # keeps track of convergence failures and other warnings
  out$Warnings <- paste(unlist(purrr_out$warnings), collapse = "; ")
  out
}

# this seed creates the problematic convergence failure on the first evaluation
# of rdply
set.seed(2)
simulations <- plyr::rdply(.n = 3, fit_model_quietly(mini_simulator()()))
simulations
浏览器 这听起来像是
选项
的组合,触发警告和错误以立即进入
浏览器
调试器

func <- function(type = "none") {
  if (type == "warning") {
    warning("impending doom")
  } else if (type == "error") {
    stop("doom")    
  }
  type
}

func()
# [1] "none"
func("warning")
# Warning in func("warning") : impending doom
# [1] "warning"
func("error")
# Error in func("error") (from #5) : doom
这会将警告转换为错误:

options(warn=2)
func("warning")
# Error in func("warning") (from #3) : (converted from warning) impending doom
现在使用
error
选项,我们可以处理该错误:

options(warn=1, error=browser)
func("warning")
# Warning in func("warning") : impending doom
# [1] "warning"
func("error")
# Error in func("error") (from #5) : doom
# Browse[1]> 
c
因此,将警告转换为错误并捕获错误:

options(warn=2, error=browser)
func("warning")
# Error in func("warning") (from #3) : (converted from warning) impending doom
# Browse[1]> 
c
我相信这就是发生在你身上的事

Purrr
至于为什么
purrr::悄无声息地
似乎在做一些事情,我可以确认它正在绕过或忽略从警告到错误的预期升级:

quietfunc <- quietly(func)
str(quietfunc("warning"))
# List of 4
#  $ result  : chr "warning"
#  $ output  : chr ""
#  $ warnings: chr "impending doom"
#  $ messages: chr(0) 
options(warn=2, error=browser)
str(quietfunc("warning"))     # no browser!
# List of 4
#  $ result  : chr "warning"
#  $ output  : chr ""
#  $ warnings: chr "impending doom"
#  $ messages: chr(0) 
str(quietfunc("error"))       # yes browser
# Error in .f(...) (from #5) : doom
# Browse[1]> 
c

也许吧?

我有偏见,但我认为你应该看看SimDesign软件包。它是解决这类问题的一组非常有用的工具(并且隐式地处理非收敛问题)。它在CRAN上。这与
选项(“错误”)
有关吗?在我的机器上,您的代码只给出了一个错误(
error:“data”未找到,并且公式环境中缺少一些变量
),因此,如果您以前做过
options(error=browser)
,那么这可以解释这种行为。@Twitch\u City感谢您的建议。我一定去看看。不过,我还是想知道是什么导致了这种行为,以及如何避免这种行为。@r2evans-Hmm,我没有将任何内容更改为
options(“error”)
。在我看来,您的错误更像是由于没有使用函数
mini\u simulator
生成数据。您是否安装了示例开头列出的所有必要软件包?事实上,我希望知道我的例子是否可以复制。感谢帮助正如我所说,您的代码给了我一个错误,而不是调试器,因此它可能是可复制的:如果我设置
options(error=browser)
,那么我会得到类似的行为。如果你的选择被设定了,那就可以解释了。阅读
?选项
,了解更多信息。
options(“error”)
告诉您什么?谢谢,您的回答非常有用。首先,它解决了我的问题。其次,深入了解
选项
的工作原理以及在R中如何处理错误和警告是非常有益的。
quietfunc <- quietly(func)
str(quietfunc("warning"))
# List of 4
#  $ result  : chr "warning"
#  $ output  : chr ""
#  $ warnings: chr "impending doom"
#  $ messages: chr(0) 
options(warn=2, error=browser)
str(quietfunc("warning"))     # no browser!
# List of 4
#  $ result  : chr "warning"
#  $ output  : chr ""
#  $ warnings: chr "impending doom"
#  $ messages: chr(0) 
str(quietfunc("error"))       # yes browser
# Error in .f(...) (from #5) : doom
# Browse[1]> 
c
options(warn=1)
str(safefunc("warning"))      # warning is not "captured" by purrr::safely
# Warning in .f(...) : impending doom
# List of 2
#  $ result: chr "warning"
#  $ error : NULL