Skip to content

Commit 839a0aa

Browse files
Add ic_search identification for VARIMA
Resolves #446
1 parent a6e07e1 commit 839a0aa

2 files changed

Lines changed: 39 additions & 5 deletions

File tree

NEWS.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# fable (development version)
22

3+
## Improvements
4+
5+
* `VARIMA()` now supports model selection by minimising the specified
6+
information criterion (`ic`) when `p` or `q` are not uniquely specified. This
7+
identification method can be directly used with
8+
`identification = "ic_search"` (#446).
9+
310
# fable 0.5.0
411

512
## New features

R/VARIMA.R

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
train_varima <- function(.data, specials, identification = NULL, ...) {
1+
train_varima <- function(.data, specials, identification = NULL, ic = "aic", ...) {
22
# Get response variables
33
y <- invoke(cbind, lapply(unclass(.data)[measured_vars(.data)], as.double))
44

@@ -13,8 +13,10 @@ train_varima <- function(.data, specials, identification = NULL, ...) {
1313
yd <- if(d > 0) diff(y, differences = d) else y
1414

1515
if (is.null(identification)) {
16-
identification <- if ((length(p) != 1) || (length(q) != 1)) {
16+
identification <- if ((length(p) != 1) && (length(q) != 1)) {
1717
"kronecker_indices"
18+
} else if (length(p) != 1 || length(q) != 1) {
19+
"ic_search"
1820
} else {
1921
"none"
2022
}
@@ -37,6 +39,30 @@ train_varima <- function(.data, specials, identification = NULL, ...) {
3739
include.mean = "(Intercept)" %in% colnames(specials$xreg[[1]])
3840
)
3941
)
42+
} else if (identification == "ic_search") {
43+
# One of p or q is fixed; search over the free parameter using ic
44+
include.mean <- "(Intercept)" %in% colnames(specials$xreg[[1]])
45+
candidates <- expand.grid(p = p, q = q)
46+
best_fit <- NULL
47+
best_ic <- Inf
48+
for (i in seq_len(nrow(candidates))) {
49+
tryCatch({
50+
cfit <- MTS::VARMA(
51+
yd,
52+
p = candidates$p[i], q = candidates$q[i],
53+
include.mean = include.mean
54+
)
55+
crit <- cfit[[ic]]
56+
if (crit < best_ic) {
57+
best_ic <- crit
58+
best_fit <- cfit
59+
}
60+
}, error = function(e) NULL)
61+
}
62+
if (is.null(best_fit)) {
63+
cli::cli_abort("VARIMA model selection failed for all candidate orders.")
64+
}
65+
best_fit
4066
} else {
4167
if(length(p) != 1 || length(q) != 1) {
4268
cli::cli_abort("Model selection is not yet supported, please specify `p` and `q` exactly.")
@@ -90,6 +116,7 @@ specials_varima <- new_specials(
90116
#' @aliases report.VARIMA
91117
#'
92118
#' @param formula Model specification (see "Specials" section).
119+
#' @param ic The information criterion used in selecting the model. Either `"aic"` or `"bic"`.
93120
#' @param identification The identification technique used to estimate the model. Possible options include NULL (automatic selection), "kronecker_indices" (Kronecker index identification), and "scalar_components" (scalar component identification). More details can be found in the "Identification" section below.
94121
#' @param ... Further arguments for arima
95122
#'
@@ -197,15 +224,15 @@ specials_varima <- new_specials(
197224
#' generate(fit, h = 10)
198225
#' IRF(fit, h = 10, impulse = "Beer")
199226
#' @export
200-
VARIMA <- function(formula, identification = NULL, ...) {
201-
# ic <- switch(ic, aicc = "AICc", aic = "AIC", bic = "BIC")
227+
VARIMA <- function(formula, ic = c("aic", "bic"), identification = NULL, ...) {
228+
ic <- match.arg(ic)
202229
varima_model <- new_model_class("VARIMA",
203230
train = train_varima,
204231
specials = specials_varima,
205232
origin = NULL,
206233
check = all_tsbl_checks
207234
)
208-
new_model_definition(varima_model, !!enquo(formula), identification, ...)
235+
new_model_definition(varima_model, !!enquo(formula), ic = ic, identification = identification, ...)
209236
}
210237

211238
varima_order <- function(x) {

0 commit comments

Comments
 (0)