My general understanding of AICc is AIC is modified for small samples so that we are less "certain" about a model with few samples, and that as the sample size gets very large, the modification approaches 0 and we become more "certain" (excuse me if I use incorrect terminology). However, I've encountered an issue when using the AICc
function in the 'AICcmodavg' package to calculate AICc for a null model (y = mx + c; m = 0) I'm comparing to others. Here you can see that AICc is supposedly smaller than the AIC:
library(minpack.lm)
library(AICcmodavg)
y = c(80,251,304,482,401,141,242,221,304,243,544,669,638)
mNull <- nlsLM(y ~ c, start=c(c=mean(y)))
And when I run the AIC functions:
> AIC(mNull)
[1] 175.6431
> AICc(mNull)
[1] 169.6431
The help file says the AICc should be calculated as: −2∗log−likelihood+2∗K∗(n/(n−K−1)), but when I try to calculate it by hand:
> k=AICc(mNull, return.K = T)
> n=length(y)
> -2*as.numeric(logLik(mNull))+2*k*(n/(n-k-1))
[1] 176.8431
Meanwhile, calculating AIC by hand seems to work correctly:
> AIC(mNull)==-2*as.numeric(logLik(mNull))+2*k
[1] TRUE
So conceptually, why would AICc be less than AIC? Both n and k in this instance wouldn't lead to a negative modifier. Am I missing something?
The problem is the way that AICc.nls()
calculates the number of observations. It uses the length of the fitted values if nobs
is not supplied. In your case, this is 1 (not the length of y
). So, if you supply nobs
to AICc()
, you'll get the right answer.
library(minpack.lm)
library(AICcmodavg)
y = c(80,251,304,482,401,141,242,221,304,243,544,669,638)
mNull <- nlsLM(y ~ c, start=c(c=mean(y)))
#> Warning in .swts * attr(rhs, "gradient"): Recycling array of length 1 in vector-array arithmetic is deprecated.
#> Use c() or as.vector() instead.
fitted(mNull)
#> [1] 347.6923
#> attr(,"label")
#> [1] "Fitted values"
AICc(mNull, nobs=length(y))
#> [1] 176.8431
k=AICc(mNull, return.K = T)
n=length(y)
-2*as.numeric(logLik(mNull))+2*k*(n/(n-k-1))
#> [1] 176.8431
Created on 2023-01-24 by the reprex package (v2.0.1)
The relevant piece of code from AICcmodavg:::AICc.nls()
(where nobs=NULL
is the default) is:
if (identical(nobs, NULL)) {
n <- length(fitted(mod))
}
else {
n <- nobs
}