我不明白为什么我不能拥有这些数据的nls函数.我尝试了很多不同的起始值,我总是有同样的错误.
这是我一直在做的事情:
expFct2 = function (x, a, b,c)
{
a*(1-exp(-x/b)) + c
}
vec_x <- c(77.87,87.76,68.6,66.29)
vec_y <- c(1,1,0.8,0.6)
dt <- data.frame(vec_x=vec_x,vec_y=vec_y)
ggplot(data = dt,aes(x = vec_x, y = vec_y)) + geom_point() +
geom_smooth(data=dt, method="nls", formula=y~expFct2(x, a, b, c),
se=F, start=list(a=1, b=75, c=-5)
Run Code Online (Sandbox Code Playgroud)
我总是有这个错误:
Error in method(formula, data = data, weights = weight, ...) :
singular gradient
Run Code Online (Sandbox Code Playgroud)
在任何情况下,将三参数非线性模型拟合到四个数据点将是适度的挑战,尽管在这种情况下数据表现良好.第1点是你的c参数(-5)的起始值是偏离的.绘制与您的起始参数相对应的曲线图片(见下文)将有助于您理解这一点(因此会认识到您获得的曲线将从c最小值到c+a最大值,并且数据范围从0.6到1 ...)
然而,即使有一个更好的起始猜测我发现自己忙于控制参数(即control=nls.control(maxiter=200)),然后是更多的警告 - nls并不知道它的稳健性.所以我尝试了这个SSasympOff模型,它实现了你想要适合的曲线的自启动版本.
start1 <- list(a=1, b=75, c=-5)
start2 <- list(a=0.5, b=75, c=0.5) ## a better guess
pfun <- function(params) {
data.frame(vec_x=60:90,
vec_y=do.call(expFct2,c(list(x=60:90),params)))
}
library(ggplot2)
ggplot(data = dt,aes(x = vec_x, y = vec_y)) + geom_point() +
geom_line(data=pfun(start1))+
geom_line(data=pfun(start2),colour="red")+
geom_smooth(data=dt, method="nls", formula=y~SSasympOff(x, a, b, c),
se=FALSE)
Run Code Online (Sandbox Code Playgroud)
我一般建议是,它更容易弄清楚发生了什么事情,如果你适合解决问题nls 之外的geom_smooth,建设希望使用添加的曲线predict.nls......
更一般地说,获得良好起始参数的方法是了解拟合函数的几何形状,以及哪些参数控制曲线的哪些方面.正如我上面提到的,c是移位饱和指数曲线的最小值,a是范围,并且b是一个比例参数(你可以看到,当x=b曲线是1-exp(-1)或者从最小值到最大值的大约2/3时).无论是一些代数和微积分(即取得限制),还是玩弄curve()函数,都是收集这些信息的好方法.
这可以用两个线性参数(.lin1和.lin2)和一个非线性参数(b)写成:
a*(1-exp(-x/b)) + c
= (a+c) - a * exp(-x/b)
= .lin1 + .lin2 * exp(-x/b)
Run Code Online (Sandbox Code Playgroud)
where .lin1 = a+c和.lin2 = -a(so a = - .lin2and c = .lin1 + .lin2)这让我们使用"plinear"它只需要指定单个非线性参数的起始值(消除如何设置其他参数的起始值的问题),并且尽管起始值b=75远离解决方案:
nls(y ~ cbind(1, exp(-x/b)), start = list(b = 75), alg = "plinear")
Run Code Online (Sandbox Code Playgroud)
这是一个运行的结果,从中可以看出.lin2问题严重缩放的大小:
> x <- c(77.87,87.76,68.6,66.29)
> y <- c(1,1,0.8,0.6)
> nls(y ~ cbind(1, exp(-x/b)), start = list(b = 75), alg = "plinear")
Nonlinear regression model
model: y ~ cbind(1, exp(-x/b))
data: parent.frame()
b .lin1 .lin2
3.351e+00 1.006e+00 -1.589e+08
residual sum-of-squares: 7.909e-05
Number of iterations to convergence: 9
Achieved convergence tolerance: 9.887e-07
> R.version.string
[1] "R version 2.14.2 Patched (2012-02-29 r58660)"
> win.version()
[1] "Windows Vista (build 6002) Service Pack 2"
Run Code Online (Sandbox Code Playgroud)
编辑:添加样本运行和评论缩放.