Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Randomly perturb the starting values and try again #237

Open
sfcheung opened this issue Jun 18, 2022 · 0 comments
Open

Randomly perturb the starting values and try again #237

sfcheung opened this issue Jun 18, 2022 · 0 comments

Comments

@sfcheung
Copy link
Contributor

(From this thread in Google group: https://groups.google.com/g/lavaan/c/KzPT7VdHpb8/m/Xl9jUd9pAAAJ)

I sometimes use OpenMx. It has the function mxTryHard() which will fit a model several times with randomly perturbed starting values, to see if a solution can be found. Maybe a similar function can be developed for lavaan? This is a draft one to illustrate the idea:

try_more <- function(object, attempts = 3, seed = NULL, rmin = .5, rmax = 1) {
    set.seed(seed)
    ptable <- lavaan::parameterTable(object)
    i_free <- ptable$free > 0
    i_free_p <- i_free & (ptable$op != "~~")
    k <- sum(i_free_p)
    ptable$est <- ptable$start
   # Generate a list of vectors of randomly perturbed starting values
    x <- replicate(attempts, stats::runif(k, rmin, rmax), simplify = FALSE)
    out0 <- lapply(x, function(x) {
                      ptable_i <- ptable
                      ptable_i[i_free_p, "est"] <- ptable[i_free_p, "est"] * x
                      # Should do something to reject "bad" starting values
                      stats::update(object, start = ptable_i,
                                    check.start = FALSE)
                    })
    out0 <- c(list(object), out0)
    # Need to add some error catching code. It is possible that all of them fail the check.
    fit_ok <- sapply(out0, lavaan::lavInspect, what = "post.check")
    out1 <- out0[fit_ok]
    fit_fmin <- sapply(out1, lavaan::fitMeasures, fit.measures = "fmin")
    out2 <- out1[which(fit_fmin == min(fit_fmin))]
    # Should have the option to return more diagnostic information
    out2[[1]]
  }

The version above is certainly not yet ready for use (e.g., error checking need to be added, need a more robust way to change the starting values, etc.) but is sufficient to illustrate the idea, I think.

If a model does not take a long time to fit, maybe this function can be run whenever a model is fitted, to check automatically whether the objective function can be further minimized. If yes, returned the new solution with smallest objective function value.

If convergence failed when fitting a model, maybe this function can also be run automatically to see if convergence can be achieved by changing the starting values.

Or, just like OpenMx, this can be a standalone function for users who would like to do this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants