R: функція glm із специфікацією сімейства = “бінома” та “вага”


14

Мене дуже плутає те, як вага працює в glm з сім'єю = "двочлен". У моєму розумінні ймовірність glm з family = "binomial" визначається так:

f(y)=(nny)pny(1p)n(1y)=exp(n[ylogp1p(log(1p))]+log(nny))
де y - "частка спостережуваного успіху", а n - відома кількість випробувань.

Наскільки я розумію, ймовірність успіху p параметризується деякими лінійними коефіцієнтами β як p=p(β) а функція glm із сім'єю = "двочлен" шукає:

argmaxβilogf(yi).
Тоді цю проблему оптимізації можна спростити як:

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

Тому якщо дозволити ni=nic для всіх i=1,...,N для деякої постійної c , то також повинно бути правдою, що:
argmaxβilogf(yi)=argmaxβini[yilogp(β)1p(β)(log(1p(β)))]
З цього я подумав, що масштабування кількості випробувань 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" 

Тому я очікував, що масштабування ваги не вплине на оцінену β враховуючи частку успіху як відповіді. Однак наступні два коди повертають різні значення коефіцієнта:

 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функції (в glm.R ), що і робить роботу в R: 1) у відхиленнях залишків за допомогою функції C binomial_dev_residsfamily.c ) та 2) на етапі IWLS Cdqrlslm.c ). Я не знаю достатньо С, щоб допомогти в пошуку логіки
shadowtalker

3
Перегляньте відповіді тут .
Стати

@ssdecontrol Я читаю glm.fit у посиланні, яке ви мені дали, але я не можу знайти, де функція C "binomial_dev_resids" називається в glm.fit. Не заперечуєте, якщо на це вказуєте?
Фея

@ssdecontrol О, вибачте, я думаю, що я розумію. Кожна «сім'я» - це список, а одним із елементів є «dev.resids». Коли я набираю двочлен на консолі R, я бачу визначення біноміального об'єкта, і він має рядок: dev.resids <- функція (y, mu, wt) .Call (C_binomial_dev_resids, y, mu, wt)
FairyOnIce

Відповіді:


4

Ваш приклад просто спричиняє помилку округлення в Р. Великі ваги погано спрацьовують glm. Це правда, що масштабування wпрактично будь-якої меншої кількості, як-от 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-розкладання де - матриця проектування, а - діагональ з квадратними коренями записів, як описано тут . Тобто використовується метод Ньютона-Рафсона.WXXW

Відповідний $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"

Ми можемо повторити останню частину ще два рази, щоб побачити, що метод Ньютона-Рафсона розходиться:

> #####
> # 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

Я думаю, що ваги впливають більше, ніж аргументи для ініціалізації. За допомогою логістичної регресії Ньютон Рафсон оцінює максимальну ймовірність, яка існує і є унікальною, коли дані не розділені. Поставлення оптимізатора різних вихідних значень не призведе до різних значень, але, можливо, знадобиться більше часу, щоб дістатися до нього.
AdamO

Msgstr "Поставлення оптимізатора різних вихідних значень не досягне різних значень ..." . Ну метод Ньютона не розходиться і знаходить унікальний максимум в останньому прикладі, де я встановлюю початкові значення (див. Приклад, де я надаю mustart аргумент). Здається, це питання, пов'язане з поганою початковою оцінкою .
Бенджамін Кристофферсен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.