使逻辑增长曲线适合数据

时间:2015-07-05 23:53:18

标签: r curve-fitting logistic-regression

我一直试图将逻辑增长方程拟合到我的数据集中,结果好坏参半。我通常使用这样的设置:

# Post PT
time <- 1:48

Diversity <- new8

plot(time, Diversity,log="y",las=1, pch=16, type="l")

logisticModel <- nls(Diversity~K/(1+exp(Po+r*time)), start=list(Po=25, r=-1.6, K=200),control=list(maxiter=1000,minFactor=.00000000001))

这里的目标是在逻辑上随时间推移建模Diversity;这是渐近线的物种多样性曲线。但是,对于特定的数据集,我无法让模型起作用,也不能为我的生活找出原因。例如,在一次迭代中,正在提取的Diversity(因此,new8)值是

[1]  25  22  68  72 126 141  82  61  97 126 101 110 173 164 160 137 122 113 104 104 109 102 107 122 149 127 137 146 185 188 114  91 102 132 147
[36] 148 151 154 165 215 216 206 205 207 207 220 200 204

# plot via this, and it is a nice species diversity curve beginning to level off

plot(Diversity,type="l")

这个数据已经开始达到极限,但我不能适应它的逻辑曲线。如果我尝试,无论迭代次数多高,我都会遇到超出最大迭代次数的错误。我一遍又一遍地玩起始参数而没有运气。目前,例如代码如下所示:

# Post PT
time <- 1:48

Diversity <- new8

plot(time, Diversity,log="y",las=1, pch=16, type="l")

logisticModel <- nls(Diversity~K/(1+exp(Po+r*time)), start=list(Po=25, r=-1.6, K=200),control=list(maxiter=1000,minFactor=.00000000001))

任何帮助都不仅仅是值得赞赏的。整天坐在我的沙发上停留在这上面。如果某人有更好的方法来强制从数据中提取物流增长曲线,我很乐意听到它!作为旁注,我对这些数据集使用SSlogis也没有运气。

1 个答案:

答案 0 :(得分:2)

数值不稳定性常常是涉及指数项的模型的问题。尝试使用起始参数评估模型:

> 200/(1+exp(25-1.6*df$norm_time))
 [1] 2.871735e-09 2.969073e-09 3.069710e-09 3.173759e-09 3.281333e-09 3.392555e-09 3.507546e-09 3.626434e-09 3.749353e-09
[10] 3.876437e-09 4.007830e-09 4.143676e-09 4.284126e-09 4.429337e-09 4.579470e-09 4.734691e-09 4.895174e-09 5.061097e-09
[19] 5.232643e-09 5.410004e-09 5.593377e-09 5.782965e-09 5.978979e-09 6.181637e-09 6.391165e-09 6.607794e-09 6.831766e-09
[28] 7.063329e-09 7.302742e-09 7.550269e-09 7.806186e-09 8.070778e-09 8.344338e-09 8.627170e-09 8.919589e-09 9.221919e-09
[37] 9.534497e-09 9.857670e-09 1.019180e-08 1.053725e-08 1.089441e-08 1.126368e-08 1.164546e-08 1.204019e-08 1.244829e-08
[46] 1.287023e-08 1.330646e-08 1.375749e-08

由于预测数据具有如此小的值,因此nls()估计梯度所需的参数的任何适度变化都可能会产生非常小的数据变化,几乎不会超过甚至低于minFactor()

规范化您的数据以使其数值范围在友好的友好范围内(例如0到1)会更好。

require(stringr)
require(ggplot2)
new8 <- '25  22  68  72 126 141  82  61  97 126 101 110 173 164 160 137 122 113 104 104 109 102 107 122 149 127 137 146 185 188 114  91 102 132 147 148 151 154 165 215 216 206 205 207 207 220 200 204'
Diversity = as.numeric(str_split(new8, '[ ]+')[[1]])
time <- 1:48
df = data.frame(time=time, div=Diversity)

# normalize time
df$norm_time <- df$time / max(df$time)

# normalize diversity
df$norm_div <- (df$div - min(df$div)) / max(df$div)

通过这种规范化多样性的方式,您的Po参数始终可以假设为0.这意味着我们可以从模型中消除它。该模型现在只有两个自由度而不是三个,这也使得拟合更容易。

这引导我们进入以下模式:

logisticModel <- nls(norm_div~K/(1+exp(r*norm_time)), data=df, 
                     start=list(K=1, r=-1.6), 
                     control=list(maxiter=1000, minFactor=.00000000001))

您的数据看起来并不适合我的模型,但我不是您所在领域的专家:

ggplot(data=df, aes(x=norm_time, y=norm_div)) + 
geom_point(log='y') + 
  geom_line(aes(x=norm_time, y=predict(logisticModel)), color='red') +
  theme_bw()

quartz.save('~/Desktop/SO_31236153.png', type='png')

summary(logisticModel)

Formula: norm_div ~ K/(1 + exp(r * norm_time))

Parameters:
  Estimate Std. Error t value Pr(>|t|)    
K   0.6940     0.1454   4.772 1.88e-05 ***
r  -2.6742     2.4222  -1.104    0.275    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.1693 on 46 degrees of freedom

Number of iterations to convergence: 20 
Achieved convergence tolerance: 5.895e-06

enter image description here