Skip to content

Commit

Permalink
update models
Browse files Browse the repository at this point in the history
  • Loading branch information
loelschlaeger committed Apr 25, 2024
1 parent fc8d3d3 commit d635f5d
Show file tree
Hide file tree
Showing 30 changed files with 250 additions and 153 deletions.
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ vignettes/figs/
^CRAN-SUBMISSION$
^sticker$
^development_packages\.R$
^fit_models\.R$
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Imports:
MASS,
oeli (>= 0.3.0),
padr,
pracma,
progress,
Rcpp,
stats,
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export(reorder_states)
export(set_controls)
export(simulate_hmm)
export(viterbi)
importFrom(MASS,ginv)
importFrom(Rcpp,evalCpp)
importFrom(checkmate,assert_integerish)
importFrom(checkmate,assert_number)
Expand Down Expand Up @@ -78,6 +79,7 @@ importFrom(graphics,points)
importFrom(graphics,text)
importFrom(graphics,title)
importFrom(padr,pad)
importFrom(pracma,hessian)
importFrom(stats,AIC)
importFrom(stats,BIC)
importFrom(stats,acf)
Expand Down
12 changes: 6 additions & 6 deletions R/compute_ci.R
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,21 @@ compute_ci <- function(x, alpha = 0.05) {
}

### compute confidence intervals using the inverse Hessian approach
inv_fisher <- 1 / x$hessian_diagonal
sds <- suppressWarnings(sqrt(inv_fisher))
inverse_fisher <- x$inverse_fisher
sds <- suppressWarnings(sqrt(inverse_fisher))
z_alpha <- stats::qnorm(p = 1 - alpha / 2)
lower_limit <- x$estimate - z_alpha * sds
upper_limit <- x$estimate + z_alpha * sds

### if negative variance, replace by NA_real_
bad_inv_fisher <- which(
bad_inverse_fisher <- which(
!vapply(
inv_fisher, checkmate::test_number, logical(1), na.ok = FALSE,
inverse_fisher, checkmate::test_number, logical(1), na.ok = FALSE,
finite = TRUE, lower = 0
)
)
lower_limit[bad_inv_fisher] <- NA_real_
upper_limit[bad_inv_fisher] <- NA_real_
lower_limit[bad_inverse_fisher] <- NA_real_
upper_limit[bad_inverse_fisher] <- NA_real_

### create and return output
out <- lapply(
Expand Down
82 changes: 33 additions & 49 deletions R/data_and_models.R
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@
#' fit = list("runs" = 10, "gradtol" = 1e-6, "steptol" = 1e-6)
#' )
#' dax_data <- prepare_data(controls)
#' dax_model_2n <- fit_model(dax_data)
#' dax_model_2n <- fit_model(dax_data, seed = 1)
#' dax_model_2n <- decode_states(dax_model_2n)
#' dax_model_2n <- compute_residuals(dax_model_2n)
#' summary(dax_model_2n)
Expand All @@ -178,22 +178,26 @@
#' @details
#' The model was estimated via:
#' \preformatted{
#' # TODO refit
#' controls <- set_controls(
#' states = 3,
#' sdds = "t",
#' data = list(
#' file = dax,
#' date_column = "Date",
#' data_column = "Close",
#' logreturns = TRUE,
#' from = "2000-01-03",
#' to = "2022-12-31"
#' ),
#' fit = list("runs" = 100, "gradtol" = 1e-6, "steptol" = 1e-6)
#' states = 3,
#' sdds = "t",
#' data = list(
#' file = dax,
#' date_column = "Date",
#' data_column = "Close",
#' logreturns = TRUE,
#' from = "2000-01-03",
#' to = "2022-12-31"
#' ),
#' fit = list(
#' runs = 100,
#' iterlim = 300,
#' gradtol = 1e-6,
#' steptol = 1e-6
#' )
#' )
#' dax_data <- prepare_data(controls)
#' dax_model_3t <- fit_model(dax_data)
#' dax_model_3t <- fit_model(dax_data, seed = 1, ncluster = 10)
#' dax_model_3t <- decode_states(dax_model_3t)
#' dax_model_3t <- compute_residuals(dax_model_3t)
#' summary(dax_model_3t)
Expand All @@ -217,7 +221,7 @@
#' @details
#' The model was estimated via:
#' \preformatted{
#' # TODO refit
#' try({
#' controls <- set_controls(
#' hierarchy = TRUE,
#' states = c(2, 2),
Expand All @@ -230,11 +234,18 @@
#' logreturns = c(TRUE, TRUE)
#' ),
#' fit = list(
#' runs = 200
#' runs = 200,
#' iterlim = 300,
#' gradtol = 1e-6,
#' steptol = 1e-6
#' )
#' )
#' dax_vw_data <- prepare_data(controls)
#' dax_vw_model <- fit_model(dax_vw_data)
#' dax_vw_model <- fit_model(dax_vw_data, seed = 1, ncluster = 10)
#' dax_vw_model <- decode_states(dax_vw_model)
#' dax_vw_model <- compute_residuals(dax_vw_model)
#' summary(dax_vw_model)
#' })
#' }
#'
#' @format An object of class \code{\link{fHMM_model}}.
Expand All @@ -254,7 +265,6 @@
#' @details
#' The model was estimated via:
#' \preformatted{
#' # TODO refit
#' controls <- set_controls(
#' hierarchy = TRUE,
#' states = c(3, 2),
Expand All @@ -274,7 +284,7 @@
#' )
#' )
#' unemp_spx_data <- prepare_data(controls)
#' unemp_spx_model_3_2 <- fit_model(unemp_spx_data)
#' unemp_spx_model_3_2 <- fit_model(unemp_spx_data, seed = 1)
#' }
#'
#' @format An object of class \code{\link{fHMM_model}}.
Expand All @@ -294,10 +304,10 @@
#' The model was estimated via:
#' \preformatted{
#' controls <- set_controls(
#' states = 2,
#' sdds = "gamma(mu = 1|2)",
#' horizon = 200,
#' fit = list("runs" = 10)
#' states = 2,
#' sdds = "gamma(mu = 1|2)",
#' horizon = 200,
#' runs = 10
#' )
#' pars <- fHMM_parameters(
#' controls = controls,
Expand All @@ -317,29 +327,3 @@
#' @keywords model
"sim_model_2gamma"

#' Simulated 4-state HMM with log-normal distributions
#'
#' @description
#' A pre-computed 4-state HMM with state-dependent log-normal distributions
#' on \code{1000} simulated observations.
#'
#' @usage data("sim_model_4lnorm")
#'
#' @details
#' The model was estimated via:
#' \preformatted{
#' # TODO refit
#' controls <- set_controls(
#' states = 4,
#' sdds = "lognormal",
#' horizon = 1000,
#' fit = list(runs = 50)
#' )
#' data_sim <- prepare_data(controls, seed = 1)
#' sim_model_4lnorm <- fit_model(data_sim, seed = 1)
#' }
#'
#' @format An object of class \code{\link{fHMM_model}}.
#'
#' @keywords model
"sim_model_4lnorm"
2 changes: 2 additions & 0 deletions R/fHMM-package.R
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@
#' @importFrom grDevices col2rgb
#' @importFrom grDevices colorRampPalette
#' @importFrom grDevices rgb
#' @importFrom MASS ginv
#' @importFrom padr pad
#' @importFrom pracma hessian
#' @importFrom Rcpp evalCpp
#' @importFrom stats acf
#' @importFrom stats AIC
Expand Down
12 changes: 6 additions & 6 deletions R/fHMM_model.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@
#' A \code{numeric} vector, the model log-likelihoods in all optimization runs.
#' @param gradient
#' A \code{numeric} vector, the gradient at the optimum.
#' @param hessian_diagonal
#' A \code{numeric} vector, the diagonal elements of the approximated Hessian at
#' the optimum.
#' @param inverse_fisher
#' A \code{numeric} vector, the inverse Fisher information for each parameter.
#' @param decoding
#' A \code{numeric} vector, the decoded time series.
#' @param alpha
Expand All @@ -41,7 +40,7 @@

fHMM_model <- function(
data, estimate, nlm_output, estimation_time, ll, lls, gradient,
hessian_diagonal, decoding
inverse_fisher, decoding
) {
structure(
list(
Expand All @@ -52,8 +51,9 @@ fHMM_model <- function(
"ll" = ll,
"lls" = lls,
"gradient" = gradient,
"hessian_diagonal" = hessian_diagonal,
"decoding" = NULL
"inverse_fisher" = inverse_fisher,
"decoding" = NULL,
"system_information" = oeli::system_information()
),
class = "fHMM_model"
)
Expand Down
19 changes: 15 additions & 4 deletions R/fit_model.R
Original file line number Diff line number Diff line change
Expand Up @@ -200,14 +200,25 @@ fit_model <- function(
)
}

### compute diagonal elements of Hessian
### compute inverse Fisher information
if (verbose) message("Approximating Hessian...")
hessian_diagonal <- suppressWarnings(pracma::hessdiag(
fisher <- pracma::hessdiag(
f = target,
x = mods[[which.max(lls)]][["estimate"]],
observations = data[["data"]],
controls = data[["controls"]]
))
)
if (all(fisher > 0)) {
inverse_fisher <- 1 / fisher
} else {
hessian <- suppressWarnings(pracma::hessian(
f = target,
x0 = mods[[which.max(lls)]][["estimate"]],
observations = data[["data"]],
controls = data[["controls"]]
))
inverse_fisher <- diag(MASS::ginv(hessian))
}

### final message
if (verbose) message("Fitting completed!")
Expand All @@ -228,7 +239,7 @@ fit_model <- function(
ll = ll,
lls = lls,
gradient = mod$gradient,
hessian_diagonal = hessian_diagonal,
inverse_fisher = inverse_fisher,
decoding = NULL
)

Expand Down
2 changes: 1 addition & 1 deletion R/reorder_states.R
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ reorder_states <- function(x, state_order = "mean") {
permut_all <- diag(length(x$estimate))[match, ]
x$estimate <- parUncon
x$gradient <- as.vector(permut_all %*% x$gradient)
x$hessian_diagonal <- as.vector(permut_all %*% x$hessian_diagonal)
x$inverse_fisher <- as.vector(permut_all %*% x$inverse_fisher)
x$nlm_output$estimate <- x$estimate
x$nlm_output$gradient <- x$gradient

Expand Down
Binary file modified data/dax_model_2n.rda
Binary file not shown.
Binary file modified data/dax_model_3t.rda
Binary file not shown.
Binary file modified data/dax_vw_model.rda
Binary file not shown.
Binary file modified data/sim_model_2gamma.rda
Binary file not shown.
Binary file removed data/sim_model_4lnorm.rda
Binary file not shown.
Loading

0 comments on commit d635f5d

Please sign in to comment.