
Fast Adjacent-Category Logit Regression, Direct MLE (C++ Backend)
Source:R/RcppExports.R
fast_adjacent_category_logit_cpp.RdFits the adjacent-category logit ordinal regression model
$$\log\frac{\Pr(Y = k+1)}{\Pr(Y = k)} = \alpha_k + \beta^\top x, \quad k = 1, \dots, K-1,$$
by direct maximum likelihood on the full multinomial likelihood of y,
rather than via the stacked-binary / stratified-conditional-logit reduction
implemented by expand_adjacent_category_data_cpp() elsewhere in the
package. \(\beta\) (the covariate effects, shared across all K - 1 cuts)
and the K - 1 cut-specific intercepts \(\alpha_k\) are estimated jointly
by numerically optimizing the exact multinomial log-likelihood, which is
generally more accurate and can be faster than fitting the row-stacked expansion
as a stratified logistic regression, at the cost of a custom (rather than reused)
optimizer implementation.
Usage
fast_adjacent_category_logit_cpp(
X,
y,
maxit = 100L,
tol = 1e-08,
smart_cold_start = TRUE,
fixed_idx = NULL,
fixed_values = NULL,
optimization_alg = "lbfgs",
warm_start_fisher_info = NULL,
warm_start_params = NULL,
warm_start_beta = NULL
)Arguments
- X
A numeric matrix of predictors, \(n \times p\), with no intercept column (the model's cut-specific intercepts \(\alpha_k\) serve that role).
- y
A numeric vector of length \(n\) giving each subject's ordinal category; need not be pre-coded
1:K(see Details for the rank-based remapping).- maxit
Maximum number of optimizer iterations.
- tol
Convergence tolerance.
- smart_cold_start
Logical. If TRUE, use an initial OLS-based guess when starting from scratch (a "cold start") with no prior knowledge. This is ignored if a warm start is provided.
- fixed_idx
Optional integer indices (into the
c(alpha, beta)parameter layout described in Details) of parameters to hold fixed rather than estimate.- fixed_values
Optional values to fix the parameters named by
fixed_idxat; must be the same length asfixed_idx.- optimization_alg
Optimization algorithm; see Details.
- warm_start_fisher_info
Optional initial Fisher Information matrix (over the full
c(alpha, beta)parameter vector) to warm-start curvature information.- warm_start_params
Optional starting values for the full parameter vector
c(alpha, beta). If provided,smart_cold_startis ignored.- warm_start_beta
Optional starting values for just the covariate coefficients \(\beta\) (cut intercepts \(\alpha\) are still initialized separately). If provided,
smart_cold_startis ignored.
Value
A list with components b (the shared covariate coefficients
\(\hat\beta\), length p), alpha (the K - 1 estimated
cut intercepts \(\hat\alpha_k\)), params (the full
c(alpha, b) parameter vector, as optimized), neg_loglik (the
multinomial negative log-likelihood at convergence), and converged
(logical).
Details
Category coding. y need not already be coded 1:K: the
distinct values of y are extracted and sorted (get_levels()), and
each observation is remapped to its 1-based rank among those sorted
distinct values (map_y_to_1K()) — e.g. y = c(10, 30, 20, 10) is
treated identically to y = c(1, 3, 2, 1), with K = 3. K is
therefore the number of distinct observed values, not any externally
supplied category count, and requires at least 2 (an error is raised otherwise).
Parameterization and likelihood. Internally, category probabilities are
computed via a numerically stable log-space recurrence: unnormalized
log-probabilities \(\log \tilde p_k = \sum_{j=k}^{K-2} (\alpha_j - \eta)\)
(\(\eta = x^\top \beta\)) are accumulated additively — never by exponentiating
\(\alpha_k\) or \(-\eta\) directly — and normalized with a standard
log-sum-exp, so every exp() call sees an argument \(\le 0\) and
\(\Pr(Y = k)\) is bounded to \([0, 1]\) regardless of how extreme
\(\alpha\)/\(\eta\) get during optimization (fixed 2026-08-27: the prior
right-to-left product recurrence in terms of raw \(e^{-\eta}\) and
\(e^{\alpha_k}\) could each individually overflow to Inf before
normalization, corrupting the objective/gradient to Inf/NaN and
leaving the optimizer's line search unable to recover — confirmed via direct
testing to reliably exhaust the full iteration budget without converging on
ordinary synthetic data at every sample size and seed tried, and to diverge
outright to NaN parameters from an all-zero start). The returned
neg_loglik is the resulting exact multinomial negative log-likelihood
(\(-\sum_i \log \Pr(Y_i = y_i)\)), with the analytic gradient computed in the
same pass and used internally for optimization. See
fast_adjacent_category_logit_with_var_cpp for the variant that
additionally returns the variance-covariance matrix of the estimates.
Parameter vector layout. The optimizer's parameter vector (returned as
params) is c(alpha_1, ..., alpha_{K-1}, beta_1, ..., beta_p) — the
K - 1 cut intercepts first, then the p shared covariate
coefficients (p = ncol(X)).
Optimization. Optimized via optimization_alg ("lbfgs"
default; see .normalize_optimizer_algorithm for the supported set),
for at most maxit iterations at tolerance tol. When no warm start is
supplied, smart_cold_start = TRUE (default) seeds the optimizer from an
OLS-based initial guess rather than a naive zero/arbitrary start; supplying
warm_start_params (the full parameter vector) or warm_start_beta
(just the covariate coefficients, with cut intercepts initialized separately)
overrides smart_cold_start entirely. fixed_idx/fixed_values
allow holding specific parameters (by index into the layout above) fixed at
supplied values during optimization rather than estimating them, and
warm_start_fisher_info allows reusing a previously computed Fisher
information matrix to warm-start curvature information for faster convergence.
See also
fast_adjacent_category_logit_with_var_cpp for the
variance-augmented variant; expand_adjacent_category_data_cpp() for the
alternative stacked-binary reduction of the same model.
Ordinal regression for
orientation.