R非线性最小二乘(nls)模型拟合

时间:2012-06-27 20:38:04

标签: r model plot nls model-fitting

我正在尝试将来自我的数据的G函数的信息拟合到以下数学模式:y = A /((1 +(B ^ 2)*(x ^ 2))^((C + 1 )/ 2))。这张图的形状可以在这里看到:

http://www.wolframalpha.com/input/?i=y+%3D+1%2F+%28%281+%2B+%282%5E2%29*%28x%5E2%29%29%5E%28%282%2B1%29%2F2%29%29

以下是我一直在做的基本示例:

data(simdat)

library(spatstat)

simdat.Gest <- Gest(simdat) #Gest is a function within spatstat (explained below)

Gvalues <- simdat.Gest$rs

Rvalues <- simdat.Gest$r

GvsR_dataframe <- data.frame(R = Rvalues, G = rev(Gvalues))

themodel <- nls(rev(Gvalues) ~ (1 / (1 + (B^2)*(R^2))^((C+1)/2)), data = GvsR_dataframe, start = list(B=0.1, C=0.1), trace = FALSE)

“Gest”是'spatstat'库中的函数。它是G函数或最近邻函数,它显示独立轴上粒子之间的距离,以及在从属轴上找到最近邻粒子的概率。因此,它从y = 0开始并在y = 1时达到饱和点。

如果你绘制simdat.Gest,你会发现曲线是's'形的,这意味着它从y = 0开始并最终在y = 1。因此,我尊重矢量Gvalues,是因变量。因此,信息处于正确的方向以适合上述模型。

你可能还注意到我自动设置了A = 1.这是因为G(r)总是在1处饱和,所以我没有把它保留在公式中。

我的问题是我不断收到错误。对于上面的示例,我收到此错误:

Error in nls(rev(Gvalues) ~ (1/(1 + (B^2) * (R^2))^((C + 1)/2)), data = GvsR_dataframe,  : 
  singular gradient

我也遇到了这个错误:

Error in nls(Gvalues1 ~ (1/(1 + (B^2) * (x^2))^((C + 1)/2)), data = G_r_dataframe,  : 
  step factor 0.000488281 reduced below 'minFactor' of 0.000976562

我不知道第一个错误来自哪里。然而,第二个,我认为是因为我没有为B和C选择合适的起始值。

我希望有人可以帮我找出第一个错误的来源。另外,选择起始值以避免第二个错误的最有效方法是什么?

谢谢!

1 个答案:

答案 0 :(得分:3)

如上所述,您的问题很可能是起始值。您可以使用两种策略:

  1. 使用强力来查找起始值。请参阅包nls2以获取执行此操作的功能。
  2. 尝试对起始值进行合理猜测。 根据您的值,可以线性化模型。
  3.   

    G =(1 /(1 +(B ^ 2)*(R ^ 2))^((C + 1)/ 2))

         

    ln(G)= - (C + 1)/ 2 * ln(B ^ 2 * R ^ 2 + 1)

         

    如果B ^ 2 * R ^ 2很大,则变为大约。 ln(G)= - (C + 1)*(ln(B)+ ln(R)),它是线性的。

         

    如果B ^ 2 * R ^ 2接近1,则约为1。 ln(G)= - (C + 1)/ 2 * ln(2),它是常数。

    (请检查错误,因为足球比赛,昨晚已经很晚了。)

    提供更多信息后,

    修改: 数据看起来遵循累积分布函数。如果它像鸭子一样嘎嘎叫,它很可能是一只鸭子。实际上?Gest表示估计了CDF。

    library(spatstat)
    data(simdat)
    simdat.Gest <- Gest(simdat)
    Gvalues <- simdat.Gest$rs
    Rvalues <- simdat.Gest$r
    plot(Gvalues~Rvalues)
    
    #let's try the normal CDF
    fit <- nls(Gvalues~pnorm(Rvalues,mean,sd),start=list(mean=0.4,sd=0.2))
    summary(fit)
    lines(Rvalues,predict(fit))
    #Looks not bad. There might be a better model, but not the one provided in the question.