The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
Three scenarios call for the distributed API:
All three are solved with the same primitive: each chunk produces a
vcmm_ss summary; summaries are additive; the fit is
computed from the aggregate.
Theorem 1 of Jalili and Lin (2025): partition the data into \(K\) chunks, compute a sufficient-statistics summary on each chunk, sum the summaries, and fit. The result is bit-equivalent (up to BLAS summation noise) to fitting on the pooled data. The summaries lose no information — they are the sufficient statistics for the VCMM likelihood.
The summary on chunk \(k\) stores \[ \bigl(a_k,\; b_k,\; C_k,\; (Z^\top Z)_k,\; (Z^\top y)_k,\; (X^\top Z)_k,\; n_k\bigr) \] where \(a = y^\top y\), \(b = X^\top y\), \(C = X^\top X\). Adding summaries across chunks is element-wise addition; the aggregate is the same as the single summary you would have computed on the pooled data.
A modest example: \(N = 1200\) observations, \(K = 1\) varying covariate, \(q = 4\) independent random effects. Then we’ll split it into 3 nodes.
This is the “data on \(K\) machines” case. Each node:
node_summary() on its slice,vcmm_ss object (small — a few KB
regardless of \(n_k\)) to the central
node.The central node sums the summaries and calls
fit_from_summaries().
# Assign each observation to one of 3 nodes
node_id <- sample.int(3L, N, replace = TRUE)
splits <- split(seq_len(N), node_id)
lengths(splits)
#> 1 2 3
#> 405 401 394Build the spline design once. (In a real deployment, each node would
construct its piece of the design locally using the same
n_basis, degree, and knot placement — the
package handles this automatically as long as the inputs agree.)
design <- build_vcmm_design(X = x, t = t)
X_d <- design$X_design
# N rows x p columns; p = intercept + spline-basis coefficients,
# with n_basis auto-picked from the sample size.
dim(X_d)
#> [1] 1200 15Each node produces a summary:
summaries <- lapply(splits, function(idx) {
node_summary(y[idx], X_d[idx, , drop = FALSE], Z[idx, , drop = FALSE])
})
summaries[[1]]
#> <vcmm_ss> one-batch sufficient statistics
#> n_obs : 405
#> p : 15 (fixed-effects columns)
#> q : 4 (random-effects columns)
#> a : 2461The size of each summary is independent of \(n_k\):
object.size(summaries[[1]])
#> 4776 bytes
object.size(y[splits[[1]]]) + object.size(X_d[splits[[1]], ])
#> 52104 bytesNow fit from the summaries — pass the list directly:
ctrl <- vcmm_control(sigma_eps = 0.5,
sigma_alpha = 0.5,
update_variance = TRUE)
fit_dist <- fit_from_summaries(summaries,
penalty = design$penalty,
control = ctrl,
method = "ss",
re_cov = "diag")
fit_dist
#> <vcmm_fit> Varying Coefficient Mixed-Effects Model fit
#> method : SS
#> n_obs : 1200
#> p (fixed) : 15
#> q (random) : 4
#> RE cov : diag
#> iterations : 5 (converged)
#> sigma_eps : 0.4845
#> sigma_alpha : 0.7251
#> elapsed : <0.001 secfit_pooled <- vcmm(y, X = x, Z = Z, t = t,
method = "ss", re_cov = "diag",
control = ctrl)
# beta estimates
max(abs(fit_pooled$beta - fit_dist$beta))
#> [1] 1.107447e-14
# alpha estimates
max(abs(fit_pooled$alpha - fit_dist$alpha))
#> [1] 2.220446e-16
# variance components
all.equal(fit_pooled$sigma_eps, fit_dist$sigma_eps)
#> [1] TRUE
all.equal(fit_pooled$sigma_alpha, fit_dist$sigma_alpha)
#> [1] TRUEThe maximum coefficient difference sits at the BLAS summation-noise floor — typically near machine epsilon (\(\sim 10^{-15}\)). The distributed fit is the pooled fit; only the path that produced it differs.
When you have many small chunks and don’t want to keep them all in memory, use the accumulator instead of a list. The accumulator stores a running sum of the sufficient statistics; chunks can be incorporated and discarded as they arrive.
p <- ncol(X_d)
acc <- init_accumulator(p = p, q = q)
# Pretend chunks arrive one at a time
for (k in seq_along(splits)) {
idx <- splits[[k]]
ss_k <- compute_sufficient_stats(y[idx],
X_d[idx, , drop = FALSE],
Z[idx, , drop = FALSE])
acc <- accumulate_stats(acc, ss_k)
}
acc
#> <vcmm_accumulator> accumulated sufficient statistics
#> n_obs : 1200
#> p : 15 (fixed-effects columns)
#> q : 4 (random-effects columns)
#> a : 7587Fit from the accumulator — same call signature:
When rowSums(Z) is constant — for example, a row of
\(Z\) has exactly one “origin”
indicator and one “destination” indicator, so each row sums to \(s = 2\) — the model has a one-dimensional
identifiability redundancy. For any scalar \(c\), replacing \[
\alpha \;\mapsto\; \alpha + c\mathbf{1}, \qquad
\beta_0 \;\mapsto\; \beta_0 - c\,s
\] leaves \(Z\alpha +
\beta_0\mathbf{1}\) — and hence the likelihood — unchanged.
vcmm() detects this automatically by inspecting the raw
\(Z\) matrix and applies a centering
shift so that \(\sum_j \hat\alpha_j =
0\).
fit_from_summaries() doesn’t auto-detect the row-sum
from the sufficient statistics, so you supply it explicitly via
rowsum_constant:
# Skeleton — see vignette("od-migration") for a complete runnable example.
# G and Sigma_spatial come from the OD setup (number of regions and an
# initial spatial covariance matrix).
fit_dist_od <- fit_from_summaries(
summaries, penalty = design$penalty, control = ctrl,
method = "ss", re_cov = "kronecker",
n_groups = G, # number of OD regions
Sigma_spatial_init = Sigma_spatial, # G x G initial spatial covariance
rowsum_constant = 2 # matches what vcmm() applies internally
)Without rowsum_constant, the distributed fit’s \(\hat\beta_0\) and \(\hat\alpha\) differ from the pooled fit’s
by exactly the centering shift. The fits are the same up to the
redundancy; only the choice of representative within the equivalence
class differs.
See vignette("od-migration", package = "cevcmm") for a
full OD example.
vignette("od-migration", package = "cevcmm").vignette("getting-started", package = "cevcmm").Jalili, L. and Lin, L.-H. (2025). Scalable and Communication-Efficient Varying Coefficient Mixed Effect Models: Methodology, Theory, and Applications. arXiv:2511.12732; under review at Journal of the American Statistical Association.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.