拟合'nls':初始参数估计时的奇异梯度矩阵

时间:2015-07-19 22:18:43

标签: r curve-fitting nls

我是新手使用'nls',我遇到了找到起始参数的问题。我已经阅读了几篇文章并尝试了各种参数和公式结构,但我一直都会遇到错误。

这是我正在做的一个小例子,如果有人能给我一些提示我会非常感激!

# Data to which I want to fit a non-linear function
x <- c(0,  4, 13, 30, 63, 92)
y <- c(0.00000000, 0.00508822, 0.01103990, 0.02115466, 0.04036655, 0.05865331)
z <- 0.98

# STEPS:
# 1 pool, z fixed. This works.
fit <- nls(y ~ z * ((1 - exp(-k1*x))),
           start=list(k1=0))


# 2 pool model, z fixed
fit2 <- nls(y ~ z * (1 - exp(-k1*x)) + (1 - exp(-k2*x)),
            start=list(k1=0, k2=0)) # Error: singular gradient matrix at initial parameter estimates


# My goal: 2 pool model, z free
fit3 <- nls(y ~ z * (1 - exp(-k1*x)) + (1 - exp(-k2*x)),
            start=list(z=0.5, k1=0, k2=0)) 

1 个答案:

答案 0 :(得分:2)

自从您提出问题以来已经有一段时间了,但也许您仍对某些评论感兴趣:

当一个人改变起始参数时,至少你的fit2可以正常工作(参见下面的代码和图表)。我认为fit3只是一个“太复杂”的模型,因为这些数据基本上只是一个线性趋势。这意味着两个参数通常足以很好地描述数据(见第二个图)。

所以作为一般提示:当你获得

  

初始参数估计时的奇异梯度矩阵

你可以

1)改变起始值/初始参数估计值

和/或

2)尝试通过查找通常会导致麻烦的冗余参数来简化模型。

我还强烈建议您始终将数据与初始猜测一起绘制(另请参阅this question)。

以下是显示fitfit2和我定义的第三个函数的结果的图表,该函数在下面的代码中给出:

enter image description here

正如您所看到的,fit2与具有变量z和另外一个指数的函数之间几乎没有区别。两个参数似乎足以很好地描述系统的合理性(一个已经很好地用上图中的黑线表示)。如果您希望在某个数据点中插入一条线,您还可以查看this answer

那么当一个人使用具有两个自由参数的线性函数和一个具有变量z,一个指数项和一个变量偏移的函数时,现在看起来如何?如下图所示;再次没有太大的区别:

enter image description here

残差如何比较?

> fit
Nonlinear regression model
  model: y ~ zfix * ((1 - exp(-k1 * x)))
   data: parent.frame()
       k1 
0.0006775 
 residual sum-of-squares: 1.464e-05

> fit2
Nonlinear regression model
  model: y ~ zfix * (1 - exp(-k1 * x)) + (1 - exp(-k2 * x))
   data: parent.frame()
        k1         k2 
-0.0006767  0.0014014 
 residual sum-of-squares: 9.881e-06

> fit3
Nonlinear regression model
  model: y ~ Z * (1 - exp(-k1 * x))
   data: parent.frame()
       Z       k1 
0.196195 0.003806 
 residual sum-of-squares: 9.59e-06

> fit4
Nonlinear regression model
  model: y ~ a * x + b
   data: parent.frame()
        a         b 
0.0006176 0.0019234 
 residual sum-of-squares: 6.084e-06

> fit5
Nonlinear regression model
  model: y ~ z * (1 - exp(-k1 * x)) + k2
   data: parent.frame()
       z       k1       k2 
0.395106 0.001685 0.001519 
 residual sum-of-squares: 5.143e-06

可以猜测,只有一个自由参数的拟合给出了最差,而有三个自由参数的拟合给出了最好的结果;然而,(在我看来)没有太大的区别。

以下是我使用的代码:

x <- c(0,  4, 13, 30, 63, 92)
y <- c(0.00000000, 0.00508822, 0.01103990, 0.02115466, 0.04036655, 0.05865331)
zfix <- 0.98

plot(x,y)

# STEPS:
# 1 pool, z fixed. This works.
fit <- nls(y ~ zfix * ((1 - exp(-k1*x))), start=list(k1=0))
xr = data.frame(x = seq(min(x),max(x),len=200))
lines(xr$x,predict(fit,newdata=xr))

# 2 pool model, z fixed
fit2 <- nls(y ~ zfix * (1 - exp(-k1*x)) + (1 - exp(-k2*x)), start=list(k1=0, k2=0.5))
lines(xr$x,predict(fit2,newdata=xr), col='red')

# 3 z variable
fit3 <- nls(y ~ Z * (1 - exp(-k1*x)), start=list(Z=zfix, k1=0.2))
lines(xr$x,predict(fit3,newdata=xr), col='blue')

legend('topleft',c('fixed z, single exp', 'fixed z, two exp', 'variable z, single exp'), 
       lty=c(1,1,1),
       lwd=c(2.5,2.5,2.5),
       col=c('black', 'red','blue'))

#dev.new()
plot(x,y)

# 4 fit linear function a*x + b
fit4 <- nls(y ~ a *x + b, start=list(a=1, b=0.))
lines(xr$x,predict(fit4,newdata=xr), col='blue')

fit5 <- nls(y ~ z * (1 - exp(-k1*x)) + k2,  start=list(z=zfix, k1=0.1, k2=0.5))
lines(xr$x,predict(fit5,newdata=xr), col='red')

legend('topleft',c('linear approach', 'variable z, single exp, offset'), 
       lty=c(1,1),
       lwd=c(2.5,2.5),
       col=c('blue', 'red'))