Fits multivariate Gaussian-mixture proxies to target
distributions on real Euclidean space, given by a density, by samples,
or by a characteristic function. Four fitting regimes are unified under one verb:
(i) closed-form moment matching for a single component,
(ii) classical expectation-maximisation when independent samples are
available, (iii) importance-sampled expectation-maximisation that
minimises the Kullback-Leibler divergence when the target can be
evaluated point-wise but not (cheaply) sampled, and (iv) a least-squares
fit to the characteristic function when only that is known, with
numerical bounds on the Kolmogorov distance along one-dimensional
projections. Closed-form
Gaussian-mixture operators (density, sampling, marginalisation,
conditioning, divergence) round out the toolkit. The conditioning
operator drives multiple imputation of data missing at random,
covering the multimodal and heteroscedastic cases a single-Gaussian
model cannot represent. Implements the
regime hierarchy of van der Hoek and Elliott (2024)

proxymix fits multivariate Gaussian-mixture proxies to target
distributions on $\mathbb{R}^p$. Three regimes from van der Hoek and
Elliott (2024) fit a density or samples and are Kullback–Leibler
optimal. A fourth fits a distribution known only through its
characteristic function. All four are unified under one verb:
| Regime | When it applies | Method |
|---|---|---|
| (i) moment | $N = 1$ component | Closed-form moment matching |
| (ii) sample | i.i.d. samples from the target are available | Classical EM |
| (iii) kld | target density f(x) can be evaluated but not (cheaply) sampled |
KLD-EM with importance sampling |
| (iv) cf | only the characteristic function of the target is known | Least squares on the characteristic function, with bounds on the Kolmogorov distance |
Regime (iii) is the reason the package exists. The sample-based mixture
packages (mclust, mixtools, flexmix) all assume i.i.d. draws from
the target; proxymix fits directly against an evaluable (possibly
unnormalised) log-density. The nearest CRAN neighbour is AdMit, which
adaptively fits a mixture of Student-t distributions to an evaluable
kernel as an importance/proposal density; proxymix differs in fitting
a Gaussian mixture that is Kullback–Leibler optimal, precisely so
that the fitted object then supports the closed-form operator calculus
(marginals, conditionals, Bayes updates, products, convolutions,
filtering) and carries a fit-quality certificate through every
operation.
Why not MCMC? If you can evaluate the unnormalised density you can always run a sampler and then fit a mixture to the draws. The regime-(iii) fit is the shortcut when what you want is the compact closed-form object: no chain tuning or convergence diagnostics, a deterministic pipeline given the seed, and a mixture whose marginals, conditionals, moments and samples are then available in closed form through the operator calculus. The trade-off is dimension: the importance sampling that drives regime (iii) loses effective sample size sharply beyond roughly $p = 5$–$10$, and every fit reports its effective sample size so that limit is visible rather than silent. For high-dimensional posteriors, sample with your favourite MCMC and use regime (ii) on the draws.
mclust and mixtools fit to draws from the target. proxymix also fits to a density it can only evaluate, and its Gaussian components keep marginals, conditionals and Bayes updates in closed form.
From CRAN:
install.packages("proxymix")
The development version from GitHub:
# install.packages("remotes")
remotes::install_github("max578/proxymix")
or locally from the source tree:
R CMD build proxymix
R CMD INSTALL proxymix_*.tar.gz
Documentation site: https://max578.github.io/proxymix/.
library(proxymix)
## A target you can evaluate but not sample from -- a 2D "banana".
banana <- banana_target()
## Fit a 3-component Gaussian mixture proxy via KLD-EM with importance sampling.
fit <- fit_proxymix(banana, N = 3L, regime = "kld",
proposal = proposal_mvt(n_dim = 2L, df = 5),
is_size = 2000L, max_iter = 60L, seed = 1L)
print(fit)
#> <gmm_fit>: regime = "kld", K = 3, p = 2
#> target : banana
#> iterations : 37
#> converged : TRUE
#> [1] w = 0.6456, |mu| = 0.3299, tr(Sigma) = 1.3601
#> [2] w = 0.2473, |mu| = 1.2996, tr(Sigma) = 2.2312
#> [3] w = 0.1071, |mu| = 1.8882, tr(Sigma) = 4.9044
## Closed-form operations on the fitted mixture.
gmm_marginalise(fit, keep = 1L)
#> <marginalise(kld_em[N=3] on banana)>: K = 3 components in p = 1 dimensions
#> [1] w = 0.6456, |mu| = 0.1818, tr(Sigma) = 0.4620
#> [2] w = 0.2473, |mu| = 1.1518, tr(Sigma) = 0.4846
#> [3] w = 0.1071, |mu| = 1.5954, tr(Sigma) = 0.6321
gmm_conditionalise(fit, given = c(NA, 0.5))
#> <conditionalise(kld_em[N=3] on banana)>: K = 3 components in p = 1 dimensions
#> [1] w = 0.6730, |mu| = 0.2620, tr(Sigma) = 0.4524
#> [2] w = 0.2576, |mu| = 1.1133, tr(Sigma) = 0.2352
#> [3] w = 0.0694, |mu| = 1.4188, tr(Sigma) = 0.1199
## The symmetric stable law of index 1.5 has no closed-form density
## and infinite variance, but its characteristic function is exp(-|t|^1.5).
cf_stable <- function(t) exp(-abs(t[, 1])^1.5)
fit_stable <- from_cf_elliptical(cf_stable, n_dim = 1L, seed = 1L)
fit_stable
#> <gmm_fit>: regime = "cf", K = 10, p = 1
#> target : <none>
#> iterations : NA
#> converged : TRUE
#> cf held-out RMS error : 0.000557
#> Kolmogorov distance : at least 0.000245, at most 0.00509 (1 direction)
#> [1] w = 0.5595, |mu| = 0.0000, tr(Sigma) = 1.3211
#> [2] w = 0.2645, |mu| = 0.0000, tr(Sigma) = 3.7563
#> [3] w = 0.0618, |mu| = 0.0000, tr(Sigma) = 10.6806
#> [4] w = 0.0500, |mu| = 0.0000, tr(Sigma) = 30.3689
#> [5] w = 0.0478, |mu| = 0.0000, tr(Sigma) = 0.4646
#> ... 5 more components
## Quantiles, tail probabilities and draws come from the mixture.
qgmm(c(0.95, 0.99), fit_stable)
#> [1] 3.048049 7.752634
The printed bounds say how far the distribution function of the mixture can be from that of the stable law. The vignette on characteristic functions checks them against an exact computation.
fit_proxymix(
target,
N = 1L,
regime = c("auto", "moment", "sample", "kld", "cf"),
...
)
target is an S7 gmm_target produced by gmm_target() (from a
log-density), gmm_target_from_samples() (from samples),
cf_target() (from a characteristic function), or one of the built-in
factories (banana_target(), donut_target(), mixture_target()).regime = "auto" picks the cheapest applicable regime from the
target’s contents.dgmm(x, fit) # density evaluation
rgmm(n, fit) # exact sampling
gmm_marginalise(fit, keep)
gmm_conditionalise(fit, given)
gmm_kld(fit_p, fit_q) # Monte Carlo + variational bounds
fit <- from_objective(f, lower, upper, N = 10L) # a mixture map of the optima
gmm_modes(fit)$modes # the distinct optima
from_objective() treats an objective f as the Gibbs measure
exp(-f / T) – a regime-(iii) target you can evaluate but not sample –
and returns a closed-form mixture over its low regions, so a multimodal
f is recovered as a whole rather than one optimum at a time.
gmm_modes() resolves the fitted map into the recovered optima.
| You have | You want | Reach for |
|---|---|---|
| an evaluable (unnormalised) log-density | a compact closed-form proxy | gmm_target() then fit_proxymix(regime = "kld") |
| i.i.d. samples | a mixture fit | gmm_target_from_samples() then fit_proxymix() |
| an objective function | a map of its optima | from_objective(), gmm_modes() |
| a kernel density estimate | a small closed-form surrogate | from_kde() |
| a characteristic function only (a stable law, a sum of independent variables) | a mixture with bounds on the Kolmogorov distance | cf_target() then fit_proxymix(), or from_cf(), from_cf_elliptical(), from_cf_sources() |
| a fitted mixture | marginals, conditionals, updates | gmm_marginalise(), gmm_conditionalise(), gmm_observe(), gmm_affine() |
| data with holes | multiple imputation | gmm_impute() with mar() / mnar() / censored() |
| a time series + state-space model | filtering / stability testing | gmm_filter(), gmm_eos_test() |
| a fitted mixture | information-theoretic diagnostics | gmm_entropy(), gmm_divergence(), gmm_mutual_information() |
| a fitted mixture + treatment data | causal / decision quantities | gmm_intervene(), fit_uplift(), proxy_cate() |
| an unnormalised posterior | the marginal likelihood | gmm_evidence() |
| a fitted proxy | error bars on any functional | gmm_fit_ensemble(), proxy_functional_ci() |
| an evaluable-only target | the component count | select_N() |
| a fit collapsing in high dimension | an adaptive proposal | fit_kld_em(adapt = "pmc") |
The package ships with thirteen vignettes:
quickstart – one-page tour.posterior_proxy – the flagship workflow: a real unnormalised
Bayesian posterior compressed to a proxy, with the evidence,
closed-form reads, and bootstrap error bars.three_regimes – a walk-through of regimes (i)–(iii) on toy 2-D
targets, including the agreement of (i) and (iii) at $N = 1$.density_shapes – the regime-(iii) demonstration: banana, donut,
three-mixture targets fit by importance-sampled KLD-EM.cf_targets – regime (iv): a stable law, a sum of independent
variables, two-dimensional targets and a filtering step, each fitted
from its characteristic function and checked against an independent
computation.operator_calculus – closed-form pushforward, Bayesian update,
aggregation and conditioning on a fitted mixture.from_kde – compressing a kernel density estimate into a
Gaussian-mixture proxy.many_methods – one fitted mixture in place of regression,
clustering, PCA and ridge regression.entropy – closed-form entropy, divergence and mutual-information
diagnostics.calibration – mapping the optima of an objective via its Gibbs
measure.missing_data – multiple imputation by conditioning the fitted
mixture (missing at random).missing_data_mnar – imputation under value-dependent missingness
and censoring, with sensitivity analysis.end_of_sample – testing whether the last few observations of a
series are consistent with a fitted state-space model.A standalone, single-file HTML primer for proxymix is hosted at
The page is targeted at Adelaide University Mathematics and Statistics
undergraduates (Guided depth, default) and postgraduate / PhD readers
(Technical depth, via the in-page dial). It runs in the browser with no
R install required, and works the same way offline by double-click.
Source at
max578/proxymix-tutorial.
Hoek, J. van der and Elliott, R. J. (2024). Mixtures of multivariate Gaussians. Stochastic Analysis and Applications. doi:10.1080/07362994.2024.2372605.
Bug reports and suggestions are welcome through the GitHub issues.
citation("proxymix")
MIT © Max Moldovan.