R:family =“ binomial”および“ weight”仕様のglm関数


13

family = "binomial"を使用してglmで体重がどのように機能するか、非常に混乱しています。私の理解では、family = "binomial"のglmの可能性は次のように指定されます

f(y)=(nny)pny(1p)n(1y)=exp(n[ylogp1p(log(1p))]+log(nny))
ここで、yは「観察された成功の割合」であり、nは既知の試行回数です。

私の理解では、成功の確率pは、ような線形係数とfamily = "binomial"のglm関数でパラメーター化されます: 次に、この最適化問題は次のように簡略化できます。βp=p(β)

argmaxβilogf(yi).

argmaxβilogf(yi)=argmaxβini[yilogp(β)1p(β)(log(1p(β)))]+log(niniyi)=argmaxβini[yilogp(β)1p(β)(log(1p(β)))]

したがって、すべてのi = 1、...、Nに対してni=nici=1,...,N定数cに対して許可するc場合、
argmaxβilogf(yi)=argmaxβini[yilogp(β)1p(β)(log(1p(β)))]
これから、試行回数n_iのスケーリングni定数を使用すると、成功率与えられた場合の最尤推定値には影響しませんβyi

glmのヘルプファイルには次のように書かれています。

 "For a binomial GLM prior weights are used to give the number of trials 
  when the response is the proportion of successes" 

したがって、応答の成功の割合を考えると、重みのスケーリングが推定影響を与えないと予想しました。ただし、次の2つのコードは異なる係数値を返します。β

 Y <- c(1,0,0,0) ## proportion of observed success
 w <- 1:length(Y) ## weight= the number of trials
 glm(Y~1,weights=w,family=binomial)

これにより以下が得られます。

 Call:  glm(formula = Y ~ 1, family = "binomial", weights = w)

 Coefficients:
 (Intercept)  
      -2.197     

一方、すべての重みに1000を掛けると、推定係数は異なります。

 glm(Y~1,weights=w*1000,family=binomial)

 Call:  glm(formula = Y ~ 1, family = binomial, weights = w * 1000)

 Coefficients:
 (Intercept)  
    -3.153e+15  

私はこのような他の多くの例を見ましたが、いくつかの適度な重みのスケーリングもありました。ここで何が起こっていますか?


3
価値のあることは、weights引数はglm.fit関数内の2つの場所(glm.R内)になります。これは、Rで機能します:1)C関数binomial_dev_residsfamily.c)による逸脱残差および2)Cdqrlslm.cで)IWLSステップで。ロジックをトレースするのにもっと役立つCが十分にわからない
-shadowtalker

3
ここで返信を確認してください
スタット

@ssdecontrolあなたがくれたリンクでglm.fitを読んでいますが、C関数「binomial_dev_resids」がglm.fitで呼び出されている場所を見つけることができません。それを指摘してもよろしいですか?
FairyOnIce

@ssdecontrolああ、すみません、わかりました。各「ファミリ」はリストであり、要素の1つは「dev.resids」です。Rコンソールでbinomialと入力すると、二項オブジェクトの定義が表示され、次の行があります:dev.resids <-function(y、mu、wt).Call(C_binomial_dev_resids、y、mu、wt)
FairyOnIce

回答:


3

あなたの例は、Rで丸め誤差を引き起こすだけです。大きな重みはでうまく機能しませんglmw事実上、100などの任意の小さい数でスケーリングすると、スケーリングされていないのと同じ推定値になりwます。

重み引数でより信頼性の高い動作が必要な場合svyglmは、surveyパッケージの関数を使用してみてください。

こちらをご覧ください:

    > svyglm(Y~1, design=svydesign(ids=~1, weights=~w, data=data.frame(w=w*1000, Y=Y)), family=binomial)
Independent Sampling design (with replacement)
svydesign(ids = ~1, weights = ~w, data = data.frame(w = w * 1000, 
    Y = Y))

Call:  svyglm(formula = Y ~ 1, design = svydesign(ids = ~1, weights = ~w2, 
    data = data.frame(w2 = w * 1000, Y = Y)), family = binomial)

Coefficients:
(Intercept)  
     -2.197  

Degrees of Freedom: 3 Total (i.e. Null);  3 Residual
Null Deviance:      2.601 
Residual Deviance: 2.601    AIC: 2.843

1

私はそれはで使用された初期値に降りてくると思いますglm.fitからfamily$initialize、メソッドdivergereを行いいます。私の知る限りglm.fit、 QR分解を形成することで問題を解決しますWバツバツW

関連する$intializeコードは次のとおりです。

if (NCOL(y) == 1) {
    if (is.factor(y)) 
        y <- y != levels(y)[1L]
    n <- rep.int(1, nobs)
    y[weights == 0] <- 0
    if (any(y < 0 | y > 1)) 
        stop("y values must be 0 <= y <= 1")
    mustart <- (weights * y + 0.5)/(weights + 1)
    m <- weights * y
    if (any(abs(m - round(m)) > 0.001)) 
        warning("non-integer #successes in a binomial glm!")
}

ここにglm.fit私の要点を示す簡略版があります

> #####
> # setup
> y <- matrix(c(1,0,0,0), ncol = 1)
> weights <- 1:nrow(y) * 1000
> nobs <- length(y)
> family <- binomial()
> X <- matrix(rep(1, nobs), ncol = 1) # design matrix used later
> 
> # set mu start as with family$initialize
> if (NCOL(y) == 1) {
+   n <- rep.int(1, nobs)
+   y[weights == 0] <- 0
+   mustart <- (weights * y + 0.5)/(weights + 1)
+   m <- weights * y
+   if (any(abs(m - round(m)) > 0.001)) 
+     warning("non-integer #successes in a binomial glm!")
+ }
> 
> mustart # starting value
             [,1]
[1,] 0.9995004995
[2,] 0.0002498751
[3,] 0.0001666111
[4,] 0.0001249688
> (eta <- family$linkfun(mustart))
          [,1]
[1,]  7.601402
[2,] -8.294300
[3,] -8.699681
[4,] -8.987322
> 
> #####
> # Start loop to fit
> mu <- family$linkinv(eta)
> mu_eta <- family$mu.eta(eta)
> z <- drop(eta + (y - mu) / mu_eta)
> w <- drop(sqrt(weights * mu_eta^2 / family$variance(mu = mu)))
> 
> # code is simpler here as (X^T W X) is a scalar
> X_w <- X * w
> (.coef <- drop(crossprod(X_w)^-1 * ((w * z) %*% X_w)))
[1] -5.098297
> (eta <- .coef * X)
          [,1]
[1,] -5.098297
[2,] -5.098297
[3,] -5.098297
[4,] -5.098297
> 
> # repeat a few times from "start loop to fit"

最後の部分をさらに2回繰り返して、ニュートンラプソン法が分岐することを確認できます。

> #####
> # Start loop to fit
> mu <- family$linkinv(eta)
> mu_eta <- family$mu.eta(eta)
> z <- drop(eta + (y - mu) / mu_eta)
> w <- drop(sqrt(weights * mu_eta^2 / family$variance(mu = mu)))
> 
> # code is simpler here as (X^T W X) is a scalar
> X_w <- X * w
> (.coef <- drop(crossprod(X_w)^-1 * ((w * z) %*% X_w)))
[1] 10.47049
> (eta <- .coef * X)
         [,1]
[1,] 10.47049
[2,] 10.47049
[3,] 10.47049
[4,] 10.47049
> 
> 
> #####
> # Start loop to fit
> mu <- family$linkinv(eta)
> mu_eta <- family$mu.eta(eta)
> z <- drop(eta + (y - mu) / mu_eta)
> w <- drop(sqrt(weights * mu_eta^2 / family$variance(mu = mu)))
> 
> # code is simpler here as (X^T W X) is a scalar
> X_w <- X * w
> (.coef <- drop(crossprod(X_w)^-1 * ((w * z) %*% X_w)))
[1] -31723.76
> (eta <- .coef * X)
          [,1]
[1,] -31723.76
[2,] -31723.76
[3,] -31723.76
[4,] -31723.76

で始まるweights <- 1:nrow(y)か言うなら、これは起こりませんweights <- 1:nrow(y) * 100

mustart引数を設定することにより、発散を回避できることに注意してください。例えば

> glm(Y ~ 1,weights = w * 1000, family = binomial, mustart = rep(0.5, 4))

Call:  glm(formula = Y ~ 1, family = binomial, weights = w * 1000, mustart = rep(0.5, 
    4))

Coefficients:
(Intercept)  
     -2.197  

Degrees of Freedom: 3 Total (i.e. Null);  3 Residual
Null Deviance:      6502 
Residual Deviance: 6502     AIC: 6504

重みは初期化する引数以上に影響すると思います。ロジスティック回帰では、Newton Raphsonは、データが分離されていない場合に存在し、一意である最尤を推定します。オプティマイザーに異なる開始値を指定しても、異なる値に到達することはありませんが、到達するまでに時間がかかる可能性があります。
AdamO

「オプティマイザに異なる開始値を供給すると...異なる値に到達しないだろう」。ニュートン法は発散せず、初期値を設定する最後の例で一意の最大値を見つけます(mustart 引数を指定する例を参照)。貧しい初期推定に関連する問題のようです。
ベンジャミンクリストファーセン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.