R中nls的指数回归

时间:2014-10-25 09:07:16

标签: r regression exponential

我正在尝试解决以下问题:

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控件,也不会返回任何值。 我做错了什么?我需要更多的积分来解决这个问题吗?

谢谢!

3 个答案:

答案 0 :(得分:1)

您需要更好的起始值。

首先按增加x的顺序对数据框进行排序,以便绘图效果很好。

如果我们将c设置为零,我们可以将更简单的模型拟合到log(y) ~ A - b*x,这在所有系数中都是线性的,因此它可以通过lm拟合,并且不需要起始值。

使用该更简单模型给出的b的起始值。另请注意,ac线性输入完整模型,因此我们可以使用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)

结果如下.lin1a.lin2c

> 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

这里我们将输入数据显示为红点,并通过拟合结果绘制线条:

enter image description here

答案 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)

resulting plot

如果模型基于科学,则测量的x值范围可能太小。

答案 2 :(得分:0)

问题似乎出现在您的数据中。

如果您尝试plot( y ~ x ),那么它看起来并不是指数级的:实际上它似乎比线性略快,特别是如果您发现数据中有x y个值实际上有两个点3.710225 7000所以你试图将凸曲线拟合到表明凹曲线的数据。两个建议:

  1. 删除这两点:

    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))

  2. 给予

    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
    
    1. 通过扭转ab

      的符号,让您的起点建议凹曲线

      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))

    2. 给予

      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