Having zero-length parameters breaks `CmdStanModel$optimize` when argument `init` is given

I’m fitting the following model:

data {
    // Dimensions ----
    int<lower=1> n_obs; // # of observations

    int<lower=0> n_int; // # of distinct intercept parameters
    int<lower=0> n_fe; // # of distinct fixed-effects parameters
    int<lower=0> n_re; // # of distinct random-effects parameters

    int<lower=0> n_nz_int; // # of nonzero elements in the intercept design matrix
    int<lower=0> n_nz_fe; // # of nonzero elements in the fixed-effects design matrix
    int<lower=0> n_nz_re; // # of nonzero elements in the random-effects design matrix

    int<lower=0> n_re_terms; // # of random-effects terms in design formula

    int<lower=1> n_batches; // # of batches
    int<lower=1> n_feats; // # of original features


    // Index Variables ----
    array[n_re] int<lower=1, upper=n_re_terms> re_id; // Random-effects term membership
    array[n_obs] int<lower=1, upper=n_batches> batch_id; // Batch membership
    array[n_obs] int<lower=1, upper=n_feats> feat_id; // Feature membership


    // Response ----
    array[n_obs] int<lower=0> counts;


    // Design Matrices ----
    vector[n_nz_int] int_design_x;
    array[n_nz_int] int int_design_j;
    array[n_obs + 1] int int_design_p;

    vector[n_nz_fe] fe_design_x;
    array[n_nz_fe] int fe_design_j;
    array[n_obs + 1] int fe_design_p;

    vector[n_nz_re] re_design_x;
    array[n_nz_re] int re_design_j;
    array[n_obs + 1] int re_design_p;
}
parameters {
    // Shrinkage ----
    real<lower=0> tau; // Global shrinkage parameter
    vector<lower=0>[n_fe] lambda; // Local shrinkage parameters


    // Feature Expression ----
    vector[n_int] int_coefs; // Intercept coefficients
    vector[n_fe] fe_coefs; // Fixed-effect coefficients
    vector[n_re] re_coefs; // Random-effect coefficients

    vector<lower=0>[n_re_terms] re_sigma; // Random-effect std-devs


    // Size Factors ----
    simplex[n_batches] raw_sf;


    // Feature-level Dispersion
    real<lower=0> iodisp; // TODO
}
transformed parameters {
    // Size Factors ----
    vector[n_batches] sf = log(raw_sf) + log(n_batches);
}
model {
    vector[n_obs] log_mu;

    // Priors ----
    // Horseshoe
    lambda ~ cauchy(0, tau);
    re_sigma ~ cauchy(0, tau);

    fe_coefs ~ normal(0, lambda);

    // Random-effects
    for (i in 1:n_re) {
        re_coefs[i] ~ normal(0, re_sigma[re_id[i]]);
    }


    // Computing gene expression quantity
    log_mu = csr_matrix_times_vector(n_obs, n_int, int_design_x, int_design_j, int_design_p, int_coefs);
    if (n_fe != 0) {
        log_mu += csr_matrix_times_vector(n_obs, n_fe, fe_design_x, fe_design_j, fe_design_p, fe_coefs);
    }
    if (n_re != 0) {
        log_mu += csr_matrix_times_vector(n_obs, n_re, re_design_x, re_design_j, re_design_p, re_coefs);
    }


    for (i in 1:n_obs) {
        // Adjusting for batch-effect
        log_mu[i] += sf[batch_id[i]];

        // Likelihood ----
        counts[i] ~ neg_binomial_2_log(log_mu[i], iodisp);
    }
}

I’m having an issue when passing data where either n_fe or n_re is 0. The initial fit works properly:

    # Estimate initial fit
    cur_fit <- model$optimize(stan_data, iter = n_iters, show_messages = F, sig_figs = 18)

However when passing the CmdStanModel object into init for the next fit I get the following:

# Test
model$optimize(stan_data, init = cur_fit)
Init values were only set for a subset of parameters.
Missing init values for the following parameters:
lambda, fe_coefs

To disable this message use options(cmdstanr_warn_inits = FALSE).

Initial log joint probability = 14831.6
    Iter      log prob        ||dx||      ||grad||       alpha      alpha0  # evals  Notes
       1       14831.6             0   8.83946e+09       1e-12       0.001       45
Chain 1 Optimization terminated with error:
Chain 1   Line search failed to achieve a sufficient decrease, no more progress can be made
Warning: Fitting finished unexpectedly! Use the $output() method for more information.

Finished in  0.1 seconds.
Error: Fitting failed. Unable to print.

Even when I extract the parameters from the first cur_fit, format them as a list, and add numeric(0) arguments for the missing parameter names, the first warning goes away but the optimization doesn’t get past the first iteration.

What can I do to fix this? I need to repeatedly start and stop optimization as I have custom stopping conditions for only a subset of the parameters (I only care if sf has converged).

Operating System: macOS Sequoia 15.5
CmdStan Version: 2.36.0
Interface Version: cmdstanr 0.9.0
Compiler/Toolkit: Apple clang version 17.0.0

Problem is not due to 0-length parameters, seems I have identifiability issues (where I also have many flat regions in the parameter space) if there is only a single observation per distinct negative binomial. Weirdly does not show up when I do this with brms so I think I’ve implemented something improperly.

1 Like

Although you already noticed that the 0-length parameters are not a problem, a general clarification about this message

It is possible to initialize only a subset of parameters with user defined initial values and the rest are then initialized with default random uniform(-2, 2) in unconstrained space. 0-length parameters are then initialized with zero length random vector. The warning is given just in case that some inits were unintentionally forgotten.

1 Like