使用R拟合Sigmoidal曲线

时间:2015-10-09 08:11:47

标签: r curve-fitting

我已阅读帖子(R中的Sigmoidal Curve Fit)。它被标记为重复,但我看不到与帖子有关的任何内容。而这些帖子的答案还不够。

我读了webpage

与其他人类似,他使用这种格式来符合这条线:

fitmodel <- nls(y~a/(1 + exp(-b * (x-c))), start=list(a=1,b=.5,c=25))

问题是,在大多数情况下给出了a,b,c,我没有线索,我应该将a,b,c用于我的数据集。有人可以就如何获取参数给我一些建议吗?

这是我的一组数字:

x <- c(3.9637878,3.486667,3.0095444,2.5324231,2.0553019,1.5781806,1.1010594,0.6242821)
y <- c(6491.314,6190.092,2664.021,2686.414,724.707,791.243,1809.586,541.243)

3 个答案:

答案 0 :(得分:5)

幸运的是,R为物流模型提供了自我启动模型。它使用了轻微的重新参数化,但实际上与您的模型相同:Asym/(1+exp((xmid-input)/scal))

自我启动模型可以为您估算出良好的起始值,因此您不必指定它们。

plot(y ~ x)
fit <- nls(y ~ SSlogis(x, Asym, xmid, scal), data = data.frame(x, y))

summary(fit)
#Formula: y ~ SSlogis(x, Asym, xmid, scal)
#
#Parameters:
#      Estimate Std. Error t value Pr(>|t|)
#Asym 1.473e+04  2.309e+04   0.638    0.551
#xmid 4.094e+00  2.739e+00   1.495    0.195
#scal 9.487e-01  5.851e-01   1.622    0.166
#
#Residual standard error: 941.9 on 5 degrees of freedom
#
#Number of iterations to convergence: 0 
#Achieved convergence tolerance: 4.928e-06

lines(seq(0.5, 4, length.out = 100), 
      predict(fit, newdata = data.frame(x = seq(0.5, 4, length.out = 100))))

resulting plot

当然,您的数据并不真正支持该模型。估计的中点恰好位于数据范围的正确极限,因此参数估计(特别是渐近线)非常不确定。

答案 1 :(得分:2)

我用来填充数据的代码:

 df <- data.frame(x=c(3.9637878,3.486667,3.0095444,2.5324231,2.0553019,1.5781806,1.1010594,0.6242821),                     
                  y=c(6491.314,6190.092,2664.021,2686.414,724.707,791.243,1809.586,541.243))

library(drc)
fm <- drm(y ~ x, data = df, fct = G.3())

plot(fm)
summary(fm)

拟合之后的样子: enter image description here

答案 2 :(得分:1)

我看到两个问题。

  1. nls的默认算法对起始参数非常敏感。在您的示例数据中,我发现使用algorithm='port'很有用。或者,切换到“强大”的实现也可能有所帮助。

  2. 它有助于理解模型中参数的作用。

  3. 您模型的简单解释是: sigmoid从0到a。它到达x = c的“中途”点。 b具有斜率的作用,如果为负,则模型将从a变为0。

    特别是对于您发布的测试数据,我估计起始值如下:

    • 我注意到的第一件事 - 您的数据并非完全“接近”为零,因此添加大约1000的偏移量d可能会有用。
    • a则为5000或更高
    • c更大2 - 也许3
    • b需要猜测 - 从x 2到3.5你的信号跳跃从1000到6000给出5000差异 - 除以a - 斜率为1 / 1.5 = 0.66或更高......让我们四舍五入。

    所以最终使用公式

    fitmodel <- nls(y ~a/(1 + exp(-b * (x-c)) ) + d, start=list(a=5000,b=1,c=3, d=1000))
    

    给出一个拟合(也可以在没有d的情况下工作)。试着找到设置algorithm='port'使命令对起始值更不敏感。