2012-03-13 51 views
7

我不明白爲什麼我不能有這些數據的nls函數。 我已經嘗試了很多不同的起始值,而且我總是有同樣的錯誤。如何找到nls函數的良好開始值?

這是我一直在做:

expFct2 = function (x, a, b,c) 
{ 
    a*(1-exp(-x/b)) + c 
} 
vec_x <- c(77.87,87.76,68.6,66.29) 
vec_y <- c(1,1,0.8,0.6) 
dt <- data.frame(vec_x=vec_x,vec_y=vec_y) 
ggplot(data = dt,aes(x = vec_x, y = vec_y)) + geom_point() + 
    geom_smooth(data=dt, method="nls", formula=y~expFct2(x, a, b, c), 
     se=F, start=list(a=1, b=75, c=-5) 

我一直這個錯誤:

Error in method(formula, data = data, weights = weight, ...) : 
    singular gradient 

回答

8

這可以通過兩個線性參數(.lin1.lin2)和一個非線性參數(b)這樣被寫成:

a*(1-exp(-x/b)) + c 
= (a+c) - a * exp(-x/b) 
= .lin1 + .lin2 * exp(-x/b) 

其中.lin1 = a+c.lin2 = -a(所以a = - .lin2c = .lin1 + .lin2)這讓我們使用"plinear",其僅需要指定單個非線性參數的起始值(消除了如何設置其他參數的起始值的問題),並且儘管收斂從該溶液的是遠的b=75Ë起始值:

nls(y ~ cbind(1, exp(-x/b)), start = list(b = 75), alg = "plinear") 

下面是一個運行的結果,從中我們可以從.lin2尺寸,這個問題被嚴重按比例參見:

> x <- c(77.87,87.76,68.6,66.29) 
> y <- c(1,1,0.8,0.6) 
> nls(y ~ cbind(1, exp(-x/b)), start = list(b = 75), alg = "plinear") 
Nonlinear regression model 
    model: y ~ cbind(1, exp(-x/b)) 
    data: parent.frame() 
     b  .lin1  .lin2 
3.351e+00 1.006e+00 -1.589e+08 
residual sum-of-squares: 7.909e-05 

Number of iterations to convergence: 9 
Achieved convergence tolerance: 9.887e-07 
> R.version.string 
[1] "R version 2.14.2 Patched (2012-02-29 r58660)" 
> win.version() 
[1] "Windows Vista (build 6002) Service Pack 2" 

編輯:添加示例運行和縮放評論。

+0

用這個我得到b .lin1 .lin2 3.351e + 00 1.006e + 00 -1.589e + 08當我計算a和c時,我有:nls(vec_y〜expFct2 (vec_x,a,b,c),start = list(a = 1.589e + 08,b = 75,c = -158899999),control = nls.control(maxiter = 200))我有這個錯誤:nlsModel (formula,mf,start,wts):初始參數估計的奇異梯度矩陣。我不明白爲什麼 – Tali 2012-03-19 10:20:55

+0

通常,在運行非線性優化時,您希望參數大致處於相同的幅度範圍內。已添加示例運行顯示問題。變換你的參數,這樣不會發生。 「線性」方法的優點在於它相對清晰的如何轉換爲線性,而現在我們看到了它給我們提供的信息,我們必須進一步改進我們的參數和哪些參數。文森特已經展示瞭如何做到這一點。 – 2012-03-19 11:14:49

+0

謝謝,我現在明白了 – Tali 2012-03-19 11:25:56

9

擬合三參數非線性模型對四個數據點是要在適度挑戰無論如何,儘管在這種情況下數據表現良好。點#1是你的c參數(-5)的起始值是離開的。繪製與您的起始參數相對應的曲線圖片(參見下文)將有助於您理解這一點(因此可以認識到,您獲得的曲線最小範圍爲c,最大範圍爲c+a,數據範圍爲0.6到1 ...)

但是,即使有更好的開始猜測,我發現自己對控制參數感到惱火(即control=nls.control(maxiter=200)),其次是更多的警告 - nls不以其穩健性而聞名。所以我嘗試了SSasympOff模型,它實現了您想要適合的曲線的自啓動版本。

start1 <- list(a=1, b=75, c=-5) 
start2 <- list(a=0.5, b=75, c=0.5) ## a better guess 

pfun <- function(params) { 
    data.frame(vec_x=60:90, 
      vec_y=do.call(expFct2,c(list(x=60:90),params))) 
} 
library(ggplot2) 
ggplot(data = dt,aes(x = vec_x, y = vec_y)) + geom_point() + 
    geom_line(data=pfun(start1))+ 
    geom_line(data=pfun(start2),colour="red")+ 
    geom_smooth(data=dt, method="nls", formula=y~SSasympOff(x, a, b, c), 
       se=FALSE) 

我一般建議是,它更容易弄清楚發生了什麼事情,如果你適合nlsgeom_smooth解決問題,構建你想用predict.nls添加的曲線......

更一般地說,獲得良好啓動參數的方法是瞭解您正在擬合的函數的幾何結構,以及哪些參數控制曲線的哪些方面。正如我上面提到的,c是移位飽和指數曲線的最小值,a是範圍,而b是一個刻度參數(可以看出當x=b,曲線是1-exp(-1)或約2/3的方式最小到最大)。無論是代數和微積分(即有限制)還是玩弄curve()函數,都是收集這些信息的好方法。

+0

謝謝你的回答。我不知道SSasympOff函數。但是我怎樣才能找到a,b和c的值來實現我的功能呢?如果我在做getInitial(vec_y〜SSasympOff(vec_x,0.5,75,0.5),data = dt),這不是我的方程的值。 – Tali 2012-03-19 09:03:30

2

我很努力地找到對你的參數的解釋: a是一個斜率,b是收斂速度,a + c是極限,但c本身似乎沒有多大意義。 重新設置功能後,問題消失。

f <- function (x, a,b,c) a + c * exp(-x/abs(b)) 
nls(y~f(x, a, b, c), data=dt, start=list(a=1, b=75, c=-5), trace=TRUE) 

然而,c值看起來非常,非常高: 這大概就是爲什麼最初的模型沒有收斂。

Nonlinear regression model 
    model: y ~ f(x, a, b, c) 
    data: dt 
     a   b   c 
1.006e+00 3.351e+00 -1.589e+08 
residual sum-of-squares: 7.909e-05 

Number of iterations to convergence: 9 
Achieved convergence tolerance: 2.232e-06 

這是另一個更合理的相同功能的參數化。

g <- function (x, a,b,c) a * (1-exp(-(x-c)/abs(b))) 
nls(y~g(x, a, b, c), data=dt, start=list(a=1, b=75, c=-5), trace=TRUE) 

Nonlinear regression model 
    model: y ~ g(x, a, b, c) 
    data: dt 
    a  b  c 
1.006 3.351 63.257 
residual sum-of-squares: 7.909e-05 

Number of iterations to convergence: 10 
Achieved convergence tolerance: 1.782e-06 
+0

好吧,但是如何從這裏,我可以找到我的函數的開始值,因爲如果我像這樣做:nls(vec_y〜expFct2(vec_x,a,b,c), start = list(a = 1.006 ,b = 3.351,c = 63.257),控制= nls.control(maxiter = 200),我有這個錯誤:nlsModel(公式,mf,start,wts)中的錯誤: 初始參數估計的奇異梯度矩陣 – Tali 2012-03-19 09:25:50

+0

我的建議首先要分開各種參數 秒,更重要的是 的影響,以確保我們所尋找的最佳值具有相同的數量級 (如果其中一個的數量是100,000,000倍大於其他人, 你應該期待的問題)。 這個修復後ametrization,優化對初始值更加敏感。 – 2012-03-19 09:51:46

+0

你是怎麼從這個a *(1-exp(-x/b))+ c得到這個a *(1-exp( - (x-c)/ abs(b)))? – Tali 2012-03-19 10:41:59