Concept - Latent Class and Dirichlet Process Models for Multiple Systems Estimation
Summary
LCMCR (Manrique-Vallier 2016) models the 2K list-inclusion table as a mixture of product-Bernoulli latent classes with a truncated Dirichlet-process (stick-breaking) weight prior, and treats the unseen individuals by data augmentation. It gives flexible heterogeneity without picking list interactions, but Aleshin-Guendel (2020) shows its families are non-identifiable when the number of classes exceeds K/2, and Silverman (2020) shows unstable results on the UK and Netherlands data.
Each individual i=1..N has class ci∼Categorical(ν1..νJ) and inclusion indicators xik∣ci=j∼Bernoulli(λjk) independently over lists k=1..K. The observed cells are those with some xik=1; N includes N−n unseen individuals with xi=0.
Marginal cell probability: πh=∑jνj∏kλjkhk(1−λjk)1−hk; the missing cell is π0=∑jνj∏k(1−λjk).
Dirichlet-process version (LCMCR; details to verify)
Replace finite J by a stick-breaking prior: νj=vj∏l<j(1−vl), vj∼Beta(1,α), truncated at J∗ classes, with a hyperprior on the concentration α and Beta priors on λjk; the population size has a prior of the form p(N)∝1/N (improper) or a bounded alternative, and inference is by Gibbs sampling with data augmentation of the unobserved individuals (as I recall; confirm exact hyperparameters against the paper and the R package LCMCR). Reported summary: posterior of N, including the uncertainty from the augmented zero-pattern count.
Identification bound (from Aleshin-Guendel 2020)
With J∗ distinct classes and K lists, the family is identified iff 2J∗≤K. The LCMCR default J∗=5 requires K≥10; the recommended J∗=K never is. Practical reading: with K≤9 lists the posterior for N is partly set by the prior over class structure and the truncation level.
Computation. In a probabilistic-programming implementation, classes are summed out per cell using logsumexp rather than sampled (Concept - Marginalising Latent Discrete Counts for HMC); the unseen cell contributes the term π0 through n∼Binomial(N,1−π0) combined with a prior on N. Label switching is handled by ordering constraints, and the cell-level likelihood avoids per-individual class indicators when counts are aggregated (a 2K table has at most 2K−1 distinct patterns).
Diagnostics. (a) Vary J∗ below and above K/2 and compare posterior intervals for N (stability). (b) Merge two small lists and re-estimate: a good estimator should not move much (this exposed Netherlands instability in Silverman 2020 - Madigan-York and Dirichlet Process Benchmarks). (c) Prior-versus-posterior comparison for N.
Examples
PyMC-style sketch (untested): finite latent class MSE on a table
import numpy as np, pymc as pm, pytensor.tensor as pt, itertoolsK, J = 4, 2 # keep 2J <= K for identificationH = np.array([h for h in itertools.product([0,1], repeat=K) if any(h)])counts = np.array([...]) # observed cell counts, one per row of Hn = counts.sum()with pm.Model() as lcm: nu = pm.Dirichlet("nu", np.ones(J)) lam = pm.Beta("lam", 1, 1, shape=(J, K)) # log cell probabilities per class: (J, 2^K-1) logc = (H[None] * pt.log(lam)[:, None] + (1-H[None]) * pt.log1p(-lam)[:, None]).sum(-1) logpi = pm.math.logsumexp(pt.log(nu)[:, None] + logc, axis=0) log_pi0 = pm.math.logsumexp(pt.log(nu) + pt.log1p(-lam).sum(1)) # conditional multinomial likelihood of observed cells, then add N | n via a prior on N pm.Potential("cells", pt.sum(counts * (logpi - pt.log1p(-pt.exp(log_pi0))))) pm.Deterministic("dark_per_observed", pt.exp(log_pi0) / (1 - pt.exp(log_pi0)))
Posterior draws of π0 give N=n/(1−π0) (point) and, with a Negative-Binomial predictive for the unseen count, a full interval. Not tested; check with simulated data where the truth is known.
Relevance to marketing measurement
Latent class models for overlapping audiences (heavy vs light users) mirror the Mth idea: dependence between data sources is explained by unobserved segments rather than pairwise interaction terms. The identification warning transfers directly: with only a few sources you cannot support many latent segments.