7

これらのデータに対して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
4

3 に答える 3

9

3パラメータの非線形モデルを4つのデータポイントに適合させることは、どのような場合でも適度に困難になりますが、この場合、データは適切に動作します。ポイント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)

私の一般的なアドバイスは、何が起こっているのかを理解し、問題を修正するのは、nls 外側にフィットgeom_smoothして、追加したい曲線を作成する方が簡単だということpredict.nlsです...

より一般的には、適切な開始パラメーターを取得する方法は、フィッティングしている関数のジオメトリと、どのパラメーターが曲線のどの側面を制御するかを理解することです。上で述べたように、cはシフトされた飽和指数曲線の最小値でありa、範囲でありb、尺度パラメーターです(の場合x=b、曲線は1-exp(-1)最小値から最大値までの約2/3であることがわかります。 )。curve()この情報を収集するには、代数と微積分を少し使用する(つまり、制限を設ける)か、関数をいじってみるのが良い方法です。

于 2012-03-13T23:16:14.443 に答える
9

これは、次のように2つの線形パラメーター(.lin1および.lin2)と1つの非線形パラメーター(b)で記述できます。

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

where .lin1 = a+cand .lin2 = -a(so a = - .lin2and c = .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"

編集:スケーリングに関するサンプル実行とコメントを追加しました。

于 2012-03-13T23:43:01.577 に答える
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 
于 2012-03-13T23:41:04.027 に答える