我不明白为什么我不能拥有这些数据的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)
我一直都有这个错误:
Error in method(formula, data = data, weights = weight, ...) :
singular gradient
答案 0 :(得分:9)
在任何情况下,将三参数非线性模型拟合到四个数据点将具有中等挑战性,尽管在这种情况下数据表现良好。第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)
我的一般建议是,如果您在nls
之外的geom_smooth
以及构建要添加的曲线,则更容易找出正在发生的事情并解决问题使用predict.nls
...
更一般地说,获得良好起始参数的方法是了解拟合函数的几何形状,以及哪些参数控制曲线的哪些方面。如上所述,c
是移位饱和指数曲线的最小值,a
是范围,b
是比例参数(您可以看到{{1} },曲线是x=b
或从最小值到最大值的大约2/3。无论是一些代数和微积分(即限制),还是使用1-exp(-1)
函数,都是收集这些信息的好方法。
答案 1 :(得分:8)
这可以使用两个线性参数(.lin1
和.lin2
)和一个非线性参数(b
)来编写,如下所示:
a*(1-exp(-x/b)) + c
= (a+c) - a * exp(-x/b)
= .lin1 + .lin2 * exp(-x/b)
其中.lin1 = a+c
和.lin2 = -a
(所以a = - .lin2
和c = .lin1 + .lin2
)这让我们可以使用"plinear"
,它只需要指定单个非线性的起始值参数(消除了如何设置其他参数的起始值的问题),并且尽管b=75
的起始值远离解决方案的起始值,但会收敛:
nls(y ~ cbind(1, exp(-x/b)), start = list(b = 75), alg = "plinear")
以下是运行的结果,我们可以从.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"
编辑:添加了示例运行和对缩放的评论。
答案 2 :(得分:2)
我很难找到对你的参数的解释: a是斜率,b是收敛速度,a + c是极限, 但c本身似乎并不意味着什么。 重新参数化后,问题就会消失。
f <- function (x, a,b,c) a + c * exp(-x/abs(b))
nls(y~f(x, a, b, c), data=dt, start=list(a=1, b=75, c=-5), trace=TRUE)
但是,c
的值看起来非常非常高:
这可能是该模型最初未能收敛的原因。
Nonlinear regression model
model: y ~ f(x, a, b, c)
data: dt
a b c
1.006e+00 3.351e+00 -1.589e+08
residual sum-of-squares: 7.909e-05
Number of iterations to convergence: 9
Achieved convergence tolerance: 2.232e-06
这是同一函数的另一个更合理的参数化。
g <- function (x, a,b,c) a * (1-exp(-(x-c)/abs(b)))
nls(y~g(x, a, b, c), data=dt, start=list(a=1, b=75, c=-5), trace=TRUE)
Nonlinear regression model
model: y ~ g(x, a, b, c)
data: dt
a b c
1.006 3.351 63.257
residual sum-of-squares: 7.909e-05
Number of iterations to convergence: 10
Achieved convergence tolerance: 1.782e-06