R:非线性拟合与非分析模型的置信区间

时间:2018-01-08 08:36:48

标签: r non-linear-regression

我需要将x-y数据与模型拟合,这是非分析性的。我有一个函数f(x),它以数字方式计算每个x的模型,但没有解析方程式。为了拟合,我在R中使用optim。我最小化模型和数据之间的RMS。它运作良好并返回合理的参数。

我想在最佳拟合参数上找到置信区间(或至少是标准误差)。我在互联网上发现,这可以通过Hessian矩阵完成,但仅限于最大化对数似然函数。我不知道如何做到这一点,我所拥有的只有xyf(x),我从中找到了RMS。唉,我没有办法估算y上的错误。

如何在拟合参数上找到置信区间?

编辑:或许R中的一个例子可能有助于解释我所要求的内容。这个例子使用一个简单的分析函数来拟合数据,在我的实际情况中,函数是非解析的,所以我不能使用,例如nls

set.seed(666)

# generate data
x <- seq(100) / 100
y <- 0.5 * x + rnorm(100, sd = 0.03) + 0.2

# function to fit
f <- function(x, a, b) {
  a * x + b
}

# error function to minimise: RMS
errfun <- function(par, x, y) {
  a <- par[1]
  b <- par[2]
  err <- sqrt(sum((f(x, a, b) - y)^2))
}

# use optim to fit the model to the data
par <- c(1, 0)
res <- optim(par, errfun, gr=NULL, x, y)

# best-fitting parameters
best_a <- res$par[1]
best_b <- res$par[2]

最佳拟合参数是a = 0.50和b = 0.20。我需要在这些上找到95%的置信区间。

1 个答案:

答案 0 :(得分:0)

这是bootstrap的工作:

(1)创建大量合成数据集x*。这些是通过从x采样替换与x中相同数量的数据创建的。例如,如果您的数据为(1,2,3,4,5,6),则x*可能为(5,2,4,4,2,3)(请注意,值可能会多次出现,或者根本不出现,因为我们正在使用替换进行抽样)

(2)对于每个x*,计算f(x*)。如果有其他参数不依赖于数据,请不要更改它们。 (只要f(x,a,b,c)不依赖f(x*,a,b,c)a,b,c就变为x。请将这些数量称为f*

(3)您可以从这些f*中估算出您想要的任何内容。如果您希望标准差为f(x),请采用f*的标准差。如果您想要95%置信区间,请选择f*的2.5到97.5百分位数的范围。更正式的是,如果您想估算g(f(x)),请将其估算为g(f(x*))

我应该说这是一个非常实用的引导程序解释。我已经掩盖了许多理论细节,但是引导程序几乎普遍适用(基本上只要你试图估计的事实存在,你通常都可以。)

将此应用于您在代码中提供的示例:

x <- seq(100) / 100
y <- 0.5 * x + rnorm(100, sd = 0.03) + 0.2

# function to fit
f <- function(x, a, b) {
  a * x + b
}

# error function to minimise: RMS
errfun <- function(par, x, y) {
  a <- par[1]
  b <- par[2]
  err <- sqrt(sum((f(x, a, b) - y)^2))
}

# this is the part where we bootstrap
# use optim to fit the model to the data
best_a <- best_b <- numeric(10000)
for(i in 1:10000){
  j <- sample(100,replace=TRUE)
  x.boot <- x[j]; y.boot <- y[j]
par <- c(1, 0)
res <- optim(par, errfun, gr=NULL, x.boot, y.boot)

# best-fitting parameters
best_a[i] <- res$par[1]
best_b[i] <- res$par[2]
}
# now, we look at the *vector* best_a
# for example, if you want the standard deviation of a,
sd(best_a)
# or a 95% confidence interval for b,
quantile(best_b,c(0.025,0.975))