डिफ़ॉल्ट प्रारंभिक मूल्य चमक के साथ लॉजिस्टिक प्रतिगमन फिटिंग


10

मैं सोच रहा हूँ कि कैसे डिफ़ॉल्ट प्रारंभिक मान निर्दिष्ट हैं glm

यह पोस्ट बताता है कि डिफ़ॉल्ट मान शून्य के रूप में सेट किए गए हैं। यह एक कहता है कि इसके पीछे एक एल्गोरिथ्म है, हालांकि प्रासंगिक लिंक टूट गया है।

मैंने एल्गोरिथ्म ट्रेस के साथ सरल लॉजिस्टिक प्रतिगमन मॉडल को फिट करने की कोशिश की:

set.seed(123)

x <- rnorm(100)
p <- 1/(1 + exp(-x))
y <- rbinom(100, size = 1, prob = p)

# to see parameter estimates in each step
trace(glm.fit, quote(print(coefold)), at = list(c(22, 4, 8, 4, 19, 3)))

शुरुआती मूल्यों के विनिर्देशन के बिना, पहला:

glm(y ~ x, family = "binomial")

Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  .... step 22,4,8,4,19,3 
NULL
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  .... step 22,4,8,4,19,3 
[1] 0.386379 1.106234
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  .... step 22,4,8,4,19,3 
[1] 0.3991135 1.1653971
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  .... step 22,4,8,4,19,3 
[1] 0.3995188 1.1669508

पहले चरण में, प्रारंभिक मूल्य हैं NULL

दूसरा, मैंने शुरू किया मान शून्य होने के लिए:

glm(y ~ x, family = "binomial", start = c(0, 0))

Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  .... step 22,4,8,4,19,3 
[1] 0 0
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  .... step 22,4,8,4,19,3 
[1] 0.3177530 0.9097521
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  .... step 22,4,8,4,19,3 
[1] 0.3909975 1.1397163
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  .... step 22,4,8,4,19,3 
[1] 0.3994147 1.1666173
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  .... step 22,4,8,4,19,3 
[1] 0.3995191 1.1669518

और हम देख सकते हैं कि पहले और दूसरे दृष्टिकोण के बीच पुनरावृत्तियों में अंतर है।

निर्दिष्ट प्रारंभिक मूल्यों को देखने के लिए glmमैंने केवल एक पुनरावृत्ति के साथ मॉडल फिट करने की कोशिश की:

glm(y ~ x, family = "binomial", control = list(maxit = 1))

Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  .... step 22,4,8,4,19,3 
NULL

Call:  glm(formula = y ~ x, family = "binomial", control = list(maxit = 1))

Coefficients:
(Intercept)            x  
     0.3864       1.1062  

Degrees of Freedom: 99 Total (i.e. Null);  98 Residual
Null Deviance:      134.6 
Residual Deviance: 115  AIC: 119

मापदंडों का अनुमान (आश्चर्यजनक रूप से नहीं) दूसरे पुनरावृत्ति में पहले दृष्टिकोण के अनुमानों के अनुरूप है यानी, [1] 0.386379 1.106234 इन मूल्यों को प्रारंभिक मानों के रूप में सेट करना पहले दृष्टिकोण के समान पुनरावृत्तियों अनुक्रम की ओर जाता है:

glm(y ~ x, family = "binomial", start = c(0.386379, 1.106234))

Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  .... step 22,4,8,4,19,3 
[1] 0.386379 1.106234
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  .... step 22,4,8,4,19,3 
[1] 0.3991135 1.1653971
Tracing glm.fit(x = structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  .... step 22,4,8,4,19,3 
[1] 0.3995188 1.1669508

तो सवाल यह है कि इन मूल्यों की गणना कैसे की जाती है?


यह जटिल है। यदि आप startमूल्यों की आपूर्ति करते हैं, तो उनका उपयोग गणना में किया जाता है जो C_Cdqrlsदिनचर्या में पारित हो जाता है। यदि आप नहीं करते हैं, तो पास किए गए मानों की गणना की जाती है (कॉल सहित eval(binomial()$initialize)), लेकिन glm.fitकभी भी स्पष्ट रूप से मानों की गणना नहीं करता है start। एक या दो घंटे का समय लें और glm.fitकोड का अध्ययन करें ।
रोलैंड

टिप्पणी के लिये आपका धन्यवाद। मैंने glm.fitकोड का अध्ययन करने की कोशिश की लेकिन मुझे अभी भी कोई सुराग नहीं है कि प्रारंभिक मूल्यों की गणना कैसे की जाती है।
अदला

जवाबों:


6

टी एल; डॉ

  • start=c(b0,b1)एटा को b0+x*b1(1 / (1 + ऍक्स्प (-eta)) के लिए ईटा )
  • start=c(0,0) y या x मान की परवाह किए बिना, ईटा को 0 (mu से 0.5) तक इनिशियलाइज़ करता है।
  • start=NULL x मान की परवाह किए बिना, अगर = 1 है, तो eta = 1.098612 (mu = 0.75) को इनिशियलाइज़ करता है।
  • start=NULL यदि x मान की परवाह किए बिना, ya = 0, तो eta = -1.098612 (mu = 0.25) को प्रारंभ करता है।

  • एक बार एटा (और परिणामस्वरूप म्यू और वार (म्यू)) की गणना की गई है, wऔर zउनकी गणना क्यूआर सॉल्वर में की जाती है, की भावना में की जाती है qr.solve(cbind(1,x) * w, z*w)

लंबा फार्म

रोलांड की टिप्पणी का निर्माण: मैंने एक glm.fit.truncated(), जहां मैंने कॉल glm.fitकरने के लिए नीचे ले जाया C_Cdqrls, और फिर टिप्पणी की। glm.fit.truncatedआउटपुट zऔर wमान (साथ ही गणना करने के लिए उपयोग की जाने वाली मात्राओं के मूल्यों ) zऔर wफिर C_Cdqrlsकॉल को पास किया जाएगा :

## call Fortran code via C wrapper
fit <- .Call(C_Cdqrls, x[good, , drop = FALSE] * w, z * w,
             min(1e-7, control$epsilon/1000), check=FALSE) 

अधिक C_Cdqrls यहाँ के बारे में पढ़ा जा सकता है । सौभाग्य से, qr.solveबेस आर में फ़ंक्शन सीधे LINPACK संस्करणों में टैप करता है जिसे अंदर बुलाया जा रहा है glm.fit()

इसलिए हम glm.fit.truncatedअलग-अलग शुरुआती मूल्य विनिर्देशों के लिए दौड़ते हैं , और फिर qr.solveडब्ल्यू और जेड मूल्यों के साथ एक कॉल करते हैं, और हम देखते हैं कि "शुरुआती मूल्य" (या पहले प्रदर्शित पुनरावृत्ति मूल्यों) की गणना कैसे की जाती है। रोलाण्ड, संकेत दिया निर्दिष्ट करने के रूप में start=NULLया start=c(0,0)GLM में () के लिए डब्ल्यू और z, गणना को प्रभावित करता है नहीं के लिए start

शुरुआत के लिए = NULL: zएक वेक्टर है जहां तत्वों का मान 2.431946 या -2.431946 है और wएक वेक्टर है जहां सभी तत्व 0.4330127 हैं:

start.is.null <- glm.fit.truncated(x,y,family=binomial(), start=NULL)
start.is.null
w <- start.is.null$w
z <- start.is.null$z
## if start is NULL, the first displayed values are:
qr.solve(cbind(1,x) * w, z*w)  
# > qr.solve(cbind(1,x) * w, z*w)  
#                 x 
# 0.386379 1.106234 

शुरुआत के लिए = c (0,0): zएक वेक्टर है जहां तत्वों का मूल्य 2 या -2 होता है और wएक वेक्टर है जहां सभी तत्व 0.5 होते हैं:

## if start is c(0,0)    
start.is.00 <- glm.fit.truncated(x,y,family=binomial(), start=0)
start.is.00
w <- start.is.00$w
z <- start.is.00$z
## if start is c(0,0), the first displayed values are:    
qr.solve(cbind(1,x) * w, z*w)  
# > qr.solve(cbind(1,x) * w, z*w)  
#                   x 
# 0.3177530 0.9097521 

ताकि सब कुछ ठीक है और अच्छा है, लेकिन हम गणना कैसे करते हैं wऔर z? नीचे glm.fit.truncated()हम देखते हैं

z <- (eta - offset)[good] + (y - mu)[good]/mu.eta.val[good]
w <- sqrt((weights[good] * mu.eta.val[good]^2)/variance(mu)[good])

गणना zऔर उपयोग की जाने वाली मात्राओं के आउटपुट मानों के बीच निम्नलिखित तुलनाओं को देखें w:

cbind(y, start.is.null$mu, start.is.00$mu)
cbind(y, start.is.null$eta, start.is.00$eta)
cbind(start.is.null$var_mu, start.is.00$var_mu)
cbind(start.is.null$mu.eta.val, start.is.00$mu.eta.val)

ध्यान दें कि केवल मान 0.5 के साथ start.is.00वेक्टर होगा muक्योंकि एटा 0 और म्यू (एटा) = 1 / (1 + एक्सप (-0)) = 0.5 पर सेट है। start.is.nully = 1 के साथ सेट करने वालों को mu = 0.75 (जो कि eta = 1.098612 से मेल खाता है) और y = 0 के साथ mu = 0.25 (जो eta = -1.098612 से मेल खाती है), और इस प्रकार var_mu= 0.75 * 0.25 = 0.1875 हो जाते हैं।

हालांकि, यह नोट करना दिलचस्प है, कि मैंने बीज और रेनन को सब कुछ बदल दिया और y = 1 के लिए म्यू = 0.75 और y = 0 के लिए म्यू = 0.25 (और इस प्रकार अन्य मात्राएं समान रहीं)। यही कारण है, का कहना है कि शुरू = शून्य ही को जन्म देता है करने के लिए है wऔर zक्या की परवाह किए बिना yऔर xक्योंकि वे ईटा = 1.098612 (म्यू = 0.75) को प्रारंभ y = अगर 1 और ईटा = -१.०,९८,६१२ (म्यू = 0.25) y = यदि 0, कर रहे हैं।

तो ऐसा प्रतीत होता है कि इंटरसेप्ट गुणांक के लिए और X- गुणांक के लिए एक प्रारंभिक मूल्य स्टार्ट = NULL के लिए सेट नहीं है, बल्कि एक्स-वैल्यू के स्वतंत्र और स्वतंत्र होने के आधार पर एटा को प्रारंभिक मान दिए गए हैं। वहां से wऔर zगणना की जाती है, फिर xqr.solver के साथ भेजी जाती है।

ऊपर दिए गए अंशों से पहले चलने वाला कोड :

set.seed(123)

x <- rnorm(100)
p <- 1/(1 + exp(-x))
y <- rbinom(100, size = 1, prob = p)


glm.fit.truncated <- function(x, y, weights = rep.int(1, nobs), 
start = 0,etastart = NULL, mustart = NULL, 
offset = rep.int(0, nobs),
family = binomial(), 
control = list(), 
intercept = TRUE,
singular.ok = TRUE
){
control <- do.call("glm.control", control)
x <- as.matrix(x)
xnames <- dimnames(x)[[2L]]
ynames <- if(is.matrix(y)) rownames(y) else names(y)
conv <- FALSE
nobs <- NROW(y)
nvars <- ncol(x)
EMPTY <- nvars == 0
## define weights and offset if needed
if (is.null(weights))
  weights <- rep.int(1, nobs)
if (is.null(offset))
  offset <- rep.int(0, nobs)

## get family functions:
variance <- family$variance
linkinv  <- family$linkinv
if (!is.function(variance) || !is.function(linkinv) )
  stop("'family' argument seems not to be a valid family object", call. = FALSE)
dev.resids <- family$dev.resids
aic <- family$aic
mu.eta <- family$mu.eta
unless.null <- function(x, if.null) if(is.null(x)) if.null else x
valideta <- unless.null(family$valideta, function(eta) TRUE)
validmu  <- unless.null(family$validmu,  function(mu) TRUE)
if(is.null(mustart)) {
  ## calculates mustart and may change y and weights and set n (!)
  eval(family$initialize)
} else {
  mukeep <- mustart
  eval(family$initialize)
  mustart <- mukeep
}
if(EMPTY) {
  eta <- rep.int(0, nobs) + offset
  if (!valideta(eta))
    stop("invalid linear predictor values in empty model", call. = FALSE)
  mu <- linkinv(eta)
  ## calculate initial deviance and coefficient
  if (!validmu(mu))
    stop("invalid fitted means in empty model", call. = FALSE)
  dev <- sum(dev.resids(y, mu, weights))
  w <- sqrt((weights * mu.eta(eta)^2)/variance(mu))
  residuals <- (y - mu)/mu.eta(eta)
  good <- rep_len(TRUE, length(residuals))
  boundary <- conv <- TRUE
  coef <- numeric()
  iter <- 0L
} else {
  coefold <- NULL
  eta <-
    if(!is.null(etastart)) etastart
  else if(!is.null(start))
    if (length(start) != nvars)
      stop(gettextf("length of 'start' should equal %d and correspond to initial coefs for %s", nvars, paste(deparse(xnames), collapse=", ")),
           domain = NA)
  else {
    coefold <- start
    offset + as.vector(if (NCOL(x) == 1L) x * start else x %*% start)
  }
  else family$linkfun(mustart)
  mu <- linkinv(eta)
  if (!(validmu(mu) && valideta(eta)))
    stop("cannot find valid starting values: please specify some", call. = FALSE)
  ## calculate initial deviance and coefficient
  devold <- sum(dev.resids(y, mu, weights))
  boundary <- conv <- FALSE

  ##------------- THE Iteratively Reweighting L.S. iteration -----------
  for (iter in 1L:control$maxit) {
    good <- weights > 0
    varmu <- variance(mu)[good]
    if (anyNA(varmu))
      stop("NAs in V(mu)")
    if (any(varmu == 0))
      stop("0s in V(mu)")
    mu.eta.val <- mu.eta(eta)
    if (any(is.na(mu.eta.val[good])))
      stop("NAs in d(mu)/d(eta)")
    ## drop observations for which w will be zero
    good <- (weights > 0) & (mu.eta.val != 0)

    if (all(!good)) {
      conv <- FALSE
      warning(gettextf("no observations informative at iteration %d",
                       iter), domain = NA)
      break
    }
    z <- (eta - offset)[good] + (y - mu)[good]/mu.eta.val[good]
    w <- sqrt((weights[good] * mu.eta.val[good]^2)/variance(mu)[good])
    # ## call Fortran code via C wrapper
    # fit <- .Call(C_Cdqrls, x[good, , drop = FALSE] * w, z * w,
    #              min(1e-7, control$epsilon/1000), check=FALSE)
    # 

    #print(iter)
    #print(z)
    #print(w)
  }


  }
  return(list(z=z, w=w, mustart=mustart, etastart=etastart, eta=eta, offset=offset, mu=mu, mu.eta.val=mu.eta.val,
              weight=weights, var_mu=variance(mu)))

}

2
आपके उत्कृष्ट उत्तर के लिए धन्यवाद, यह बहुत परे है मैं उम्मीद कर रहा था :)
एडेला
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.