3

3p ワイブル分布のスケール、形状、およびしきい値パラメーターを推定したいと考えています。

これまでに行ったことは次のとおりです。

この投稿を参照して、R で 3 パラメーターのワイブル分布をフィッティングします。

関数を使ってみた

    EPS = sqrt(.Machine$double.eps) # "epsilon" for very small numbers

llik.weibull <- function(shape, scale, thres, x)
{ 
  sum(dweibull(x - thres, shape, scale, log=T))
}

thetahat.weibull <- function(x)
{ 
  if(any(x <= 0)) stop("x values must be positive")

  toptim <- function(theta) -llik.weibull(theta[1], theta[2], theta[3], x)

  mu = mean(log(x))
  sigma2 = var(log(x))
  shape.guess = 1.2 / sqrt(sigma2)
  scale.guess = exp(mu + (0.572 / shape.guess))
  thres.guess = 1

  res = nlminb(c(shape.guess, scale.guess, thres.guess), toptim, lower=EPS)

  c(shape=res$par[1], scale=res$par[2], thres=res$par[3])
}

MASS-Package の「fitdistr」関数の引数「start」の初期値として使用できるように、ワイブル パラメータを「事前推定」します。

パラメータを 2 回推定する理由を尋ねるかもしれません...理由は、fitdistr 関数によっても推定される推定値の分散共分散行列が必要だからです。

例:

    set.seed(1)

    thres <- 450
    dat <- rweibull(1000, 2.78, 750) + thres

pre_mle <- thetahat.weibull(dat)

    my_wb <- function(x, shape, scale, thres) { 
        dweibull(x - thres, shape, scale)
    }

    ml <- fitdistr(dat, densfun = my_wb, start = list(shape = round(pre_mle[1], digits = 0), scale = round(pre_mle[2], digits = 0), 
    thres = round(pre_mle[3], digits = 0)))

    ml

     > ml
       shape        scale        thres   
       2.942548   779.997177   419.996196   (  0.152129) ( 32.194294) ( 28.729323)

     > ml$vcov
                shape       scale       thres
    shape  0.02314322    4.335239   -3.836873
    scale  4.33523868 1036.472551 -889.497580
    thres -3.83687258 -889.497580  825.374029 

これは、形状パラメーターが 1 を超える場合に非常にうまく機能します。残念ながら、私のアプローチでは、形状パラメーターが 1 よりも小さい可能性がある場合に対処する必要があります。

形状パラメータが 1 より小さい場合にこれが不可能な理由については、http ://www.weibull.com/hotwire/issue148/hottopics148.htm で説明されています。

ケース 1 では、3 つのパラメータすべてが不明であり、次のように述べられています。

「ti の最小の故障時間を tmin と定義します。このとき、γ → tmin のとき、ln(tmin - γ) → -∞。β が 1 未満の場合、(β - 1)ln(tmin - γ) は + ∞ . β, η および γ の与えられた解について, より大きな尤度値を与える別の解のセットをいつでも見つけることができます (たとえば、γ を tmin に近づけることによって). したがって、β の MLE 解はありません。 ηとγ」

これは非常に理にかなっています。まさにこの理由で、私は彼らがこのページで説明した方法でそれをやりたいと思っています.

「Weibull++ では、勾配ベースのアルゴリズムを使用して、β、η、および γ の MLE 解を見つけます。γ の範囲の上限は、tmin の 0.99 に任意に設定されます。データ セットに応じて、局所最適または 0.99tmin が γ の MLE 解として返されます。」

解が (0, .99 * tmin) の間にあるように、ガンマ (「thres」と呼ばれるコード内) の実行可能な間隔を設定したいと考えています。

この問題を解決する方法を知っている人はいますか?

関数 fitdistr では、1 つのパラメーターを制約して、制約付き MLE を実行する機会がないようです。

もう 1 つの方法は、スコア ベクトルの外積による漸近分散の推定です。スコア ベクトルは、上記で使用した関数 thetahat.weibul(x) から取得できます。しかし、外積を手動で (関数を使用せずに) 計算すると、非常に時間がかかり、制約付き ML 推定の問題は解決されません。

敬具、ティム

4

2 に答える 2

4

制約付き MLE を設定するのはそれほど難しくありません。これはbbmle::mle2;で行います。で行うこともできますがstats4::mlebbmleいくつかの追加機能があります。

より大きな問題は、許容空間の境界上にある場合、推定値のサンプリング分散を定義することが理論的に難しいことです。ワルド分散推定の背後にある理論は崩壊します。尤度プロファイリングによって信頼区間を計算することもできます...またはブートストラップすることもできます。これを行っているときにさまざまな最適化の問題に遭遇しました...特定の理由があるかどうかについてはあまり考えていません

3 パラメーターのワイブル関数をmle2使用するために再フォーマットします (x最初の引数として取りlog、引数として取ります):

dweib3 <- function(x, shape, scale, thres, log=TRUE) { 
    dweibull(x - thres, shape, scale, log=log)
}

開始関数 (わずかに再フォーマット):

weib3_start <- function(x) {
   mu <- mean(log(x))
   sigma2 <- var(log(x))
   logshape  <- log(1.2 / sqrt(sigma2))
   logscale <- mu + (0.572 / logshape)
   logthres <- log(0.5*min(x))
   list(logshape = logshape, logsc = logscale, logthres = logthres)
}

データの生成:

set.seed(1)
dat <- data.frame(x=rweibull(1000, 2.78, 750) + 450)

モデルの適合: 利便性と安定性のために対数スケールでパラメーターを適合させていますが、ゼロの境界を使用することもできます。

tmin <- log(0.99*min(dat$x))
library(bbmle)
m1 <- mle2(x~dweib3(exp(logshape),exp(logsc),exp(logthres)),
           data=dat,
           upper=c(logshape=Inf,logsc=Inf,
                   logthres=tmin),
           start=weib3_start(dat$x),
           method="L-BFGS-B")

vcov(m1)、通常、分散共分散推定値を提供する必要があります(推定値が境界上にない限り、ここではそうではありません)NaN値を提供します...さらに掘り下げないと理由がわかりません。

library(emdbook)
tmpf <- function(x,y) m1@minuslogl(logshape=x,
                                         logsc=coef(m1)["logsc"],
                                         logthres=y)
tmpf(1.1,6)
s1 <- curve3d(tmpf,
              xlim=c(1,1.2),ylim=c(5.9,tmin),sys3d="image")
with(s1,contour(x,y,z,add=TRUE))

ここに画像の説明を入力

h <- lme4:::hessian(function(x) do.call(m1@minuslogl,as.list(x)),coef(m1))
vv <- solve(h)
diag(vv) ## [1] 0.002672240 0.001703674 0.004674833
(se <- sqrt(diag(vv))) ## standard errors
## [1] 0.05169371 0.04127558 0.06837275
cov2cor(vv)
##            [,1]       [,2]       [,3]
## [1,]  1.0000000  0.8852090 -0.8778424
## [2,]  0.8852090  1.0000000 -0.9616941
## [3,] -0.8778424 -0.9616941  1.0000000

これは、対数スケール変数の分散共分散行列です。元のスケールで分散共分散行列に変換する場合は、(x_i)*(x_j) でスケーリングする必要があります (つまり、変換の導関数でexp(x))。

outer(exp(coef(m1)),exp(coef(m1))) * vv
##             logshape       logsc    logthres
## logshape  0.02312803    4.332993   -3.834145
## logsc     4.33299307 1035.966372 -888.980794
## logthres -3.83414498 -888.980794  824.831463

これがうまくいかない理由がわかりませんnumDeriv-上記の分散推定には十分注意してください。(リチャードソンの外挿が機能するには、境界に近すぎるのでしょうか?)

library(numDeriv)
hessian()
grad(function(x) do.call(m1@minuslogl,as.list(x)),coef(m1))  ## looks OK
vcov(m1)

プロファイルは問題ないように見えます... (std.errヘッシアンは可逆でないため、指定する必要があります)

pp <- profile(m1,std.err=c(0.01,0.01,0.01))
par(las=1,bty="l",mfcol=c(1,3))
plot(pp,show.points=TRUE)

ここに画像の説明を入力

confint(pp)
##              2.5 %   97.5 %
## logshape 0.9899645 1.193571
## logsc    6.5933070 6.755399
## logthres 5.8508827 6.134346

別の方法として、元のスケールでこれを行うこともできます... 1 つの可能性は、対数スケーリングを使用して適合させてから、元のスケールでこれらのパラメーターから始めて再適合させることです。

wstart <- as.list(exp(unlist(weib3_start(dat$x))))
names(wstart) <- gsub("log","",names(wstart))
m2 <- mle2(x~dweib3(shape,sc,thres),
           data=dat,
           lower=c(shape=0.001,sc=0.001,thres=0.001),
           upper=c(shape=Inf,sc=Inf,
                   thres=exp(tmin)),
           start=wstart,
           method="L-BFGS-B")
vcov(m2)
##             shape          sc       thres
## shape  0.02312399    4.332057   -3.833264
## sc     4.33205658 1035.743511 -888.770787
## thres -3.83326390 -888.770787  824.633714
all.equal(unname(coef(m2)),unname(exp(coef(m1))),tol=1e-4)

上記の値とほぼ同じです。

パラメーターを制限するためにもう少し注意を払えば、小さな形状に適合させることができますが、今度はしきい値の境界に到達してしまい、分散計算に多くの問題が発生します。

set.seed(1)
dat <- data.frame(x = rweibull(1000, .53, 365) + 100)
tmin <- log(0.99 * min(dat$x))
m1 <- mle2(x ~ dweib3(exp(logshape), exp(logsc), exp(logthres)),
   lower=c(logshape=-10,logscale=0,logthres=0),
   upper = c(logshape = 20, logsc = 20, logthres = tmin),
   data = dat, 
   start = weib3_start(dat$x), method = "L-BFGS-B") 

dweibull打ち切りデータの場合は、pweibull;に置き換える必要があります。いくつかのヒントについては、3 パラメーターのワイブル累積分布関数で最尤推定を実行する際のエラーを参照してください。

于 2016-07-31T23:15:00.833 に答える