Skip to main content

causal-sampler

causal-sampler provides causal resampling for reverse causal inference: estimate an interventional distribution of observations X under an intervention on Y, then use the generated (X, Y) pairs to train a downstream predictor.

Version 1.0.0 integrates causalbootstrapping 0.2.6 and extends the CB/CW-GMM interfaces in 0.0.5 with CW-DPMM, hybrid block Gibbs-HMC and a unified identification-guided image DDPM. Identification and interpretation depend on the supplied causal graph, measured variables, overlap and distribution estimates; generated data are an estimated interventional sample, not independently verified unconfounded observations.

Installation

The package declares Python >=3.9 and depends on causalbootstrapping==0.2.6. Numerical dependency ranges admit compatible NumPy 1.x/2.x versions and newer Python interpreters. Python 3.12 is a useful starting point; see validation notes for tested versions. Create an isolated environment:

conda create -n causal-sampler python=3.12
conda activate causal-sampler
python -m pip install --upgrade pip

Install the release wheel, using its actual path:

python -m pip install dist/causal_sampler-1.0.0-py3-none-any.whl

Or install from this source directory:

python -m pip install .
# Include notebook dependencies:
python -m pip install ".[demo]"
# Editable development installation:
python -m pip install -e ".[demo,dev]"

Once 1.0.0 is published to PyPI, it can also be installed with python -m pip install causal-sampler==1.0.0.

Publish causalbootstrapping 0.2.6 first, then causal-sampler 1.0.0. Before the dependency is on PyPI, install its prepared wheel alongside this wheel using your actual local paths:

python -m pip install /path/to/causalbootstrapping-0.2.6-py3-none-any.whl dist/causal_sampler-1.0.0-py3-none-any.whl

The dependency is not vendored and no machine-specific path is embedded in package metadata.

PyTorch is a required dependency for the public pipeline in this release. For a CPU-only Linux environment, you may install the tested CPU build first:

python -m pip install "torch==2.8.0" --index-url https://download.pytorch.org/whl/cpu
python -m pip install .

For CUDA, install a compatible PyTorch build for your platform before the package; then select device="cuda" for HMC/DDPM. GPU execution was not part of the local release validation. The Python graphviz dependency is installed automatically; rendering causal graphs additionally requires the Graphviz system executable. Resampling without graph rendering does not require that executable.

Public samplers

from causal_sampler import pipeline as cs_pipe
# Direct imports are also supported:
from causal_sampler import CausalBootstrapSampler, CausalDDPMSampler
Method Public class Main fit configuration
Empirical causally weighted bootstrap CausalBootstrapSampler Density estimator, kernel, optional weight transformation
Causally weighted Gaussian mixture CausalGMMSampler comp_k, covariance type, weighted EM settings
Causally weighted Dirichlet process mixture CausalDPMMSampler alpha, prior, covariance type, Gibbs iterations
Hybrid block Gibbs-HMC CausalBlockGibbsHMC Update blocks, burn-in, thinning, device
Unified ID-guided conditional image DDPM CausalDDPMSampler Variable types, image shape, network and diffusion settings

All five classes offer fit(), resample() and fit_deconf_model(). Method-specific training arguments and return conventions are documented in their docstrings. The DDPM additionally offers save_checkpoint(), load_checkpoint() and from_checkpoint(). Persistence is not a shared high-level API for every sampler.

Quick start: front-door bootstrap

This small synthetic example needs no downloaded dataset. U is used only to simulate unobserved confounding and is deliberately absent from data_dict.

import numpy as np
from causal_sampler import pipeline as cs_pipe

rng = np.random.default_rng(42)
n = 120
u = rng.normal(size=n)
y = (u + rng.normal(size=n) > 0).astype(int)
z = y + rng.normal(scale=0.7, size=n)
x = np.column_stack([
    2 * z + u + rng.normal(size=n),
    z - u + rng.normal(size=n),
])
training_data = {"X": x, "Y": y[:, None], "Z": z[:, None]}
graph = "Y;Z;X;Y->Z;Z->X;Y<->X;"

flow = cs_pipe.CausalBootstrapSampler(
    causal_graph=graph,
    cause_var_name="Y", effect_var_name="X",
    intv_values=[0, 1], data_dict=training_data,
    est_method="kde", bandwidth="scott",
)
flow.fit()
X_deconf, Y_deconf, source_idx = flow.resample(
    n_samples=[100, 100], random_seed=42,
    return_samples=True, return_indices=True, verbose=0,
)
assert np.array_equal(X_deconf, x[source_idx])

Y_deconf contains the assigned intervention values. Under some identification formulas these differ from the original labels of the source rows. source_idx always refers to row positions in the data supplied to this sampler; it is not a DataFrame index label. The indices remain aligned after shuffling.

For non-DDPM samplers, supply finite numeric arrays shaped (N, d); scalar (N,) arrays are also normalized to (N, 1). Every variable must use the same row order and count. An integer n_samples=100 requests 100 per intervention, not 100 in total. A sequence follows intv_values order. Generated arrays are available as flow.deconf_X and flow.deconf_Y even with return_samples=False.

Mixture models and downstream prediction

gmm = cs_pipe.CausalGMMSampler(
    causal_graph=graph, cause_var_name="Y", effect_var_name="X",
    intv_values=[0, 1], data_dict=training_data, est_method="kde",
)
gmm.fit(comp_k=3, cov_type="diag", max_iter=50, random_seed=42, verbose=0)
X_gmm, Y_gmm = gmm.resample(100, random_seed=42, return_samples=True)

from sklearn.ensemble import RandomForestClassifier
classifier = gmm.fit_deconf_model(RandomForestClassifier(random_state=42))

Use CW-DPMM when the number of components is to be inferred under its prior:

dpmm = cs_pipe.CausalDPMMSampler(
    causal_graph=graph, cause_var_name="Y", effect_var_name="X",
    intv_values=[0, 1], data_dict=training_data, est_method="kde",
)
dpmm.fit(alpha=1.0, cov_type="diag", init_clusters=2,
         burn_in=10, max_iter=30, random_seed=42, verbose=0)
X_dpmm, Y_dpmm = dpmm.resample(100, random_seed=42, return_samples=True)

max_iter counts retained DPMM sweeps after its burn_in sweeps. Generation uses the final fitted mixture state. Repeated resample(random_seed=42) calls on an unchanged DPMM now reset its actual per-intervention generators. Historical sampling sequences are not guaranteed to match 0.0.5 or development snapshots.

Weight transformations

CB, CW-GMM and CW-DPMM accept the following fit options:

flow.fit(weight_transform=None)                       # unchanged weights
flow.fit(weight_transform="ess_norm", ess_fraction=0.1)
flow.fit(weight_transform="log")                      # log1p(weights)
flow.fit(weight_transform=[0.01, 0.99])                # quantile clipping

Quantiles are computed on positive weights only; structural zeros remain zero. ESS adjustment uses a power transformation to meet the requested ESS floor while preserving zero support. It is not only multiplication by a normalization constant. All nontrivial transformations change the empirical target distribution and should be reported with sensitivity analyses. log compression depends on the absolute scale of the input weights. An ESS fraction is a tuning choice, not a guarantee of causal validity or additional independent information.

Misspelled or unsupported options raise an error. Development-only arguments truncate_weights and truncated_weight are not supported; use weight_transform. For direct calls to compute_causal_weight(), the argument is named transform.

HMC and DDPM

See the sampler guide for HMC update blocks and initialization, and the complete DDPM API for every constructor, fit, generation and checkpoint option.

The DDPM accepts one image effect, one scalar categorical cause, and auxiliary conditional mixtures certified by symbolic leaf elimination. It does not implement every formula returned by ID. Unsupported expressions raise UnsupportedIDExpression. variable_types and image_shape must be explicit. Its optional reconstruction consistency penalty defaults to zero.

Run examples and notebooks

python examples/quickstart.py --method all
python -m jupyterlab Demo
  • Demo 00: all sampler APIs: self-contained, small CPU examples for all five samplers, source indices, weight options and checkpoints.
  • Demo 01: synthetic back-door: original classification/regression study; requires external CSVs and has refreshed interface notes.
  • Demo 02: background-MNIST: preserves the original experiment; requires the external CSVs listed in its first cell. The large pretrained pickle is no longer distributed or loaded automatically.
  • Demo 03: general graph: original external-CSV experiment with updated API guidance.

The short examples demonstrate executable interfaces, not tuned experimental performance. Fit samplers, density estimators and downstream models on training partitions only; split by participant where observations repeat within a subject.

Development and release

python -m unittest discover -s tests -v
python -m build
python -m twine check dist/*

See CHANGELOG.md, migration notes, and RELEASE.md. The source distribution includes documentation, notebooks, examples and tests. The wheel contains the importable package and license.

Citation and license

The original package citation entries are retained below. They provide background for causal bootstrapping and mechanism learning, not a claim that every added sampler is described in those papers.

@article{mao2024mechanism,
  title={Mechanism learning: Reverse causal inference in the presence of multiple unknown confounding through front-door causal bootstrapping},
  author={Mao, Jianqiao and Little, Max A},
  journal={arXiv preprint arXiv:2410.20057},
  year={2024}
}
@article{little2019causal,
  title={Causal bootstrapping},
  author={Little, Max A and Badawy, Reham},
  journal={arXiv preprint arXiv:1910.09648},
  year={2019}
}

Author: Jianqiao Mao. Licensed under the GNU GPL version 3 text supplied with the original release; see LICENSE.

Changes from the prepared 0.0.6 package

  • Dependency pin advances to causalbootstrapping 0.2.6; package metadata no longer imposes Python <3.11. PyTorch now requires >=2.5,<3.
  • The CB adapter calls the dependency's validated bootstrapper and uses its returned source indices, then applies one shared shuffle to X, Y and indices. sampling_mode="exact" remains an alias for "robust" at this top-level API.
  • Invalid computed weights raise with the intervention value in the message. NaNs are not silently replaced; fix the density/support issue before training.
  • Public class names, fit/resample signatures and return conventions remain. Seeded CB samples may differ from 0.0.6; repeatability within 1.0.0 is tested.
  • DDPM architecture and checkpoint format are unchanged from the prepared unified implementation. Experimental pre-unification checkpoints still require migration; supported ID-expression restrictions remain in force.

Release files for causal-sampler 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for causal-sampler 1.0.0
File Size Uploaded
causal_sampler-1.0.0.tar.gz 147.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for causal-sampler 1.0.0
File Interpreter ABI Platform
causal_sampler-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 246.7 kB

Release files / causal_sampler-1.0.0.tar.gz

Download URL causal_sampler-1.0.0.tar.gz
Size 147.0 kB
Tags Source
SHA-256 checksum
How to use checksums
dfff3431326e1203fa047e35d655d242f1716c22ae1f14e2b6a75a1d5c7d18de
BLAKE2b-256 checksum
How to use checksums
26f464231e52622db9f345165423a791e1384dea99262741a27ed38d313b9764
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.9.12

Release files / causal_sampler-1.0.0-py3-none-any.whl

Download URL causal_sampler-1.0.0-py3-none-any.whl
Size 99.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8526033429044a9efe4e942fc8703b1c083aaf6ceea9f507e3c3b3edc87a9091
BLAKE2b-256 checksum
How to use checksums
e22c2e0d838843f8352d0209ac3589290b3b484c25bb2602a683af1c5bfb8d9f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.9.12

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page