我是新手使用'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))
答案 0 :(得分:2)
自从您提出问题以来已经有一段时间了,但也许您仍对某些评论感兴趣:
当一个人改变起始参数时,至少你的fit2
可以正常工作(参见下面的代码和图表)。我认为fit3
只是一个“太复杂”的模型,因为这些数据基本上只是一个线性趋势。这意味着两个参数通常足以很好地描述数据(见第二个图)。
所以作为一般提示:当你获得
初始参数估计时的奇异梯度矩阵
你可以
1)改变起始值/初始参数估计值
和/或
2)尝试通过查找通常会导致麻烦的冗余参数来简化模型。
我还强烈建议您始终将数据与初始猜测一起绘制(另请参阅this question)。
以下是显示fit
,fit2
和我定义的第三个函数的结果的图表,该函数在下面的代码中给出:
正如您所看到的,fit2
与具有变量z
和另外一个指数的函数之间几乎没有区别。两个参数似乎足以很好地描述系统的合理性(一个已经很好地用上图中的黑线表示)。如果您希望在某个数据点中插入一条线,您还可以查看this answer。
那么当一个人使用具有两个自由参数的线性函数和一个具有变量z,一个指数项和一个变量偏移的函数时,现在看起来如何?如下图所示;再次没有太大的区别:
残差如何比较?
> 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'))