我正在尝试解决以下问题:
x <- c(0.11557577149788574,2.1552479877306925,2.5505873377321175,1.0995198836006757,3.710225290286669,2.386870541964232,0.11557577149788574,0.11557577149788574,2.1552479877306925,2.5505873377321175,1.0995198836006757,3.710225290286669,2.386870541964232,0.11557577149788574)
y <- c(16500,11500,11500,13630,7000,11995,13490,16500,11500,11500,13630,7000,11995,13490)
df <- data.frame(x, y)
m <- nls(y ~ I(a*exp(-b*x)+c), data=df, start=list(a=14000, b=1, c=100), control=nls.control(maxiter=10000, minFactor=1e-7, tol=1e-5, printEval=F, warnOnly=F))
但是,即使我尝试更改起始值和nls控件,也不会返回任何值。 我做错了什么?我需要更多的积分来解决这个问题吗?
谢谢!
答案 0 :(得分:1)
您需要更好的起始值。
首先按增加x
的顺序对数据框进行排序,以便绘图效果很好。
如果我们将c
设置为零,我们可以将更简单的模型拟合到log(y) ~ A - b*x
,这在所有系数中都是线性的,因此它可以通过lm
拟合,并且不需要起始值。
使用该更简单模型给出的b
的起始值。另请注意,a
和c
线性输入完整模型,因此我们可以使用plinear
nls
算法,无需为这些系数提供起始值:
o <- order(df$x)
df_o <- df[o, ] # order it by increasing x
fm0 <- lm(log(y) ~ I(-x), df_o) # simpler model to get better starting values
fm <- nls(y ~ cbind(exp(-b*x), 1), df_o, start = coef(fm0)[2], alg = "plinear")
plot(df_o, col = "red", pch = 20)
lines(fitted(fm) ~ x, df_o)
结果如下.lin1
为a
且.lin2
为c
:
> fm
Nonlinear regression model
model: y ~ cbind(exp(-b * x), 1)
data: df_o
b .lin1 .lin2
-0.4903 -1529.0253 16509.4422
residual sum-of-squares: 10555038
Number of iterations to convergence: 5
Achieved convergence tolerance: 8.504e-07
这里我们将输入数据显示为红点,并通过拟合结果绘制线条:
答案 1 :(得分:0)
您的数据集中没有足够的信息来可靠地估计此非线性模型的系数。您的数据几乎没有曲率。如果你使用Levenberg-Marquardt,它会遇到与线性拟合大致相等的参数值:
plot(y~x)
library(minpack.lm)
m <- nlsLM(y ~ a*exp(-b*x)+c, data=df, start=list(a=14000, b=1, c=100),
control = nls.lm.control(maxiter = 1000))
summary(m)
#Formula: y ~ a * exp(-b * x) + c
#
#Parameters:
# Estimate Std. Error t value Pr(>|t|)
#a 2.308e+06 6.822e+08 0.003 0.997
#b 8.506e-04 2.518e-01 0.003 0.997
#c -2.292e+06 6.822e+08 -0.003 0.997
#
#Residual standard error: 1250 on 11 degrees of freedom
#Number of iterations till stop: 94
#Achieved convergence tolerance: 1.49e-08
#Reason stopped: Number of calls to `fcn' has reached or exceeded `maxfev' == 400.
lines(x, predict(m), col="green", lwd=2)
abline(lm(y~x), col="red", lty=2, lwd=2)
如果模型基于科学,则测量的x值范围可能太小。
答案 2 :(得分:0)
问题似乎出现在您的数据中。
如果您尝试plot( y ~ x )
,那么它看起来并不是指数级的:实际上它似乎比线性略快,特别是如果您发现数据中有x y
个值实际上有两个点3.710225 7000
所以你试图将凸曲线拟合到表明凹曲线的数据。两个建议:
删除这两点:
df2 <- df[df$y!=7000,]
m2 <- nls(y ~ I(a*exp(-b*x)+c), data=df2, start=list(a=14000, b=1, c=100), control=nls.control(maxiter=10000, minFactor=1e-7, tol=1e-5, printEval=F, warnOnly=F))
给予
Nonlinear regression model
model: y ~ I(a * exp(-b * x) + c)
data: df2
a b c
1.418e+04 1.202e-01 1.030e+03
residual sum-of-squares: 9781328
Number of iterations to convergence: 14
Achieved convergence tolerance: 2.573e-06
通过扭转a
和b
m <- nls(y ~ I(a*exp(-b*x)+c), data=df, start=list(a=-14000, b=-1, c=100), control=nls.control(maxiter=10000, minFactor=1e-7, tol=1e-5, printEval=F, warnOnly=F))
给予
Nonlinear regression model
model: y ~ I(a * exp(-b * x) + c)
data: df
a b c
-1529.0204 -0.4903 16509.4360
residual sum-of-squares: 10555038
Number of iterations to convergence: 7
Achieved convergence tolerance: 7.471e-07