pystatistics 3.3.0__tar.gz → 3.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pystatistics-3.4.0/.release/UNRELEASED.md +29 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/CHANGELOG.md +18 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/PKG-INFO +13 -2
- {pystatistics-3.3.0 → pystatistics-3.4.0}/README.md +12 -1
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pyproject.toml +1 -1
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/__init__.py +1 -1
- pystatistics-3.4.0/pystatistics/mice/backends/_gpu_linreg.py +138 -0
- pystatistics-3.4.0/pystatistics/mice/backends/_gpu_methods.py +81 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/backends/cpu.py +7 -4
- pystatistics-3.4.0/pystatistics/mice/backends/gpu.py +170 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/solvers.py +36 -20
- pystatistics-3.4.0/tests/mice/test_gpu.py +146 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mice/test_mice.py +16 -3
- pystatistics-3.3.0/.release/UNRELEASED.md +0 -30
- {pystatistics-3.3.0 → pystatistics-3.4.0}/.github/workflows/publish.yml +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/.github/workflows/trigger-docs-rebuild.yml +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/.gitignore +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/.release/CHECKLIST.md +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/.release/release.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/CLAUDE.md +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/LICENSE +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/benchmarks/mvnmle_bench.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/DESIGN.md +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/Forge.md +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/GPU_BACKEND_NOTES.md +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/Makefile +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/PYSTATSBIO_CONTEXT.md +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/ROADMAP.md +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/_static/custom.css +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/anova.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/conf.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/core.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/descriptive.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/gam.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/hypothesis.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/index.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/mixed.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/montecarlo.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/multinomial.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/multivariate.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/mvnmle.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/ordinal.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/regression.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/survival.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/docs/timeseries.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/GPU_BACKEND_CONVENTION.md +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/anova/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/anova/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/anova/_contrasts.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/anova/_levene.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/anova/_posthoc.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/anova/_repeated.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/anova/_ss.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/anova/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/anova/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/anova/solvers.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/capabilities.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/compute/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/compute/device.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/compute/linalg/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/compute/linalg/batched.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/compute/linalg/cholesky.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/compute/linalg/determinant.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/compute/linalg/qr.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/compute/linalg/solve.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/compute/linalg/svd.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/compute/optimization/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/compute/optimization/convergence.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/compute/precision.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/compute/timing.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/compute/tolerances.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/compute/torch_interop.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/datasource.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/encoding.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/exceptions.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/protocols.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/result.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/core/validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/descriptive/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/descriptive/_missing.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/descriptive/_quantile_types.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/descriptive/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/descriptive/backends/cpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/descriptive/backends/gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/descriptive/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/descriptive/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/descriptive/solvers.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/gam/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/gam/_basis.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/gam/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/gam/_fit.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/gam/_gam.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/gam/_gcv.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/gam/_smooth.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/gam/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/gam/backends/_gpu_family.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/gam/backends/gpu_pirls.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/gam/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/_design_factories.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/_p_adjust.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/backends/_chisq_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/backends/_fisher_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/backends/_ks_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/backends/_prop_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/backends/_t_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/backends/_var_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/backends/_wilcox_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/backends/cpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/backends/gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/hypothesis/solvers.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/_chain.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/_rng.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/_visit.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/datasets.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/methods/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/methods/_linreg.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/methods/base.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/methods/norm.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/methods/pmm.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/methods/registry.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/pooling.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mice/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mixed/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mixed/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mixed/_deviance.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mixed/_pirls.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mixed/_pls.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mixed/_random_effects.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mixed/_satterthwaite.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mixed/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mixed/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mixed/solvers.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/montecarlo/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/montecarlo/_ci.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/montecarlo/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/montecarlo/_influence.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/montecarlo/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/montecarlo/backends/cpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/montecarlo/backends/gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/montecarlo/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/montecarlo/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/montecarlo/solvers.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/multinomial/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/multinomial/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/multinomial/_likelihood.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/multinomial/_solver.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/multinomial/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/multinomial/backends/gpu_likelihood.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/multinomial/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/multivariate/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/multivariate/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/multivariate/_factor.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/multivariate/_pca.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/multivariate/_rotation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/multivariate/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/multivariate/backends/gpu_pca.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/_monotone.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/_objectives/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/_objectives/base.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/_objectives/cpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/_objectives/gpu_fp32.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/_objectives/gpu_fp64.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/_objectives/parameterizations.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/_utils.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/backends/_em_batched.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/backends/_em_batched_np.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/backends/_em_batched_patterns.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/backends/_em_batched_torch.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/backends/_squarem.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/backends/cpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/backends/em.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/backends/gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/datasets.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/mcar_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/patterns.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/mvnmle/solvers.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/ordinal/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/ordinal/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/ordinal/_likelihood.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/ordinal/_solver.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/ordinal/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/ordinal/backends/gpu_likelihood.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/ordinal/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/py.typed +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/regression/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/regression/_formatting.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/regression/_glm.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/regression/_linear.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/regression/_nb_theta.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/regression/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/regression/backends/cpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/regression/backends/cpu_glm.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/regression/backends/gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/regression/backends/gpu_glm.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/regression/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/regression/families.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/regression/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/regression/solvers.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/regression/terms.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/survival/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/survival/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/survival/_cox.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/survival/_discrete.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/survival/_km.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/survival/_logrank.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/survival/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/survival/backends/cpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/survival/backends/gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/survival/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/survival/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/survival/solvers.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/_acf.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/_arima_batch.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/_arima_factored.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/_arima_fit.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/_arima_forecast.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/_arima_kalman.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/_arima_likelihood.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/_arima_order.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/_decomposition.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/_differencing.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/_ets_fit.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/_ets_forecast.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/_ets_models.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/_stationarity.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/_whittle.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/backends/whittle_batch_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/pystatistics/timeseries/backends/whittle_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/anova/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/anova/conftest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/anova/test_contrasts.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/anova/test_design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/anova/test_factorial.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/anova/test_levene.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/anova/test_oneway.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/anova/test_posthoc.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/anova/test_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/anova/test_repeated_measures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/benchmark_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/conftest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/core/test_datasource.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/core/test_exceptions.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/core/test_result.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/core/test_torch_interop.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/core/test_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/descriptive/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/descriptive/conftest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/descriptive/test_cor.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/descriptive/test_cov.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/descriptive/test_describe.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/descriptive/test_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/descriptive/test_missing.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/descriptive/test_moments.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/descriptive/test_quantile.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/descriptive/test_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_ancova_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_ancova_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_bonferroni_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_bonferroni_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_eta_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_eta_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_levene_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_levene_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_oneway_balanced_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_oneway_balanced_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_oneway_unbalanced_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_oneway_unbalanced_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_rm_mixed_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_rm_mixed_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_rm_within_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_rm_within_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_tukey_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_tukey_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_twoway_balanced_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_twoway_balanced_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_twoway_unbalanced_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/anova_twoway_unbalanced_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/basic_100x3.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/basic_100x3_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/basic_100x3_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/collinear_almost.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/collinear_almost_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/collinear_almost_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_basic_100x5.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_basic_100x5_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_basic_100x5_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_constant_column.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_constant_column_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_constant_column_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_extreme_values.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_extreme_values_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_extreme_values_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_large_1000x10.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_large_1000x10_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_large_1000x10_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_nan_columnwise.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_nan_columnwise_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_nan_columnwise_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_nan_scattered.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_nan_scattered_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_nan_scattered_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_negative_correlation.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_negative_correlation_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_negative_correlation_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_perfect_correlation.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_perfect_correlation_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_perfect_correlation_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_single_column.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_single_column_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_single_column_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_ties.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_ties_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/desc_ties_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/different_scales.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/different_scales_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/different_scales_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/generate_anova_fixtures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/generate_descriptive_fixtures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/generate_fixtures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/generate_glm_fixtures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/generate_hypothesis_fixtures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/generate_mixed_fixtures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/generate_montecarlo_fixtures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/generate_survival_fixtures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_binomial_balanced.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_binomial_balanced_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_binomial_balanced_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_binomial_basic.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_binomial_basic_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_binomial_basic_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_binomial_large.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_binomial_large_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_binomial_large_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_binomial_separated.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_binomial_separated_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_binomial_separated_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_gaussian_basic.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_gaussian_basic_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_gaussian_basic_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_gaussian_large.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_gaussian_large_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_gaussian_large_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_poisson_basic.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_poisson_basic_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_poisson_basic_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_poisson_large_counts.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_poisson_large_counts_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_poisson_large_counts_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_poisson_zeros.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_poisson_zeros_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/glm_poisson_zeros_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/high_noise.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/high_noise_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/high_noise_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_chisq_2x2_yates_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_chisq_2x2_yates_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_chisq_3x3_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_chisq_3x3_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_chisq_gof_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_chisq_gof_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_chisq_gof_unequal_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_chisq_gof_unequal_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_fisher_2x2_less_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_fisher_2x2_less_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_fisher_2x2_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_fisher_2x2_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_fisher_3x3_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_fisher_3x3_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_ks_onesample_norm_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_ks_onesample_norm_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_ks_twosample_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_ks_twosample_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_prop_onesample_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_prop_onesample_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_prop_twosample_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_prop_twosample_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_t_onesample_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_t_onesample_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_t_paired_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_t_paired_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_t_pooled_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_t_pooled_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_t_welch_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_t_welch_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_var_basic_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_var_basic_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_wilcox_ranksum_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_wilcox_ranksum_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_wilcox_signed_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/htest_wilcox_signed_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/ill_conditioned.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/ill_conditioned_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/ill_conditioned_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/large_coeffs.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/large_coeffs_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/large_coeffs_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_boot_ci_90_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_boot_ci_90_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_boot_ci_normal_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_boot_ci_normal_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_boot_ci_skewed_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_boot_ci_skewed_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_boot_mean_balanced_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_boot_mean_balanced_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_boot_mean_ordinary_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_boot_mean_ordinary_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_boot_median_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_boot_median_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_boot_variance_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_boot_variance_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_perm_greater_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_perm_greater_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_perm_not_significant_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_perm_not_significant_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_perm_significant_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mc_perm_significant_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mixed/glmm_binomial.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mixed/glmm_poisson.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mixed/lmm_crossed.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mixed/lmm_intercept.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mixed/lmm_ml.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mixed/lmm_no_effect.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mixed/lmm_slope.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mixed/mixed_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/mixed/mixed_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/near_square.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/near_square_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/near_square_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/no_intercept.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/no_intercept_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/no_intercept_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/run_r_anova_validation.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/run_r_descriptive_validation.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/run_r_glm_validation.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/run_r_hypothesis_validation.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/run_r_mixed_validation.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/run_r_montecarlo_validation.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/run_r_survival_validation.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/run_r_validation.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/run_validation.sh +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/small_noise.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/small_noise_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/small_noise_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_cox_breslow_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_cox_breslow_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_cox_single_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_cox_single_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_cox_ties_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_cox_ties_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_cox_two_cov_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_cox_two_cov_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_km_basic_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_km_basic_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_km_heavy_cens_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_km_heavy_cens_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_km_loglog_ci_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_km_loglog_ci_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_km_no_cens_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_km_no_cens_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_km_plain_ci_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_km_plain_ci_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_km_ties_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_km_ties_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_lr_peto_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_lr_peto_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_lr_three_group_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_lr_three_group_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_lr_two_group_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/surv_lr_two_group_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/tall_skinny.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/tall_skinny_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/tall_skinny_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/fixtures/validate_against_r.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/gam/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/gam/test_gam.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/hypothesis/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/hypothesis/conftest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/hypothesis/test_chisq_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/hypothesis/test_design_split.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/hypothesis/test_fisher_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/hypothesis/test_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/hypothesis/test_ks_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/hypothesis/test_p_adjust.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/hypothesis/test_prop_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/hypothesis/test_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/hypothesis/test_t_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/hypothesis/test_var_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/hypothesis/test_wilcox_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mice/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mice/references/generate_mice_fixtures.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mice/references/mice_reference.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mice/references/mice_validation_complete.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mice/references/mice_validation_data.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mice/test_datasets.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mice/test_design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mice/test_methods.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mice/test_pooling.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mice/test_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mice/test_rng.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mice/test_visit.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mixed/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mixed/conftest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mixed/test_glmm.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mixed/test_lmm_crossed.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mixed/test_lmm_intercept.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mixed/test_lmm_nested.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mixed/test_lmm_slope.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mixed/test_pls.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mixed/test_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mixed/test_random_effects.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mixed/test_satterthwaite.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/montecarlo/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/montecarlo/conftest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/montecarlo/test_batched_solver.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/montecarlo/test_boot_ci.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/montecarlo/test_bootstrap.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/montecarlo/test_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/montecarlo/test_influence.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/montecarlo/test_permutation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/montecarlo/test_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/multinomial/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/multinomial/test_multinom.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/multivariate/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/multivariate/test_multivariate.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/references/apple_em_reference.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/references/apple_reference.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/references/generate_em_fixtures.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/references/little_mcar_apple.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/references/little_mcar_complete.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/references/little_mcar_extreme.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/references/little_mcar_missvals.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/references/little_mcar_simple_mcar.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/references/little_mcar_summary.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/references/missvals_em_reference.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/references/missvals_reference.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/references/small_test_reference.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/test_em.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/test_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/test_mcar.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/test_mlest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/test_monotone.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/test_no_silent_fallback.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/mvnmle/test_squarem.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/ordinal/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/ordinal/test_ordinal.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/regression/benchmark.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/regression/benchmark.r +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/regression/conftest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/regression/test_fit.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/regression/test_gamma_nb.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/regression/test_glm.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/regression/test_glm_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/regression/test_glm_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/regression/test_module_split.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/regression/test_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/regression/test_stress_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/regression/test_terms.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/regression/test_terms_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/survival/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/survival/conftest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/survival/test_coxph.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/survival/test_discrete_time.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/survival/test_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/survival/test_kaplan_meier.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/survival/test_logrank.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/survival/test_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/test_code_quality.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/timeseries/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/timeseries/test_acf_stationarity.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/timeseries/test_arima.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/timeseries/test_decomposition.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.0}/tests/timeseries/test_ets.py +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Unreleased Changes
|
|
2
|
+
|
|
3
|
+
> This file tracks all changes since the last stable release.
|
|
4
|
+
> Updated by whoever makes a change, on whatever machine.
|
|
5
|
+
> Synced via git so all sessions (Mac, Linux, etc.) see the same state.
|
|
6
|
+
>
|
|
7
|
+
> When ready to release, run: `python .release/release.py --status`
|
|
8
|
+
> and follow the manual release flow in the script docstring.
|
|
9
|
+
|
|
10
|
+
## Changes
|
|
11
|
+
|
|
12
|
+
- GPU backend for `mice` (CUDA). `mice(..., backend='gpu')` runs the `m`
|
|
13
|
+
imputation chains batched on the GPU as the leading tensor dimension: each
|
|
14
|
+
sweep step is a batched Bayesian linear solve (`torch.linalg.solve` + batched
|
|
15
|
+
Cholesky) and, for PMM, a batched nearest-neighbour donor search
|
|
16
|
+
(`(m, n_mis, n_obs)` distances → `topk`). `backend='auto'` selects CUDA when
|
|
17
|
+
available, else CPU (never MPS, matching the other modules). New `use_fp64`
|
|
18
|
+
argument runs the GPU path in double precision on CUDA (default FP32).
|
|
19
|
+
- GPU results match the CPU reference distributionally at the GPU/FP32 tolerance
|
|
20
|
+
tier (PMM donor copies are exact in FP64, exact-to-FP32 otherwise). Validated
|
|
21
|
+
in `tests/mice/test_gpu.py` against the CPU path rather than R directly.
|
|
22
|
+
- Measured PMM speedups vs the CPU backend on an RTX 5070 Ti: ~39× at n=1000
|
|
23
|
+
(p=8, m=20, maxit=8) and ~135× at n=3000 (p=10, m=20, maxit=8); the gain grows
|
|
24
|
+
with n because the donor search dominates and batches well on the GPU.
|
|
25
|
+
- Internal: the MICE backend contract now takes a `seed` (each backend spawns
|
|
26
|
+
its own RNG streams) instead of pre-spawned streams, so the CPU and GPU
|
|
27
|
+
backends share one `run()` signature. No public API change.
|
|
28
|
+
- MPS (Apple Silicon) is not yet validated for MICE; `backend='gpu'` raises a
|
|
29
|
+
clear error on MPS rather than running unverified. CUDA is supported.
|
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.4.0
|
|
4
|
+
|
|
5
|
+
GPU acceleration for MICE.
|
|
6
|
+
|
|
7
|
+
- **`mice(..., backend='gpu')` runs on CUDA GPUs.** The `m` imputation chains
|
|
8
|
+
run together on the GPU, with the per-variable linear solves and the
|
|
9
|
+
predictive-mean-matching donor search batched across chains. `backend='auto'`
|
|
10
|
+
uses a CUDA GPU when one is available and falls back to the CPU otherwise.
|
|
11
|
+
- **Large speedups on bigger problems.** Because the donor search dominates and
|
|
12
|
+
parallelises well, the GPU advantage grows with sample size — for example,
|
|
13
|
+
predictive mean matching was roughly 39× faster at n=1000 and 135× faster at
|
|
14
|
+
n=3000 than the CPU backend on an RTX 5070 Ti (m=20, maxit=8). GPU results
|
|
15
|
+
match the CPU backend at the standard GPU/FP32 tolerance.
|
|
16
|
+
- **`use_fp64=True`** runs the GPU path in double precision on CUDA for closer
|
|
17
|
+
agreement with the CPU reference (default is FP32, the fast path).
|
|
18
|
+
- GPU acceleration requires a CUDA GPU; Apple Silicon (MPS) is not yet supported
|
|
19
|
+
for MICE and is refused with a clear message rather than run unverified.
|
|
20
|
+
|
|
3
21
|
## 3.3.0
|
|
4
22
|
|
|
5
23
|
Multiple imputation by chained equations (MICE) for multivariate missing data.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pystatistics
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.4.0
|
|
4
4
|
Summary: GPU-accelerated statistical computing for Python
|
|
5
5
|
Project-URL: Homepage, https://sgcx.org/technology/pystatistics/
|
|
6
6
|
Project-URL: Documentation, https://sgcx.org/docs/pystatistics/
|
|
@@ -86,7 +86,7 @@ PyStatistics maintains two parallel computational paths with distinct goals:
|
|
|
86
86
|
| `multivariate/` | Complete | PCA and maximum likelihood factor analysis with varimax/promax rotation |
|
|
87
87
|
| `timeseries/` | Complete | ACF, PACF, ADF, KPSS, ETS, ARIMA, SARIMA, auto_arima, decompose, STL |
|
|
88
88
|
| `gam/` | Complete | Generalized additive models with penalized regression splines matching R mgcv::gam |
|
|
89
|
-
| `mice/` | Numeric
|
|
89
|
+
| `mice/` | Numeric | Multiple imputation by chained equations: PMM and Bayesian linear regression, Rubin's-rules pooling, validated against R mice; CUDA GPU backend |
|
|
90
90
|
|
|
91
91
|
See [docs/ROADMAP.md](docs/ROADMAP.md) for detailed scope, GPU applicability, and implementation priority for each module.
|
|
92
92
|
|
|
@@ -413,6 +413,17 @@ pip install pystatistics[dev]
|
|
|
413
413
|
|
|
414
414
|
## What's New
|
|
415
415
|
|
|
416
|
+
### 3.4.0 — GPU acceleration for MICE
|
|
417
|
+
|
|
418
|
+
- `mice(..., backend='gpu')` runs the imputation chains on a CUDA GPU, batching
|
|
419
|
+
the per-variable solves and the predictive-mean-matching donor search across
|
|
420
|
+
chains. `backend='auto'` uses a CUDA GPU when available, else the CPU.
|
|
421
|
+
- The speedup grows with sample size (the donor search dominates and batches
|
|
422
|
+
well): predictive mean matching ran ~39× faster at n=1000 and ~135× faster at
|
|
423
|
+
n=3000 than the CPU backend on an RTX 5070 Ti. GPU results match the CPU
|
|
424
|
+
backend at the GPU/FP32 tolerance; pass `use_fp64=True` for double precision.
|
|
425
|
+
- Requires a CUDA GPU; Apple Silicon (MPS) is not yet supported for MICE.
|
|
426
|
+
|
|
416
427
|
### 3.3.0 — Multiple imputation (MICE)
|
|
417
428
|
|
|
418
429
|
- New `mice` module: multiple imputation by chained equations for numeric data
|
|
@@ -39,7 +39,7 @@ PyStatistics maintains two parallel computational paths with distinct goals:
|
|
|
39
39
|
| `multivariate/` | Complete | PCA and maximum likelihood factor analysis with varimax/promax rotation |
|
|
40
40
|
| `timeseries/` | Complete | ACF, PACF, ADF, KPSS, ETS, ARIMA, SARIMA, auto_arima, decompose, STL |
|
|
41
41
|
| `gam/` | Complete | Generalized additive models with penalized regression splines matching R mgcv::gam |
|
|
42
|
-
| `mice/` | Numeric
|
|
42
|
+
| `mice/` | Numeric | Multiple imputation by chained equations: PMM and Bayesian linear regression, Rubin's-rules pooling, validated against R mice; CUDA GPU backend |
|
|
43
43
|
|
|
44
44
|
See [docs/ROADMAP.md](docs/ROADMAP.md) for detailed scope, GPU applicability, and implementation priority for each module.
|
|
45
45
|
|
|
@@ -366,6 +366,17 @@ pip install pystatistics[dev]
|
|
|
366
366
|
|
|
367
367
|
## What's New
|
|
368
368
|
|
|
369
|
+
### 3.4.0 — GPU acceleration for MICE
|
|
370
|
+
|
|
371
|
+
- `mice(..., backend='gpu')` runs the imputation chains on a CUDA GPU, batching
|
|
372
|
+
the per-variable solves and the predictive-mean-matching donor search across
|
|
373
|
+
chains. `backend='auto'` uses a CUDA GPU when available, else the CPU.
|
|
374
|
+
- The speedup grows with sample size (the donor search dominates and batches
|
|
375
|
+
well): predictive mean matching ran ~39× faster at n=1000 and ~135× faster at
|
|
376
|
+
n=3000 than the CPU backend on an RTX 5070 Ti. GPU results match the CPU
|
|
377
|
+
backend at the GPU/FP32 tolerance; pass `use_fp64=True` for double precision.
|
|
378
|
+
- Requires a CUDA GPU; Apple Silicon (MPS) is not yet supported for MICE.
|
|
379
|
+
|
|
369
380
|
### 3.3.0 — Multiple imputation (MICE)
|
|
370
381
|
|
|
371
382
|
- New `mice` module: multiple imputation by chained equations for numeric data
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Batched Bayesian linear-regression posterior draw on the GPU.
|
|
3
|
+
|
|
4
|
+
This is the GPU counterpart of ``methods/_linreg.py``: the same Bayesian draw,
|
|
5
|
+
but vectorized over the ``m`` imputation chains as the leading batch dimension.
|
|
6
|
+
At a given sweep step every chain is fitting the *same* target column on the
|
|
7
|
+
*same* observed rows, but with different predictor values (each chain imputed
|
|
8
|
+
the other columns differently), so we solve ``m`` independent linear systems at
|
|
9
|
+
once with batched cuBLAS/cuSOLVER kernels.
|
|
10
|
+
|
|
11
|
+
Posterior draw (identical model to the CPU path):
|
|
12
|
+
|
|
13
|
+
beta_hat = (X'X + ridge)^{-1} X'y batched solve
|
|
14
|
+
df = max(n_obs - n_params, 1) integer, shared by chains
|
|
15
|
+
sigma* = sqrt( RSS / chi2(df) ) chi2 = sum of df squared N(0,1)
|
|
16
|
+
beta* = beta_hat + sigma* * L z L L' = (X'X + ridge)^{-1}
|
|
17
|
+
|
|
18
|
+
The chi-square is built from standard normals (``df`` is a non-negative integer)
|
|
19
|
+
so the only randomness source is the seeded ``torch.Generator`` — no reliance on
|
|
20
|
+
``torch.distributions``, which ignores explicit generators.
|
|
21
|
+
|
|
22
|
+
All randomness flows through the passed generator (CLAUDE.md Rule 6). Results
|
|
23
|
+
match the CPU reference distributionally, at the GPU/FP32 tolerance tier — not
|
|
24
|
+
bit-for-bit (different RNG, single precision).
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from __future__ import annotations
|
|
28
|
+
|
|
29
|
+
from dataclasses import dataclass
|
|
30
|
+
|
|
31
|
+
# Matches the CPU ridge (methods/_linreg.py) — a tiny relative penalty keeping
|
|
32
|
+
# the batched Gram matrices invertible under FP32.
|
|
33
|
+
_DEFAULT_RIDGE = 1e-5
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass
|
|
37
|
+
class BatchedLinRegDraw:
|
|
38
|
+
"""Batched point estimate + posterior draw (leading dim = m chains)."""
|
|
39
|
+
|
|
40
|
+
beta_hat: "object" # (m, q+1) tensor
|
|
41
|
+
beta_draw: "object" # (m, q+1) tensor
|
|
42
|
+
sigma_draw: "object" # (m,) tensor
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def add_intercept(X):
|
|
46
|
+
"""Prepend a ones column to a batched predictor tensor (m, n, q) -> (m,n,q+1)."""
|
|
47
|
+
import torch
|
|
48
|
+
|
|
49
|
+
m, n, _ = X.shape
|
|
50
|
+
ones = torch.ones((m, n, 1), dtype=X.dtype, device=X.device)
|
|
51
|
+
return torch.cat([ones, X], dim=2)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def batched_bayes_linreg_draw(
|
|
55
|
+
y_obs,
|
|
56
|
+
X_obs,
|
|
57
|
+
gen,
|
|
58
|
+
ridge: float = _DEFAULT_RIDGE,
|
|
59
|
+
) -> BatchedLinRegDraw:
|
|
60
|
+
"""Draw once from the Gaussian linear-model posterior for every chain.
|
|
61
|
+
|
|
62
|
+
Parameters
|
|
63
|
+
----------
|
|
64
|
+
y_obs : (m, n_obs) tensor
|
|
65
|
+
Observed responses (identical across chains, batched for uniform ops).
|
|
66
|
+
X_obs : (m, n_obs, q) tensor
|
|
67
|
+
Observed predictors WITHOUT an intercept column (added internally).
|
|
68
|
+
gen : torch.Generator
|
|
69
|
+
Sole randomness source, on the same device as the tensors.
|
|
70
|
+
ridge : float
|
|
71
|
+
Relative ridge penalty on the diagonal of X'X.
|
|
72
|
+
"""
|
|
73
|
+
import torch
|
|
74
|
+
|
|
75
|
+
Xa = add_intercept(X_obs) # (m, n_obs, q+1)
|
|
76
|
+
m, n_obs, n_params = Xa.shape
|
|
77
|
+
dtype, device = Xa.dtype, Xa.device
|
|
78
|
+
|
|
79
|
+
Xt = Xa.transpose(1, 2) # (m, q+1, n_obs)
|
|
80
|
+
XtX = Xt @ Xa # (m, q+1, q+1)
|
|
81
|
+
|
|
82
|
+
diag = torch.diagonal(XtX, dim1=1, dim2=2) # (m, q+1)
|
|
83
|
+
diag_mean = diag.mean(dim=1).clamp_min(torch.finfo(dtype).tiny) # (m,)
|
|
84
|
+
eye = torch.eye(n_params, dtype=dtype, device=device)
|
|
85
|
+
XtX_ridge = XtX + ridge * diag_mean[:, None, None] * eye
|
|
86
|
+
|
|
87
|
+
Xty = Xt @ y_obs.unsqueeze(-1) # (m, q+1, 1)
|
|
88
|
+
beta_hat = torch.linalg.solve(XtX_ridge, Xty).squeeze(-1) # (m, q+1)
|
|
89
|
+
|
|
90
|
+
resid = y_obs - (Xa @ beta_hat.unsqueeze(-1)).squeeze(-1) # (m, n_obs)
|
|
91
|
+
rss = (resid * resid).sum(dim=1) # (m,)
|
|
92
|
+
df = max(n_obs - n_params, 1)
|
|
93
|
+
|
|
94
|
+
# chi2(df) = sum of df squared standard normals (df is an integer).
|
|
95
|
+
z_chi = torch.randn((m, df), generator=gen, dtype=dtype, device=device)
|
|
96
|
+
chi = (z_chi * z_chi).sum(dim=1).clamp_min(torch.finfo(dtype).tiny) # (m,)
|
|
97
|
+
sigma_draw = torch.where(
|
|
98
|
+
rss > 0, torch.sqrt(rss / chi), torch.zeros_like(rss)
|
|
99
|
+
) # (m,)
|
|
100
|
+
|
|
101
|
+
V = torch.linalg.inv(XtX_ridge) # (m, q+1, q+1)
|
|
102
|
+
L = _batched_safe_cholesky(V) # (m, q+1, q+1), L L' = V
|
|
103
|
+
z_beta = torch.randn((m, n_params), generator=gen, dtype=dtype, device=device)
|
|
104
|
+
beta_draw = beta_hat + sigma_draw[:, None] * (L @ z_beta.unsqueeze(-1)).squeeze(-1)
|
|
105
|
+
|
|
106
|
+
return BatchedLinRegDraw(
|
|
107
|
+
beta_hat=beta_hat, beta_draw=beta_draw, sigma_draw=sigma_draw
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _batched_safe_cholesky(V):
|
|
112
|
+
"""Lower Cholesky of each (symmetric PSD) matrix in a batch, with jitter.
|
|
113
|
+
|
|
114
|
+
``V`` is a batch of inverse-Gram matrices — positive definite in exact
|
|
115
|
+
arithmetic, but FP32 rounding can leave one marginally indefinite. We
|
|
116
|
+
symmetrize and add escalating jitter to the *whole batch* (cheap, keeps the
|
|
117
|
+
op batched) until ``cholesky_ex`` reports success for every matrix.
|
|
118
|
+
"""
|
|
119
|
+
import torch
|
|
120
|
+
|
|
121
|
+
Vs = 0.5 * (V + V.transpose(1, 2))
|
|
122
|
+
eye = torch.eye(Vs.shape[1], dtype=Vs.dtype, device=Vs.device)
|
|
123
|
+
diag = torch.diagonal(Vs, dim1=1, dim2=2)
|
|
124
|
+
scale = diag.mean().clamp_min(1.0).item()
|
|
125
|
+
|
|
126
|
+
jitter = 0.0
|
|
127
|
+
for _ in range(8):
|
|
128
|
+
M = Vs if jitter == 0.0 else Vs + jitter * eye
|
|
129
|
+
L, info = torch.linalg.cholesky_ex(M)
|
|
130
|
+
if not torch.any(info):
|
|
131
|
+
return L
|
|
132
|
+
jitter = scale * (1e-8 if jitter == 0.0 else 10.0 * jitter)
|
|
133
|
+
|
|
134
|
+
# Documented last resort (Rule 1): eigenvalue-clipped PSD factor. Reached
|
|
135
|
+
# only if a matrix is badly degenerate despite ridge + jitter.
|
|
136
|
+
w, Q = torch.linalg.eigh(Vs)
|
|
137
|
+
w = w.clamp_min(0.0)
|
|
138
|
+
return Q @ torch.diag_embed(torch.sqrt(w))
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Batched GPU imputation methods: ``norm`` and ``pmm``.
|
|
3
|
+
|
|
4
|
+
These mirror ``methods/norm.py`` and ``methods/pmm.py`` but operate on tensors
|
|
5
|
+
batched over the ``m`` chains. Each takes the observed/missing predictor blocks
|
|
6
|
+
for one target column across all chains and returns the imputed values for every
|
|
7
|
+
chain at once, so a whole sweep step is a handful of batched kernels.
|
|
8
|
+
|
|
9
|
+
The GPU backend dispatches to these by method name; a name with no GPU
|
|
10
|
+
implementation is refused by the backend (fail loud, Rule 1) rather than
|
|
11
|
+
silently downgraded.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from pystatistics.mice.backends._gpu_linreg import (
|
|
17
|
+
add_intercept,
|
|
18
|
+
batched_bayes_linreg_draw,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def gpu_norm_impute(y_obs, X_obs, X_mis, gen, *, donors=None):
|
|
23
|
+
"""Batched Bayesian linear-regression imputation (R ``norm``).
|
|
24
|
+
|
|
25
|
+
Parameters mirror the CPU method but are batched: ``y_obs`` (m, n_obs),
|
|
26
|
+
``X_obs`` (m, n_obs, q), ``X_mis`` (m, n_mis, q). Returns (m, n_mis).
|
|
27
|
+
``donors`` is accepted and ignored so the backend can call every method
|
|
28
|
+
with one uniform signature.
|
|
29
|
+
"""
|
|
30
|
+
import torch
|
|
31
|
+
|
|
32
|
+
draw = batched_bayes_linreg_draw(y_obs, X_obs, gen)
|
|
33
|
+
Xa_mis = add_intercept(X_mis)
|
|
34
|
+
yhat_mis = (Xa_mis @ draw.beta_draw.unsqueeze(-1)).squeeze(-1) # (m, n_mis)
|
|
35
|
+
noise = torch.randn(
|
|
36
|
+
yhat_mis.shape, generator=gen, dtype=yhat_mis.dtype, device=yhat_mis.device
|
|
37
|
+
)
|
|
38
|
+
return yhat_mis + draw.sigma_draw[:, None] * noise
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def gpu_pmm_impute(y_obs, X_obs, X_mis, gen, *, donors=5):
|
|
42
|
+
"""Batched predictive mean matching (R ``pmm``, matchtype=1).
|
|
43
|
+
|
|
44
|
+
Observed fitted values use ``beta_hat``; missing fitted values use the
|
|
45
|
+
posterior draw ``beta*``. For each missing row in each chain, pick one of
|
|
46
|
+
the ``k`` nearest observed fitted values at random and copy that observed
|
|
47
|
+
value. Returns (m, n_mis).
|
|
48
|
+
"""
|
|
49
|
+
import torch
|
|
50
|
+
|
|
51
|
+
draw = batched_bayes_linreg_draw(y_obs, X_obs, gen)
|
|
52
|
+
Xa_obs = add_intercept(X_obs)
|
|
53
|
+
Xa_mis = add_intercept(X_mis)
|
|
54
|
+
yhat_obs = (Xa_obs @ draw.beta_hat.unsqueeze(-1)).squeeze(-1) # (m, n_obs)
|
|
55
|
+
yhat_mis = (Xa_mis @ draw.beta_draw.unsqueeze(-1)).squeeze(-1) # (m, n_mis)
|
|
56
|
+
|
|
57
|
+
m, n_obs = yhat_obs.shape
|
|
58
|
+
n_mis = yhat_mis.shape[1]
|
|
59
|
+
k = min(donors, n_obs)
|
|
60
|
+
|
|
61
|
+
# |yhat_mis - yhat_obs| for every (chain, missing row, observed row).
|
|
62
|
+
dist = (yhat_mis[:, :, None] - yhat_obs[:, None, :]).abs() # (m, n_mis, n_obs)
|
|
63
|
+
# k nearest observed fitted values (indices into n_obs).
|
|
64
|
+
_, cand = torch.topk(dist, k, dim=2, largest=False) # (m, n_mis, k)
|
|
65
|
+
|
|
66
|
+
# One random donor per (chain, missing row) among its k candidates.
|
|
67
|
+
pick = torch.randint(
|
|
68
|
+
0, k, (m, n_mis), generator=gen, device=yhat_obs.device
|
|
69
|
+
) # (m, n_mis)
|
|
70
|
+
donor_idx = torch.gather(cand, 2, pick.unsqueeze(-1)).squeeze(-1) # (m, n_mis)
|
|
71
|
+
|
|
72
|
+
# Copy the observed donor values (gather along the observed-row axis).
|
|
73
|
+
return torch.gather(y_obs, 1, donor_idx) # (m, n_mis)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# Method-name -> batched implementation. The backend translates the design's
|
|
77
|
+
# per-column method name through this table; unknown names are refused there.
|
|
78
|
+
GPU_METHODS = {
|
|
79
|
+
"norm": gpu_norm_impute,
|
|
80
|
+
"pmm": gpu_pmm_impute,
|
|
81
|
+
}
|
|
@@ -17,6 +17,7 @@ import numpy as np
|
|
|
17
17
|
from pystatistics.core.compute.timing import Timer
|
|
18
18
|
from pystatistics.core.result import Result
|
|
19
19
|
from pystatistics.mice._chain import run_chain
|
|
20
|
+
from pystatistics.mice._rng import spawn_streams
|
|
20
21
|
from pystatistics.mice.design import MICEDesign
|
|
21
22
|
from pystatistics.mice.solution import MICEParams
|
|
22
23
|
|
|
@@ -35,7 +36,7 @@ class CPUMiceBackend:
|
|
|
35
36
|
m: int,
|
|
36
37
|
maxit: int,
|
|
37
38
|
visit_sequence: tuple[int, ...],
|
|
38
|
-
|
|
39
|
+
seed: int,
|
|
39
40
|
) -> Result[MICEParams]:
|
|
40
41
|
"""Run ``m`` chains and package the imputations.
|
|
41
42
|
|
|
@@ -48,13 +49,15 @@ class CPUMiceBackend:
|
|
|
48
49
|
Iterations per chain.
|
|
49
50
|
visit_sequence : tuple of int
|
|
50
51
|
Column visit order within each iteration.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
seed : int
|
|
53
|
+
Master RNG seed. The backend spawns one independent, reproducible
|
|
54
|
+
stream per chain from it.
|
|
54
55
|
"""
|
|
55
56
|
timer = Timer()
|
|
56
57
|
timer.start()
|
|
57
58
|
|
|
59
|
+
streams = spawn_streams(seed, m)
|
|
60
|
+
|
|
58
61
|
completed = np.empty((m, design.n, design.p), dtype=np.float64)
|
|
59
62
|
chain_means = np.empty((m, maxit, len(design.incomplete_columns)))
|
|
60
63
|
chain_vars = np.empty((m, maxit, len(design.incomplete_columns)))
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"""
|
|
2
|
+
GPU backend for MICE.
|
|
3
|
+
|
|
4
|
+
Implements the same ``run`` entrypoint as the CPU backend, but runs all ``m``
|
|
5
|
+
imputation chains concurrently on a CUDA GPU with the chain index as the leading
|
|
6
|
+
tensor batch dimension. Each sweep step — visit column ``j``, fit its method on
|
|
7
|
+
the observed rows, overwrite its missing cells — becomes a handful of batched
|
|
8
|
+
kernels across the ``m`` chains (batched linear solves + Cholesky, and for PMM a
|
|
9
|
+
batched nearest-neighbour donor search).
|
|
10
|
+
|
|
11
|
+
Why batch over chains: the ``m`` chains are statistically independent and share
|
|
12
|
+
the missingness pattern, so they have identical shapes at every step — an ideal
|
|
13
|
+
batch. The sweep stays sequential *within* a chain (column ``j`` depends on the
|
|
14
|
+
columns imputed before it), which is inherent to chained equations.
|
|
15
|
+
|
|
16
|
+
Validation tier: GPU results match the CPU reference distributionally at the
|
|
17
|
+
``GPU_FP32`` tolerance, not bit-for-bit (FP32 + a different RNG). FP64 is
|
|
18
|
+
available on CUDA (``use_fp64=True``) for closer parity.
|
|
19
|
+
|
|
20
|
+
Determinism: a single seeded ``torch.Generator`` on the device is the only
|
|
21
|
+
randomness source. Given the same seed and device, a run reproduces its own
|
|
22
|
+
output to within FP32 kernel non-determinism.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
from pystatistics.core.compute.timing import Timer
|
|
28
|
+
from pystatistics.core.compute.torch_interop import to_host_f64
|
|
29
|
+
from pystatistics.core.exceptions import ValidationError
|
|
30
|
+
from pystatistics.core.result import Result
|
|
31
|
+
from pystatistics.mice.backends._gpu_methods import GPU_METHODS
|
|
32
|
+
from pystatistics.mice.design import MICEDesign
|
|
33
|
+
from pystatistics.mice.solution import MICEParams
|
|
34
|
+
|
|
35
|
+
# R mice default donor count for PMM (the design does not carry a per-column
|
|
36
|
+
# donor count, so the GPU path uses the same default as the CPU PMMMethod).
|
|
37
|
+
_PMM_DONORS = 5
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class GPUMiceBackend:
|
|
41
|
+
"""Runs MICE chains batched on a CUDA GPU."""
|
|
42
|
+
|
|
43
|
+
def __init__(self, device: str = "cuda", use_fp64: bool = False):
|
|
44
|
+
self.device = device
|
|
45
|
+
self.use_fp64 = use_fp64
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def name(self) -> str:
|
|
49
|
+
return f"gpu_{'fp64' if self.use_fp64 else 'fp32'}"
|
|
50
|
+
|
|
51
|
+
def run(
|
|
52
|
+
self,
|
|
53
|
+
design: MICEDesign,
|
|
54
|
+
*,
|
|
55
|
+
m: int,
|
|
56
|
+
maxit: int,
|
|
57
|
+
visit_sequence: tuple[int, ...],
|
|
58
|
+
seed: int,
|
|
59
|
+
) -> Result[MICEParams]:
|
|
60
|
+
import torch
|
|
61
|
+
|
|
62
|
+
# Validate that every incomplete column's method has a GPU kernel before
|
|
63
|
+
# touching the device (fail loud at the boundary, Rule 2).
|
|
64
|
+
for j in design.incomplete_columns:
|
|
65
|
+
meth = design.method_for(j)
|
|
66
|
+
if meth not in GPU_METHODS:
|
|
67
|
+
raise ValidationError(
|
|
68
|
+
f"Method {meth!r} (column {j}) has no GPU implementation. "
|
|
69
|
+
f"GPU methods: {sorted(GPU_METHODS)}. Use backend='cpu'."
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
timer = Timer()
|
|
73
|
+
timer.start()
|
|
74
|
+
|
|
75
|
+
dtype = torch.float64 if self.use_fp64 else torch.float32
|
|
76
|
+
dev = torch.device(self.device)
|
|
77
|
+
gen = torch.Generator(device=dev)
|
|
78
|
+
gen.manual_seed(int(seed))
|
|
79
|
+
|
|
80
|
+
n, p = design.n, design.p
|
|
81
|
+
incomplete = design.incomplete_columns
|
|
82
|
+
incomplete_pos = {j: k for k, j in enumerate(incomplete)}
|
|
83
|
+
|
|
84
|
+
with timer.section("transfer"):
|
|
85
|
+
base = torch.as_tensor(design.data, device=dev, dtype=dtype) # (n, p)
|
|
86
|
+
mask = torch.as_tensor(design.missing_mask, device=dev) # (n, p)
|
|
87
|
+
# m independent copies of the data (chains diverge after init).
|
|
88
|
+
data = base.unsqueeze(0).repeat(m, 1, 1) # (m, n, p)
|
|
89
|
+
|
|
90
|
+
# Precompute per-incomplete-column index tensors (shared by all chains).
|
|
91
|
+
obs_idx, mis_idx, pred_idx = {}, {}, {}
|
|
92
|
+
for j in incomplete:
|
|
93
|
+
mcol = mask[:, j]
|
|
94
|
+
obs_idx[j] = torch.nonzero(~mcol, as_tuple=False).squeeze(1)
|
|
95
|
+
mis_idx[j] = torch.nonzero(mcol, as_tuple=False).squeeze(1)
|
|
96
|
+
pred_idx[j] = torch.tensor(
|
|
97
|
+
[c for c in range(p) if c != j], device=dev, dtype=torch.long
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
with timer.section("init"):
|
|
101
|
+
self._initialise(data, base, obs_idx, mis_idx, incomplete, m, gen, dev)
|
|
102
|
+
|
|
103
|
+
chain_mean = torch.empty((m, maxit, len(incomplete)), dtype=dtype, device=dev)
|
|
104
|
+
chain_var = torch.empty((m, maxit, len(incomplete)), dtype=dtype, device=dev)
|
|
105
|
+
|
|
106
|
+
with timer.section("sweep"):
|
|
107
|
+
for it in range(maxit):
|
|
108
|
+
for j in visit_sequence:
|
|
109
|
+
method_fn = GPU_METHODS[design.method_for(j)]
|
|
110
|
+
X = data[:, :, pred_idx[j]] # (m, n, q)
|
|
111
|
+
X_obs = X[:, obs_idx[j], :] # (m, n_obs, q)
|
|
112
|
+
X_mis = X[:, mis_idx[j], :] # (m, n_mis, q)
|
|
113
|
+
y_obs = data[:, obs_idx[j], j] # (m, n_obs)
|
|
114
|
+
|
|
115
|
+
imputed = method_fn(
|
|
116
|
+
y_obs, X_obs, X_mis, gen, donors=_PMM_DONORS
|
|
117
|
+
)
|
|
118
|
+
data[:, mis_idx[j], j] = imputed
|
|
119
|
+
|
|
120
|
+
for j in incomplete:
|
|
121
|
+
cells = data[:, mis_idx[j], j] # (m, n_mis)
|
|
122
|
+
k = incomplete_pos[j]
|
|
123
|
+
chain_mean[:, it, k] = cells.mean(dim=1)
|
|
124
|
+
chain_var[:, it, k] = cells.var(dim=1, unbiased=False)
|
|
125
|
+
|
|
126
|
+
with timer.section("download"):
|
|
127
|
+
completed = to_host_f64(data)
|
|
128
|
+
chain_mean_host = to_host_f64(chain_mean)
|
|
129
|
+
chain_var_host = to_host_f64(chain_var)
|
|
130
|
+
|
|
131
|
+
timer.stop()
|
|
132
|
+
|
|
133
|
+
params = MICEParams(
|
|
134
|
+
completed=completed,
|
|
135
|
+
chain_mean=chain_mean_host,
|
|
136
|
+
chain_var=chain_var_host,
|
|
137
|
+
incomplete_columns=incomplete,
|
|
138
|
+
m=m,
|
|
139
|
+
maxit=maxit,
|
|
140
|
+
visit_sequence=visit_sequence,
|
|
141
|
+
)
|
|
142
|
+
return Result(
|
|
143
|
+
params=params,
|
|
144
|
+
info={
|
|
145
|
+
"method": "chained_equations",
|
|
146
|
+
"m": m,
|
|
147
|
+
"maxit": maxit,
|
|
148
|
+
"device": self.device,
|
|
149
|
+
"precision": "fp64" if self.use_fp64 else "fp32",
|
|
150
|
+
"visit_sequence": list(visit_sequence),
|
|
151
|
+
},
|
|
152
|
+
timing=timer.result(),
|
|
153
|
+
backend_name=self.name,
|
|
154
|
+
warnings=(),
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
@staticmethod
|
|
158
|
+
def _initialise(data, base, obs_idx, mis_idx, incomplete, m, gen, dev):
|
|
159
|
+
"""Fill missing cells by sampling observed values of the same column,
|
|
160
|
+
independently per chain. Mutates ``data`` in place."""
|
|
161
|
+
import torch
|
|
162
|
+
|
|
163
|
+
for j in incomplete:
|
|
164
|
+
observed = base[obs_idx[j], j] # (n_obs,)
|
|
165
|
+
n_obs = observed.shape[0]
|
|
166
|
+
n_mis = mis_idx[j].shape[0]
|
|
167
|
+
draw_idx = torch.randint(
|
|
168
|
+
0, n_obs, (m, n_mis), generator=gen, device=dev
|
|
169
|
+
)
|
|
170
|
+
data[:, mis_idx[j], j] = observed[draw_idx]
|
|
@@ -20,7 +20,6 @@ import warnings
|
|
|
20
20
|
from typing import Literal, Mapping, Sequence
|
|
21
21
|
|
|
22
22
|
from pystatistics.core.compute.device import select_device
|
|
23
|
-
from pystatistics.mice._rng import spawn_streams
|
|
24
23
|
from pystatistics.mice._visit import resolve_visit_sequence
|
|
25
24
|
from pystatistics.mice.design import MICEDesign
|
|
26
25
|
from pystatistics.mice.solution import MICESolution
|
|
@@ -38,6 +37,7 @@ def mice(
|
|
|
38
37
|
methods: Mapping | Sequence[str] | None = None,
|
|
39
38
|
visit_sequence: Sequence[int] | None = None,
|
|
40
39
|
backend: BackendChoice | None = None,
|
|
40
|
+
use_fp64: bool = False,
|
|
41
41
|
verbose: bool = False,
|
|
42
42
|
) -> MICESolution:
|
|
43
43
|
"""Multiple imputation by chained equations (numeric columns, CPU).
|
|
@@ -64,8 +64,14 @@ def mice(
|
|
|
64
64
|
Column visit order within each iteration. Defaults to incomplete
|
|
65
65
|
columns in ascending index order (R "roman" default).
|
|
66
66
|
backend : {'cpu', 'gpu', 'auto'} or None
|
|
67
|
-
Compute backend. Default None -> 'cpu'
|
|
68
|
-
|
|
67
|
+
Compute backend. Default None -> 'cpu' (the R-validated reference path).
|
|
68
|
+
'gpu' runs the chains batched on a CUDA GPU; 'auto' uses CUDA when
|
|
69
|
+
available, else CPU. GPU results match the CPU backend at the GPU/FP32
|
|
70
|
+
tolerance tier.
|
|
71
|
+
use_fp64 : bool
|
|
72
|
+
Only relevant on the GPU. Run the GPU chains in double precision (CUDA
|
|
73
|
+
only) for closer parity with the CPU reference. Default False (FP32,
|
|
74
|
+
the fast consumer-GPU path). Ignored on CPU (always double precision).
|
|
69
75
|
verbose : bool
|
|
70
76
|
Print progress information.
|
|
71
77
|
|
|
@@ -105,8 +111,7 @@ def mice(
|
|
|
105
111
|
)
|
|
106
112
|
|
|
107
113
|
visit = resolve_visit_sequence(design.incomplete_columns, visit_sequence)
|
|
108
|
-
backend_impl = _get_backend(backend)
|
|
109
|
-
streams = spawn_streams(seed, m)
|
|
114
|
+
backend_impl = _get_backend(backend, use_fp64)
|
|
110
115
|
|
|
111
116
|
if verbose:
|
|
112
117
|
print(
|
|
@@ -116,7 +121,7 @@ def mice(
|
|
|
116
121
|
)
|
|
117
122
|
|
|
118
123
|
result = backend_impl.run(
|
|
119
|
-
design, m=m, maxit=maxit, visit_sequence=visit,
|
|
124
|
+
design, m=m, maxit=maxit, visit_sequence=visit, seed=seed
|
|
120
125
|
)
|
|
121
126
|
|
|
122
127
|
if verbose:
|
|
@@ -125,30 +130,41 @@ def mice(
|
|
|
125
130
|
return MICESolution(_result=result, _design=design)
|
|
126
131
|
|
|
127
132
|
|
|
128
|
-
def _get_backend(choice: BackendChoice | None):
|
|
129
|
-
"""Resolve the compute backend.
|
|
133
|
+
def _get_backend(choice: BackendChoice | None, use_fp64: bool):
|
|
134
|
+
"""Resolve the compute backend.
|
|
135
|
+
|
|
136
|
+
None/'cpu' -> CPU. 'gpu' -> CUDA GPU (raises on MPS, which is not yet
|
|
137
|
+
validated for MICE). 'auto' -> CUDA when available, else CPU; like the
|
|
138
|
+
other pystatistics modules, 'auto' never selects MPS.
|
|
139
|
+
"""
|
|
130
140
|
if choice is None or choice == "cpu":
|
|
131
141
|
from pystatistics.mice.backends.cpu import CPUMiceBackend
|
|
132
142
|
|
|
133
143
|
return CPUMiceBackend()
|
|
134
144
|
|
|
135
145
|
if choice == "auto":
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
146
|
+
device = select_device("auto")
|
|
147
|
+
if device.device_type == "cuda":
|
|
148
|
+
from pystatistics.mice.backends.gpu import GPUMiceBackend
|
|
149
|
+
|
|
150
|
+
return GPUMiceBackend(device="cuda", use_fp64=use_fp64)
|
|
151
|
+
# CPU, or MPS (never auto-selected): use the CPU reference path.
|
|
139
152
|
from pystatistics.mice.backends.cpu import CPUMiceBackend
|
|
140
153
|
|
|
141
154
|
return CPUMiceBackend()
|
|
142
155
|
|
|
143
156
|
if choice == "gpu":
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
157
|
+
device = select_device("gpu") # raises RuntimeError if no GPU
|
|
158
|
+
if device.device_type == "mps":
|
|
159
|
+
raise NotImplementedError(
|
|
160
|
+
"backend='gpu' for MICE is validated on CUDA only in this "
|
|
161
|
+
"release. The chained-equations sweep has not been validated "
|
|
162
|
+
"on Apple Silicon (MPS), so it is refused rather than run "
|
|
163
|
+
"unverified. Use backend='cpu' (the default) on a Mac; CUDA "
|
|
164
|
+
"GPUs are supported."
|
|
165
|
+
)
|
|
166
|
+
from pystatistics.mice.backends.gpu import GPUMiceBackend
|
|
167
|
+
|
|
168
|
+
return GPUMiceBackend(device=device.device_type, use_fp64=use_fp64)
|
|
153
169
|
|
|
154
170
|
raise ValueError(f"Unknown backend: {choice!r}")
|