Fit 'nls': 初始参数估计处的奇异梯度矩阵
Fit 'nls': singular gradient matrix at initial parameter estimates
我是 '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))
你问这个问题已经有一段时间了,但也许你仍然对一些评论感兴趣:
至少你的 fit2
在改变起始参数时工作正常(见下面的代码和图表)。我猜 fit3
只是一个 "too complicated" 模型,因为这些数据基本上遵循线性趋势。这意味着两个参数通常足以合理地描述数据(参见第二个图)。
所以作为一般提示:当您获得
singular gradient matrix at initial parameter estimates
你可以
1) 改变起始 values/your 初始参数估计值
and/or
2) 尝试通过查找通常会引起麻烦的冗余参数来简化模型。
我还强烈建议始终先绘制数据和您的初始猜测(另请检查 )。
这是一个图表,显示了您的 fit
、fit2
和我定义的第三个函数的结果,代码如下:
如您所见,fit2
与具有变量 z
和一个附加指数的函数之间几乎没有区别。两个参数似乎足以合理地描述系统(也有一个已经很好地用上图中的黑线表示)。如果您随后想通过某个数据点拟合一条线,您还可以查看 .
那么当我们使用一个带有两个自由参数的线性函数和一个带有变量 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'))
我是 '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))
你问这个问题已经有一段时间了,但也许你仍然对一些评论感兴趣:
至少你的 fit2
在改变起始参数时工作正常(见下面的代码和图表)。我猜 fit3
只是一个 "too complicated" 模型,因为这些数据基本上遵循线性趋势。这意味着两个参数通常足以合理地描述数据(参见第二个图)。
所以作为一般提示:当您获得
singular gradient matrix at initial parameter estimates
你可以
1) 改变起始 values/your 初始参数估计值
and/or
2) 尝试通过查找通常会引起麻烦的冗余参数来简化模型。
我还强烈建议始终先绘制数据和您的初始猜测(另请检查
这是一个图表,显示了您的 fit
、fit2
和我定义的第三个函数的结果,代码如下:
如您所见,fit2
与具有变量 z
和一个附加指数的函数之间几乎没有区别。两个参数似乎足以合理地描述系统(也有一个已经很好地用上图中的黑线表示)。如果您随后想通过某个数据点拟合一条线,您还可以查看
那么当我们使用一个带有两个自由参数的线性函数和一个带有变量 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'))