গ্লোমের সাথে লজিস্টিক রিগ্রেশন ফিটিংয়ের জন্য ডিফল্ট শুরুর মান


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 + এক্সপ্রেস (-টা))) এ আরম্ভ করে
  • start=c(0,0) y বা x মান নির্বিশেষে এটা 0 (মিউ থেকে 0.5) আরম্ভ করে।
  • start=NULL x মান নির্বিশেষে y = 1 যদি ইটা = 1.098612 (mu = 0.75) আরম্ভ করে।
  • start=NULL x মান নির্বিশেষে যদি y = 0 হয় তবে ইটা = -1.098612 (mu = 0.25) আরম্ভ করবে।

  • একবার ETA (এবং পরিণামে মিউ এবং Var (মিউ)) গণনা করা হয়েছে, wএবং zগণনা করা হয় এবং একটি কিউ সমাধানকারী পাঠিয়ে চেতনায় qr.solve(cbind(1,x) * w, z*w)

বিস্তারিত রুপ

রোল্যান্ডের মন্তব্য বন্ধ করে দিয়েছি: আমি একটি করেছি glm.fit.truncated(), যেখানে আমি কলটিতে নামলাম, এবং তারপরে এটিকে মন্তব্য glm.fitকরলাম C_Cdqrlsglm.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বেস আর এর ফাংশনটি সরাসরি লিনপ্যাক সংস্করণগুলিতে ডাকা হবে glm.fit()

সুতরাং আমরা glm.fit.truncatedবিভিন্ন প্রারম্ভিক মান স্পেসিফিকেশনগুলির জন্য দৌড়ে যাই এবং তারপরে qr.solveডাব্লু এবং জেড মানগুলির সাথে একটি কল করি এবং আমরা দেখি কীভাবে "শুরুর মান" (বা প্রথম প্রদর্শিত পুনরাবৃত্তি মানগুলি) গণনা করা হয়। রোল্যান্ড যেমন ইঙ্গিত করেছে, সুনির্দিষ্ট start=NULLবা start=c(0,0)গ্ল্যামে () ডাব্লু এবং জেড এর গণনাগুলিকে প্রভাবিত করে, এর জন্য নয়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 

শুরুর জন্য = সি (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])

গণনার জন্য ব্যবহৃত পরিমাণে outputted মানের মধ্যে নিম্নলিখিত তুলনা তাকান 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 এর সাথে মু = 0.75 (যা এটা = 1.098612 এর সাথে মিল রয়েছে) এবং y = 0 এর সাথে মি = 0.25 (যা এটা = -1.098612 এর সাথে মিল রয়েছে) সেট করে এবং এভাবে var_mu= 0.75 * 0.25 = 0.1875।

তবে এটি লক্ষণীয় আকর্ষণীয়, আমি বীজ পরিবর্তন করে সমস্ত কিছু পুনরায় পুনরায় এবং y = 0 এর জন্য মি = 0.75 এবং y = 0 এর জন্য মি = 0,5 (এবং এইভাবে অন্যান্য পরিমাণ একই স্থানে রেখেছিল)। বলতে হয়, শুরু = শূন্য একই বৃদ্ধি দেয় হয় wএবং zকি নির্বিশেষে yএবং xকারণ তারা ETA = 1.098612 গড় (mu = 0.75) আরম্ভ y = যদি 1 এবং ETA = -1.098612 গড় (mu = 0.25) y = যদি 0, হয়।

সুতরাং দেখা যাচ্ছে যে ইন্টারসেপ্ট সহগের জন্য এবং এক্স-সহগের জন্য একটি প্রারম্ভিক মান শুরু = NULL জন্য সেট করা হয়নি, বরং প্রাথমিক মান y-মান এবং এক্স-মানের সাথে পৃথক হয়ে ইটাকে দেওয়া হবে। সেখান থেকে 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
আপনার চমৎকার উত্তরের জন্য আপনাকে ধন্যবাদ, আমি আশা করি এর চেয়ে অনেক বেশি :)
অ্যাডেলা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.