如何获得 nls 函数的 p 值和置信区间?

机器算法验证 置信区间 非线性回归 nls
2022-04-13 08:23:56

我有 2 个问题。

1) 我怎样才能为我的 2 个函数设置 p.value?我的假设是我的函数和数据之间存在相关性。

2)我怎样才能为我的 2 个函数设置置信区间?

library(ggplot2)
g <- function (x, a,b,c) a * (1-exp(-(x-c)/abs(b)))
X1 <- c(129.08,109.92,85.83,37.72)
Y1 <- c(0.7,0.5,0.39,-1.36)
dt1 <- data.frame(x1=X1,y1=Y1)
model1 <- nls(Y1 ~ g(X1, a, b, c), 
          start = list(a=0.5, b=60, c=50),control=nls.control(maxiter = 200))

ggplot(data = dt1,aes(x = x1, y = y1)) + 
     theme_bw() + geom_point() + 
     geom_smooth(data=dt1, method="nls", formula=y~g(x, a, b, c),
       se=F, start=list(a=0.5, b=60, c=50))


f <- function (x, a, b, c) a*(x^2)+b*x+c   
X2 <- c(589.62,457.92,370.16,295.98,243.99,199.07,159.91,142.63,
124.15, 101.98, 87.93, 83.16, 82.2, 74.48, 47.68, 37.51, 31,
27.9, 21.24,18.28)
Y2 <- c(0.22,0.37,0.49,0.65,0.81,0.83,1,0.81,0.65,0.44,0.55,0.63,
0.65,0.55,0.37,0.32,0.27,0.22,0.17,0.14)
dt2 <- data.frame(x2=X2,y2=Y2)
model2 <- nls(Y2 ~ f(X2, a, b, c), 
           start = list(a=-1, b=3, c=0),control=nls.control(maxiter = 200))
ggplot(data = dt2,aes(x = x2, y = y2)) + 
      theme_bw() + geom_point() + 
      geom_smooth(data=dt2, method="nls", formula=y~f(x, a, b, c),
       se=F, start=list(a=-1, b=3, c=0))

先感谢您

4个回答

1. - 你可以试试(这是一个近似值)

library(nls2)  
summary(as.lm(model))  
  • 您可以使用以下方法获得模型中使用的所有参数的 p 值

    摘要(型号)

  • 您可以通过将模型与另一个(“嵌套”)模型进行比较来获取模型的 p 值

    方差分析(模型 1,模型 2)

    其中模型 2 是模型 1 的简化版本(这是您的零假设)

  • 您可以使用自举等方法来衡量完整模型的拟合概率。

    2.

  • 您可以使用(这是一个近似值)获得完整的模型置信区间

    库(nls2)预测(as.lm(model2),间隔=“信心”)

  • 您可以使用获取参数的置信区间

    限制(模型)

  • 您可以使用以下方法获取有关这些参数间隔的更多信息

    简介(型号)

    情节(配置文件(模型))

  • 您可以使用以下方法获得两个参数(用于绘图和获取矩阵)的成对置信区间

    椭圆.nls(模型)

关于置信区间,这里的其他答案似乎在使用函数(as.lm.nls,as.proto.list)方面存在问题,出于某种原因,这些函数没有为某些用户(比如我)定义。经过一番冲浪,我找到了一个适合我的答案,只需要 MASS 包。在@etov 的敦促下,我发布了我在这里找到的答案。它最初来自https://www.r-bloggers.com/predictnls-part-1-monte-carlo-simulation-confidence-intervals-for-nls-models/并且似乎是由一个名叫 Andrej 的人使用的句柄 anspiess。Andrej 的这个函数,用他的话说,“获取一个 nls 对象,提取变量/参数值/参数方差-协方差矩阵,创建一个“增强的”协方差矩阵(包括来自参数和预测变量的方差/协方差值,后者通常为零),从多元正态分布进行模拟(使用'MASS'包的mvrnorm),对值评估函数(对象公式)并最终收集统计信息”。因此,它是一种基于 Monte-Carlo 的方法,用于获取 nls 模型的置信区间。他的代码:call

predictNLS <- function(
object, 
newdata,
level = 0.95, 
nsim = 10000,
...
)
{
  require(MASS, quietly = TRUE)

  ## get right-hand side of formula
  RHS <- as.list(object$call$formula)[[3]]
  EXPR <- as.expression(RHS)

  ## all variables in model
  VARS <- all.vars(EXPR)

  ## coefficients
  COEF <- coef(object)

  ## extract predictor variable    
  predNAME <- setdiff(VARS, names(COEF))  

  ## take fitted values, if 'newdata' is missing
  if (missing(newdata)) {
    newdata <- eval(object$data)[predNAME]
    colnames(newdata) <- predNAME
  }

  ## check that 'newdata' has same name as predVAR
  if (names(newdata)[1] != predNAME) stop("newdata should have name '", predNAME, "'!")

  ## get parameter coefficients
  COEF <- coef(object)

  ## get variance-covariance matrix
  VCOV <- vcov(object)

  ## augment variance-covariance matrix for 'mvrnorm' 
  ## by adding a column/row for 'error in x'
  NCOL <- ncol(VCOV)
  ADD1 <- c(rep(0, NCOL))
  ADD1 <- matrix(ADD1, ncol = 1)
  colnames(ADD1) <- predNAME
  VCOV <- cbind(VCOV, ADD1)
  ADD2 <- c(rep(0, NCOL + 1))
  ADD2 <- matrix(ADD2, nrow = 1)
  rownames(ADD2) <- predNAME
  VCOV <- rbind(VCOV, ADD2) 

  ## iterate over all entries in 'newdata' as in usual 'predict.' functions
  NR <- nrow(newdata)
  respVEC <- numeric(NR)
  seVEC <- numeric(NR)
  varPLACE <- ncol(VCOV)   

  ## define counter function
  counter <- function (i) 
  {
    if (i%%10 == 0) 
      cat(i)
    else cat(".")
    if (i%%50 == 0) 
      cat("\n")
    flush.console()
  }

  outMAT <- NULL 

  for (i in 1:NR) {
    counter(i)

    ## get predictor values and optional errors
    predVAL <- newdata[i, 1]
    if (ncol(newdata) == 2) predERROR <- newdata[i, 2] else predERROR <- 0
    names(predVAL) <- predNAME  
    names(predERROR) <- predNAME  

    ## create mean vector for 'mvrnorm'
    MU <- c(COEF, predVAL)

    ## create variance-covariance matrix for 'mvrnorm'
    ## by putting error^2 in lower-right position of VCOV
    newVCOV <- VCOV
    newVCOV[varPLACE, varPLACE] <- predERROR^2

    ## create MC simulation matrix
    simMAT <- mvrnorm(n = nsim, mu = MU, Sigma = newVCOV, empirical = TRUE)

    ## evaluate expression on rows of simMAT
    EVAL <- try(eval(EXPR, envir = as.data.frame(simMAT)), silent = TRUE)
    if (inherits(EVAL, "try-error")) stop("There was an error evaluating the simulations!")

    ## collect statistics
    PRED <- data.frame(predVAL)
    colnames(PRED) <- predNAME   
    FITTED <- predict(object, newdata = data.frame(PRED))
    MEAN.sim <- mean(EVAL, na.rm = TRUE)
    SD.sim <- sd(EVAL, na.rm = TRUE)
    MEDIAN.sim <- median(EVAL, na.rm = TRUE)
    MAD.sim <- mad(EVAL, na.rm = TRUE)
    QUANT <- quantile(EVAL, c((1 - level)/2, level + (1 - level)/2))
    RES <- c(FITTED, MEAN.sim, SD.sim, MEDIAN.sim, MAD.sim, QUANT[1], QUANT[2])
    outMAT <- rbind(outMAT, RES)
  }

  colnames(outMAT) <- c("fit", "mean", "sd", "median", "mad", names(QUANT[1]), names(QUANT[2]))
  rownames(outMAT) <- NULL

  cat("\n")

  return(outMAT)  
}

然后他写道:“输入是一个'nls'对象,一个data.frame'newdata'值,第一列中的值x_new和(可选)“errors-in-x”(作为sigma)在第二列中。可以使用 nsim 以及置信区间的 alpha 级别调整模拟次数。输出为 f(x_new, beta)(拟合值),mu(y_n)(模拟平均值), sigma(y_n)(模拟的标准差),中位数(y_n)(模拟的中位数),mad(y_n)(模拟的疯狂)和下/上置信区间。

他有一些额外的文字进一步解释了这一点并给出了一个使用示例,但我觉得将他的整个博客文章复制到这个答案中真的不合适,所以请访问他的页面(如果它仍然存在)以获取更多详细信息. 无论如何,它非常简单且不言自明,并且在第一次尝试时就为我工作。谢谢安德烈!

关于置信区间的注释(以上 2),以及@Etienne Low-Décarie的回答:

即使在附加 nls2 之后,as.lm 函数有时也不可用。基于这个(现在陈旧的)参考(最初由delichon撰写),这里是函数的来源:

as.lm.nls <- function(object, ...) {
    if (!inherits(object, "nls")) {
        w <- paste("expected object of class nls but got object of class:",
        paste(class(object), collapse = " "))
        warning(w)
    }

    gradient <- object$m$gradient()
    if (is.null(colnames(gradient))) {
        colnames(gradient) <- names(object$m$getPars())
    }

    response.name <- if (length(formula(object)) == 2) "0" else
        as.character(formula(object)[[2]])

    lhs <- object$m$lhs()
    L <- data.frame(lhs, gradient)
    names(L)[1] <- response.name

    fo <- sprintf("%s ~ %s - 1", response.name,
    paste(colnames(gradient), collapse = "+"))
    fo <- as.formula(fo, env = as.proto.list(L))

    do.call("lmst(fo, offset = substitute(fitted(object))))
}

然后使用predict标准方式:

predCI <- predict(as.lm.nls(fittednls), interval = “confidence”, level = 0.95)

谢谢@waybackmachine

我也在努力解决这个问题,最终在传播包中找到了 predictNLS () 函数。

例如:

library(propagate)
Y    <- c(282, 314, 581, 846, 1320, 2014, 2798, 4593, 6065, 7818, 9826)
temp <- data.frame(y = Y, x = seq(1:11))
mod  <- nls(y ~ exp(a + b * x), data = temp, start = list(a = 0, b = 1))

(PROP1 <- predictNLS(mod, newdata = data.frame(x = c(12,13)), interval = "prediction"))

希望这可以帮助。

链接到 R 文档