Formula AIC/AICc/BIC in R per GLM
Sto cercando di verificare di aver compreso come R calcola la statistica AIC, AICc (AIC corretto) e BIC per un glm()
oggetto modello (in modo da poter eseguire gli stessi calcoli sugli revoScaleR::rxGlm()
oggetti, in particolare l'AICc, che non è disponibile per impostazione predefinita )
Avevo capito che questi erano definiti come segue:
let p
= numero di parametri del modello
let n
= numero di punti dati
AIC = deviance + 2p
AICc = AIC + (2p^2 + 2p)/(n-p-1)
BIC = deviance + 2p.log(n)
Quindi ho provato a replicare questi numeri e confrontarli con le corrispondenti chiamate di funzione R. Non ha funzionato:
library(AICcmodavg) # for the AICc() function
data(mtcars)
glm_a1 <- glm(mpg ~ cyl + disp + hp + drat + wt + qsec + vs + am + gear + carb,
data = mtcars,
family = gaussian(link = "identity"),
trace = TRUE)
summary(glm_a1)
n <- nrow(glm_a1$data) # 32
p <- glm_a1$rank # 11
dev <- glm_a1$deviance# 147.49
my_AIC <- dev + 2 * p
my_AICc <- my_AIC + (2 * p^2 + 2 * p)/(n - p - 1)
my_BIC <- dev + 2 * p * log(n)
AIC(glm_a1) # 163.71
my_AIC # 169.49
AICc(glm_a1) # 180.13 (from AICcmodavg package)
my_AICc # 182.69
BIC(glm_a1) # 181.30
my_BIC # 223.74
Usando debug(AIC)
posso vedere che il calcolo è diverso. Si basa su 12 parametri (uno in più per il parametro di dispersione/scala stimato?). Anche la verosimiglianza logaritmica si ottiene utilizzando logLik()
which riporta a number -69.85
, il che mi suggerisce che la devianza del modello sarebbe -2*-69.85 = 139.71
(cosa che non è).
Qualcuno sa cosa ho fatto di sbagliato per favore? Grazie.
Risposte
nella paginaextractAIC
del manuale
- L è la verosimiglianza e edf i gradi di libertà equivalenti (cioè il numero di parametri per i normali modelli parametrici) dell'adattamento.
- Per i modelli lineari generalizzati (cioè per lm, aov e glm), -2log L è la devianza, come calcolata da deviance(fit).
- k = 2 corrisponde al tradizionale AIC, utilizzando k = log(n) si ottiene invece il BIC (Bayes IC).
così
Modifiche successive alla discussione nei commenti e all'input di @user20650
glm_a1$ranks
restituisce il numero del parametro adattato senza tener conto della varianza adattata utilizzata nelle famiglie gaussiane.?glm
statidevianza: fino a una costante, meno il doppio della probabilità logaritmica massimizzata. Dove ragionevole, la costante viene scelta in modo che un modello saturo abbia devianza zero.
Ecco perchè
-2*logLik(glm_a1) - deviance(glm_a1) = 7.78 > 0
summary(glm_a1)
restituisce la riga seguenteDispersion parameter for gaussian family taken to be 7.023544
approssimativamente la differenza tra -2 log di verosimiglianza e la devianza.
library(AICcmodavg)
#> Warning: package 'AICcmodavg' was built under R version 3.6.2
#> Warning: no function found corresponding to methods exports from 'raster' for:
#> 'wkt'
data(mtcars)
glm_a1 <- glm(mpg ~ cyl + disp + hp + drat + wt + qsec + vs + am + gear + carb,
data = mtcars,
family = gaussian(link = "identity"),
trace = TRUE)
#> Deviance = 147.4944 Iterations - 1
#> Deviance = 147.4944 Iterations - 2
(loglik <- logLik(glm_a1))
#> 'log Lik.' -69.85491 (df=12)
# thus the degrees of freedom r uses are 12 instead of 11
n <- attributes(loglik)$nobs # following user20650 recommendation
p <- attributes(loglik)$df # following user20650 recommendation
dev <- -2*as.numeric(loglik)
my_AIC <- dev + 2 * p
my_AICc <- my_AIC + (2 * p^2 + 2 * p)/(n - p - 1)
my_BIC <- dev + p * log(n)
BIC(glm_a1)
#> [1] 181.2986
my_BIC
#> [1] 181.2986
AIC(glm_a1)
#> [1] 163.7098
my_AIC
#> [1] 163.7098
AICc(glm_a1)
#> [1] 180.1309
my_AICc
#> [1] 180.1309
Funzione per calcolare queste quantità per un rxGlm()
oggetto coerente con il trattamento di glm()
(aggiustamento per la differenza di devianza "fino a una costante"):
wrc_information_criteria <- function(rx_glm) # an object created by rxGlm()
{
# add 1 to parameter count for cases where the GLM scale parameter needs to be estimated (notably Gamma/gaussian)
extra_parameter_flag <- case_when(
rx_glm$family$family == "gaussian" ~ 1,
rx_glm$family$family == "Gamma" ~ 1,
rx_glm$family$family == "poisson" ~ 0,
rx_glm$family$family == "binomial" ~ 0,
TRUE ~ 999999999
)
n <- rx_glm$nValidObs
p <- rx_glm$rank + extra_parameter_flag
dev <- rx_glm$deviance
cat("\n")
cat("n :", n, "\n")
cat("p :", p, "\n")
cat("deviance:", dev, "\n")
AIC <- dev + 2 * p
AICc <- AIC + (2 * p^2 + 2 * p)/(n - p - 1)
BIC <- dev + p * log(n)
# make a constant adjustment to AIC/AICc/BIC to give consistency with R's built in AIC/BIC functions applied to glm objects
# can do this because rxGlm() supplies AIC already (consistent with R/glm()) - as long as computeAIC = TRUE in the function call
deviance_constant_adjustment <- rx_glm$aic[1] - AIC
AIC <- AIC + deviance_constant_adjustment
AICc <- AICc + deviance_constant_adjustment
BIC <- BIC + deviance_constant_adjustment
cat("\n")
cat("AIC: ", AIC , "\n")
cat("AICc:", AICc, "\n")
cat("BIC: ", BIC , "\n")
}
Proviamolo...
data(mtcars)
glm_a1 <- glm(mpg ~ cyl + disp + hp + drat + wt + qsec + vs + am + gear + carb,
data = mtcars,
family = gaussian(link = "identity"),
trace = TRUE)
glm_b1 <- rxGlm(mpg ~ cyl + disp + hp + drat + wt + qsec + vs + am + gear + carb,
data = mtcars,
family = gaussian(link = "identity"),
verbose = 1,
computeAIC = TRUE)
AIC(glm_a1)
AICc(glm_a1)
BIC(glm_a1)
wrc_information_criteria(glm_b1) # gives same results for glm_b1 as I got for glm_a1