pystatistics 3.3.0__tar.gz → 3.4.1__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.1/.release/UNRELEASED.md +23 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/CHANGELOG.md +33 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/PKG-INFO +22 -2
- {pystatistics-3.3.0 → pystatistics-3.4.1}/README.md +21 -1
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pyproject.toml +1 -1
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/__init__.py +1 -1
- pystatistics-3.4.1/pystatistics/mice/backends/_gpu_linreg.py +138 -0
- pystatistics-3.4.1/pystatistics/mice/backends/_gpu_methods.py +81 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/backends/cpu.py +7 -4
- pystatistics-3.4.1/pystatistics/mice/backends/gpu.py +170 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/methods/pmm.py +32 -11
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/solvers.py +36 -20
- pystatistics-3.4.1/tests/mice/test_gpu.py +146 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mice/test_methods.py +29 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mice/test_mice.py +16 -3
- pystatistics-3.3.0/.release/UNRELEASED.md +0 -30
- {pystatistics-3.3.0 → pystatistics-3.4.1}/.github/workflows/publish.yml +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/.github/workflows/trigger-docs-rebuild.yml +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/.gitignore +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/.release/CHECKLIST.md +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/.release/release.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/CLAUDE.md +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/LICENSE +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/benchmarks/mvnmle_bench.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/DESIGN.md +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/Forge.md +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/GPU_BACKEND_NOTES.md +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/Makefile +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/PYSTATSBIO_CONTEXT.md +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/ROADMAP.md +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/_static/custom.css +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/anova.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/conf.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/core.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/descriptive.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/gam.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/hypothesis.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/index.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/mixed.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/montecarlo.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/multinomial.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/multivariate.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/mvnmle.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/ordinal.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/regression.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/survival.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/docs/timeseries.rst +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/GPU_BACKEND_CONVENTION.md +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/anova/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/anova/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/anova/_contrasts.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/anova/_levene.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/anova/_posthoc.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/anova/_repeated.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/anova/_ss.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/anova/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/anova/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/anova/solvers.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/capabilities.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/compute/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/compute/device.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/compute/linalg/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/compute/linalg/batched.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/compute/linalg/cholesky.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/compute/linalg/determinant.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/compute/linalg/qr.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/compute/linalg/solve.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/compute/linalg/svd.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/compute/optimization/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/compute/optimization/convergence.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/compute/precision.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/compute/timing.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/compute/tolerances.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/compute/torch_interop.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/datasource.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/encoding.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/exceptions.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/protocols.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/result.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/core/validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/descriptive/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/descriptive/_missing.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/descriptive/_quantile_types.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/descriptive/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/descriptive/backends/cpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/descriptive/backends/gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/descriptive/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/descriptive/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/descriptive/solvers.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/gam/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/gam/_basis.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/gam/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/gam/_fit.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/gam/_gam.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/gam/_gcv.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/gam/_smooth.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/gam/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/gam/backends/_gpu_family.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/gam/backends/gpu_pirls.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/gam/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/_design_factories.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/_p_adjust.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/backends/_chisq_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/backends/_fisher_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/backends/_ks_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/backends/_prop_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/backends/_t_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/backends/_var_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/backends/_wilcox_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/backends/cpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/backends/gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/hypothesis/solvers.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/_chain.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/_rng.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/_visit.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/datasets.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/methods/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/methods/_linreg.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/methods/base.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/methods/norm.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/methods/registry.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/pooling.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mice/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mixed/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mixed/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mixed/_deviance.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mixed/_pirls.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mixed/_pls.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mixed/_random_effects.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mixed/_satterthwaite.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mixed/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mixed/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mixed/solvers.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/montecarlo/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/montecarlo/_ci.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/montecarlo/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/montecarlo/_influence.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/montecarlo/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/montecarlo/backends/cpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/montecarlo/backends/gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/montecarlo/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/montecarlo/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/montecarlo/solvers.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/multinomial/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/multinomial/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/multinomial/_likelihood.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/multinomial/_solver.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/multinomial/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/multinomial/backends/gpu_likelihood.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/multinomial/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/multivariate/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/multivariate/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/multivariate/_factor.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/multivariate/_pca.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/multivariate/_rotation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/multivariate/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/multivariate/backends/gpu_pca.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/_monotone.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/_objectives/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/_objectives/base.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/_objectives/cpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/_objectives/gpu_fp32.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/_objectives/gpu_fp64.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/_objectives/parameterizations.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/_utils.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/backends/_em_batched.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/backends/_em_batched_np.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/backends/_em_batched_patterns.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/backends/_em_batched_torch.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/backends/_squarem.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/backends/cpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/backends/em.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/backends/gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/datasets.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/mcar_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/patterns.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/mvnmle/solvers.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/ordinal/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/ordinal/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/ordinal/_likelihood.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/ordinal/_solver.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/ordinal/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/ordinal/backends/gpu_likelihood.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/ordinal/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/py.typed +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/regression/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/regression/_formatting.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/regression/_glm.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/regression/_linear.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/regression/_nb_theta.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/regression/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/regression/backends/cpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/regression/backends/cpu_glm.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/regression/backends/gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/regression/backends/gpu_glm.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/regression/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/regression/families.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/regression/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/regression/solvers.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/regression/terms.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/survival/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/survival/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/survival/_cox.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/survival/_discrete.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/survival/_km.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/survival/_logrank.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/survival/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/survival/backends/cpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/survival/backends/gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/survival/design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/survival/solution.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/survival/solvers.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/_acf.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/_arima_batch.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/_arima_factored.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/_arima_fit.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/_arima_forecast.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/_arima_kalman.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/_arima_likelihood.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/_arima_order.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/_common.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/_decomposition.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/_differencing.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/_ets_fit.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/_ets_forecast.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/_ets_models.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/_stationarity.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/_whittle.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/backends/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/backends/whittle_batch_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/pystatistics/timeseries/backends/whittle_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/anova/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/anova/conftest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/anova/test_contrasts.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/anova/test_design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/anova/test_factorial.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/anova/test_levene.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/anova/test_oneway.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/anova/test_posthoc.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/anova/test_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/anova/test_repeated_measures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/benchmark_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/conftest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/core/test_datasource.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/core/test_exceptions.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/core/test_result.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/core/test_torch_interop.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/core/test_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/descriptive/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/descriptive/conftest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/descriptive/test_cor.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/descriptive/test_cov.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/descriptive/test_describe.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/descriptive/test_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/descriptive/test_missing.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/descriptive/test_moments.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/descriptive/test_quantile.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/descriptive/test_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_ancova_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_ancova_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_bonferroni_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_bonferroni_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_eta_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_eta_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_levene_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_levene_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_oneway_balanced_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_oneway_balanced_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_oneway_unbalanced_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_oneway_unbalanced_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_rm_mixed_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_rm_mixed_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_rm_within_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_rm_within_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_tukey_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_tukey_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_twoway_balanced_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_twoway_balanced_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_twoway_unbalanced_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/anova_twoway_unbalanced_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/basic_100x3.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/basic_100x3_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/basic_100x3_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/collinear_almost.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/collinear_almost_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/collinear_almost_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_basic_100x5.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_basic_100x5_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_basic_100x5_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_constant_column.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_constant_column_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_constant_column_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_extreme_values.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_extreme_values_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_extreme_values_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_large_1000x10.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_large_1000x10_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_large_1000x10_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_nan_columnwise.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_nan_columnwise_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_nan_columnwise_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_nan_scattered.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_nan_scattered_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_nan_scattered_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_negative_correlation.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_negative_correlation_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_negative_correlation_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_perfect_correlation.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_perfect_correlation_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_perfect_correlation_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_single_column.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_single_column_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_single_column_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_ties.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_ties_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/desc_ties_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/different_scales.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/different_scales_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/different_scales_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/generate_anova_fixtures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/generate_descriptive_fixtures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/generate_fixtures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/generate_glm_fixtures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/generate_hypothesis_fixtures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/generate_mixed_fixtures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/generate_montecarlo_fixtures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/generate_survival_fixtures.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_binomial_balanced.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_binomial_balanced_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_binomial_balanced_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_binomial_basic.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_binomial_basic_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_binomial_basic_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_binomial_large.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_binomial_large_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_binomial_large_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_binomial_separated.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_binomial_separated_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_binomial_separated_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_gaussian_basic.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_gaussian_basic_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_gaussian_basic_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_gaussian_large.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_gaussian_large_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_gaussian_large_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_poisson_basic.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_poisson_basic_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_poisson_basic_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_poisson_large_counts.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_poisson_large_counts_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_poisson_large_counts_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_poisson_zeros.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_poisson_zeros_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/glm_poisson_zeros_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/high_noise.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/high_noise_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/high_noise_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_chisq_2x2_yates_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_chisq_2x2_yates_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_chisq_3x3_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_chisq_3x3_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_chisq_gof_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_chisq_gof_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_chisq_gof_unequal_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_chisq_gof_unequal_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_fisher_2x2_less_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_fisher_2x2_less_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_fisher_2x2_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_fisher_2x2_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_fisher_3x3_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_fisher_3x3_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_ks_onesample_norm_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_ks_onesample_norm_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_ks_twosample_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_ks_twosample_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_prop_onesample_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_prop_onesample_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_prop_twosample_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_prop_twosample_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_t_onesample_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_t_onesample_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_t_paired_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_t_paired_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_t_pooled_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_t_pooled_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_t_welch_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_t_welch_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_var_basic_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_var_basic_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_wilcox_ranksum_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_wilcox_ranksum_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_wilcox_signed_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/htest_wilcox_signed_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/ill_conditioned.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/ill_conditioned_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/ill_conditioned_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/large_coeffs.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/large_coeffs_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/large_coeffs_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_boot_ci_90_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_boot_ci_90_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_boot_ci_normal_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_boot_ci_normal_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_boot_ci_skewed_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_boot_ci_skewed_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_boot_mean_balanced_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_boot_mean_balanced_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_boot_mean_ordinary_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_boot_mean_ordinary_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_boot_median_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_boot_median_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_boot_variance_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_boot_variance_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_perm_greater_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_perm_greater_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_perm_not_significant_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_perm_not_significant_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_perm_significant_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mc_perm_significant_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mixed/glmm_binomial.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mixed/glmm_poisson.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mixed/lmm_crossed.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mixed/lmm_intercept.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mixed/lmm_ml.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mixed/lmm_no_effect.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mixed/lmm_slope.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mixed/mixed_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/mixed/mixed_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/near_square.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/near_square_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/near_square_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/no_intercept.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/no_intercept_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/no_intercept_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/run_r_anova_validation.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/run_r_descriptive_validation.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/run_r_glm_validation.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/run_r_hypothesis_validation.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/run_r_mixed_validation.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/run_r_montecarlo_validation.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/run_r_survival_validation.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/run_r_validation.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/run_validation.sh +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/small_noise.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/small_noise_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/small_noise_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_cox_breslow_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_cox_breslow_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_cox_single_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_cox_single_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_cox_ties_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_cox_ties_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_cox_two_cov_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_cox_two_cov_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_km_basic_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_km_basic_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_km_heavy_cens_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_km_heavy_cens_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_km_loglog_ci_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_km_loglog_ci_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_km_no_cens_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_km_no_cens_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_km_plain_ci_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_km_plain_ci_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_km_ties_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_km_ties_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_lr_peto_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_lr_peto_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_lr_three_group_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_lr_three_group_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_lr_two_group_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/surv_lr_two_group_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/tall_skinny.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/tall_skinny_meta.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/tall_skinny_r_results.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/fixtures/validate_against_r.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/gam/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/gam/test_gam.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/hypothesis/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/hypothesis/conftest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/hypothesis/test_chisq_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/hypothesis/test_design_split.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/hypothesis/test_fisher_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/hypothesis/test_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/hypothesis/test_ks_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/hypothesis/test_p_adjust.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/hypothesis/test_prop_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/hypothesis/test_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/hypothesis/test_t_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/hypothesis/test_var_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/hypothesis/test_wilcox_test.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mice/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mice/references/generate_mice_fixtures.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mice/references/mice_reference.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mice/references/mice_validation_complete.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mice/references/mice_validation_data.csv +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mice/test_datasets.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mice/test_design.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mice/test_pooling.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mice/test_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mice/test_rng.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mice/test_visit.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mixed/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mixed/conftest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mixed/test_glmm.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mixed/test_lmm_crossed.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mixed/test_lmm_intercept.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mixed/test_lmm_nested.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mixed/test_lmm_slope.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mixed/test_pls.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mixed/test_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mixed/test_random_effects.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mixed/test_satterthwaite.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/montecarlo/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/montecarlo/conftest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/montecarlo/test_batched_solver.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/montecarlo/test_boot_ci.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/montecarlo/test_bootstrap.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/montecarlo/test_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/montecarlo/test_influence.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/montecarlo/test_permutation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/montecarlo/test_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/multinomial/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/multinomial/test_multinom.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/multivariate/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/multivariate/test_multivariate.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/references/apple_em_reference.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/references/apple_reference.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/references/generate_em_fixtures.R +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/references/little_mcar_apple.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/references/little_mcar_complete.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/references/little_mcar_extreme.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/references/little_mcar_missvals.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/references/little_mcar_simple_mcar.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/references/little_mcar_summary.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/references/missvals_em_reference.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/references/missvals_reference.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/references/small_test_reference.json +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/test_em.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/test_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/test_mcar.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/test_mlest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/test_monotone.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/test_no_silent_fallback.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/mvnmle/test_squarem.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/ordinal/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/ordinal/test_ordinal.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/regression/benchmark.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/regression/benchmark.r +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/regression/conftest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/regression/test_fit.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/regression/test_gamma_nb.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/regression/test_glm.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/regression/test_glm_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/regression/test_glm_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/regression/test_module_split.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/regression/test_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/regression/test_stress_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/regression/test_terms.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/regression/test_terms_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/survival/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/survival/conftest.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/survival/test_coxph.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/survival/test_discrete_time.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/survival/test_gpu.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/survival/test_kaplan_meier.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/survival/test_logrank.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/survival/test_r_validation.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/test_code_quality.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/timeseries/__init__.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/timeseries/test_acf_stationarity.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/timeseries/test_arima.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/timeseries/test_decomposition.py +0 -0
- {pystatistics-3.3.0 → pystatistics-3.4.1}/tests/timeseries/test_ets.py +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
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
|
+
- CPU PMM (`mice` predictive mean matching) now scales to large datasets.
|
|
13
|
+
Replaced the dense `(n_mis, n_obs)` distance matrix in
|
|
14
|
+
`pystatistics/mice/methods/pmm.py:_match_donors` with a sorted-array windowed
|
|
15
|
+
k-NN (sort the observed predictions once, search a width-`2k` window around
|
|
16
|
+
each missing value's insertion point), matching R `mice`'s `matchindex`
|
|
17
|
+
approach. Cost drops from `O(n_mis·n_obs)` to `O(n_obs log n_obs + n_mis·k)`
|
|
18
|
+
in both time and memory. Measured CPU PMM (p=10-15, m=20, maxit=8): n=3000
|
|
19
|
+
25.4s -> 0.65s (~39x); n=20000 went from minutes/hours to ~6.5s. The window is
|
|
20
|
+
provably exact (the global k nearest neighbours lie in `[pos-k, pos+k-1]` of
|
|
21
|
+
the sorted array), so the donor pool is unchanged; imputations remain
|
|
22
|
+
distributionally identical and still match R. Exact per-seed outputs differ
|
|
23
|
+
from 3.4.0 because the donor ordering within the k-NN set changed.
|
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.4.1
|
|
4
|
+
|
|
5
|
+
Performance: CPU predictive mean matching now scales to large datasets.
|
|
6
|
+
|
|
7
|
+
- The CPU PMM donor search no longer builds a dense distance matrix between
|
|
8
|
+
every missing and every observed value. It sorts the observed predictions
|
|
9
|
+
once and searches a small window around each missing value (the same approach
|
|
10
|
+
R's `mice` uses), reducing both time and memory from quadratic in the number
|
|
11
|
+
of rows to roughly `n log n`. In practice CPU PMM at n=3000 dropped from ~25s
|
|
12
|
+
to under 1s, and large problems (n=20000) that were effectively unusable now
|
|
13
|
+
finish in seconds.
|
|
14
|
+
- Results are unchanged statistically — the donor pool and all imputation
|
|
15
|
+
distributions are identical, and validation against R's `mice` still passes.
|
|
16
|
+
Exact per-seed imputed values can differ slightly from 3.4.0.
|
|
17
|
+
|
|
18
|
+
## 3.4.0
|
|
19
|
+
|
|
20
|
+
GPU acceleration for MICE.
|
|
21
|
+
|
|
22
|
+
- **`mice(..., backend='gpu')` runs on CUDA GPUs.** The `m` imputation chains
|
|
23
|
+
run together on the GPU, with the per-variable linear solves and the
|
|
24
|
+
predictive-mean-matching donor search batched across chains. `backend='auto'`
|
|
25
|
+
uses a CUDA GPU when one is available and falls back to the CPU otherwise.
|
|
26
|
+
- **Large speedups on bigger problems.** Because the donor search dominates and
|
|
27
|
+
parallelises well, the GPU advantage grows with sample size — for example,
|
|
28
|
+
predictive mean matching was roughly 39× faster at n=1000 and 135× faster at
|
|
29
|
+
n=3000 than the CPU backend on an RTX 5070 Ti (m=20, maxit=8). GPU results
|
|
30
|
+
match the CPU backend at the standard GPU/FP32 tolerance.
|
|
31
|
+
- **`use_fp64=True`** runs the GPU path in double precision on CUDA for closer
|
|
32
|
+
agreement with the CPU reference (default is FP32, the fast path).
|
|
33
|
+
- GPU acceleration requires a CUDA GPU; Apple Silicon (MPS) is not yet supported
|
|
34
|
+
for MICE and is refused with a clear message rather than run unverified.
|
|
35
|
+
|
|
3
36
|
## 3.3.0
|
|
4
37
|
|
|
5
38
|
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.1
|
|
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,26 @@ pip install pystatistics[dev]
|
|
|
413
413
|
|
|
414
414
|
## What's New
|
|
415
415
|
|
|
416
|
+
### 3.4.1 — Faster CPU predictive mean matching
|
|
417
|
+
|
|
418
|
+
- CPU PMM in `mice` now scales to large datasets: the donor search sorts the
|
|
419
|
+
observed predictions and scans a small window per missing value (as R's
|
|
420
|
+
`mice` does) instead of forming a full distance matrix, cutting time and
|
|
421
|
+
memory from quadratic to roughly `n log n`. Large problems that were
|
|
422
|
+
effectively unusable on the CPU now finish in seconds. Results are
|
|
423
|
+
statistically unchanged.
|
|
424
|
+
|
|
425
|
+
### 3.4.0 — GPU acceleration for MICE
|
|
426
|
+
|
|
427
|
+
- `mice(..., backend='gpu')` runs the imputation chains on a CUDA GPU, batching
|
|
428
|
+
the per-variable solves and the predictive-mean-matching donor search across
|
|
429
|
+
chains. `backend='auto'` uses a CUDA GPU when available, else the CPU.
|
|
430
|
+
- The speedup grows with sample size (the donor search dominates and batches
|
|
431
|
+
well): predictive mean matching ran ~39× faster at n=1000 and ~135× faster at
|
|
432
|
+
n=3000 than the CPU backend on an RTX 5070 Ti. GPU results match the CPU
|
|
433
|
+
backend at the GPU/FP32 tolerance; pass `use_fp64=True` for double precision.
|
|
434
|
+
- Requires a CUDA GPU; Apple Silicon (MPS) is not yet supported for MICE.
|
|
435
|
+
|
|
416
436
|
### 3.3.0 — Multiple imputation (MICE)
|
|
417
437
|
|
|
418
438
|
- 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,26 @@ pip install pystatistics[dev]
|
|
|
366
366
|
|
|
367
367
|
## What's New
|
|
368
368
|
|
|
369
|
+
### 3.4.1 — Faster CPU predictive mean matching
|
|
370
|
+
|
|
371
|
+
- CPU PMM in `mice` now scales to large datasets: the donor search sorts the
|
|
372
|
+
observed predictions and scans a small window per missing value (as R's
|
|
373
|
+
`mice` does) instead of forming a full distance matrix, cutting time and
|
|
374
|
+
memory from quadratic to roughly `n log n`. Large problems that were
|
|
375
|
+
effectively unusable on the CPU now finish in seconds. Results are
|
|
376
|
+
statistically unchanged.
|
|
377
|
+
|
|
378
|
+
### 3.4.0 — GPU acceleration for MICE
|
|
379
|
+
|
|
380
|
+
- `mice(..., backend='gpu')` runs the imputation chains on a CUDA GPU, batching
|
|
381
|
+
the per-variable solves and the predictive-mean-matching donor search across
|
|
382
|
+
chains. `backend='auto'` uses a CUDA GPU when available, else the CPU.
|
|
383
|
+
- The speedup grows with sample size (the donor search dominates and batches
|
|
384
|
+
well): predictive mean matching ran ~39× faster at n=1000 and ~135× faster at
|
|
385
|
+
n=3000 than the CPU backend on an RTX 5070 Ti. GPU results match the CPU
|
|
386
|
+
backend at the GPU/FP32 tolerance; pass `use_fp64=True` for double precision.
|
|
387
|
+
- Requires a CUDA GPU; Apple Silicon (MPS) is not yet supported for MICE.
|
|
388
|
+
|
|
369
389
|
### 3.3.0 — Multiple imputation (MICE)
|
|
370
390
|
|
|
371
391
|
- 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]
|
|
@@ -63,24 +63,45 @@ def _match_donors(
|
|
|
63
63
|
"""For each missing fitted value, pick one of its ``k`` nearest observed
|
|
64
64
|
fitted values at random; return the chosen observed-row indices.
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
Scales like R's ``mice`` matcher: sort the observed fitted values once, then
|
|
67
|
+
for each missing value search a small window around its insertion point
|
|
68
|
+
instead of forming the full ``(n_mis, n_obs)`` distance matrix. Cost is
|
|
69
|
+
``O(n_obs log n_obs + n_mis·k)`` time and ``O(n_mis·k)`` memory — the dense
|
|
70
|
+
version was ``O(n_mis·n_obs)`` in both, which blows up on large data.
|
|
71
|
+
|
|
72
|
+
The window is provably exact. In a sorted array the ``k`` nearest neighbours
|
|
73
|
+
of a query lie in the contiguous block ``[pos-k, pos+k-1]`` around the
|
|
74
|
+
insertion point ``pos``; a width-``2k`` window covers that block (shifted to
|
|
75
|
+
stay in range near the ends), so the windowed k-NN equals the global k-NN.
|
|
68
76
|
"""
|
|
69
77
|
n_obs = yhat_obs.shape[0]
|
|
78
|
+
n_mis = yhat_mis.shape[0]
|
|
70
79
|
k = min(donors, n_obs)
|
|
71
80
|
|
|
72
|
-
#
|
|
73
|
-
|
|
81
|
+
# Sort donor predictions once; keep the map back to original obs rows.
|
|
82
|
+
order = np.argsort(yhat_obs, kind="stable")
|
|
83
|
+
sorted_obs = yhat_obs[order]
|
|
74
84
|
|
|
75
|
-
#
|
|
76
|
-
|
|
77
|
-
|
|
85
|
+
# Insertion point of each missing prediction into the sorted donors.
|
|
86
|
+
pos = np.searchsorted(sorted_obs, yhat_mis)
|
|
87
|
+
|
|
88
|
+
# Window of distinct candidate donors guaranteed to contain the k nearest.
|
|
89
|
+
w = min(2 * k, n_obs)
|
|
90
|
+
start = np.clip(pos - k, 0, n_obs - w) # (n_mis,)
|
|
91
|
+
win = start[:, None] + np.arange(w)[None, :] # (n_mis, w) sorted-idx
|
|
92
|
+
dist = np.abs(sorted_obs[win] - yhat_mis[:, None]) # (n_mis, w)
|
|
93
|
+
|
|
94
|
+
# k smallest distances within the window (unordered within the k).
|
|
95
|
+
if k < w:
|
|
96
|
+
knn = np.argpartition(dist, k - 1, axis=1)[:, :k] # (n_mis, k) window cols
|
|
78
97
|
else:
|
|
79
|
-
|
|
98
|
+
knn = np.broadcast_to(np.arange(w), (n_mis, w))
|
|
80
99
|
|
|
81
|
-
|
|
82
|
-
pick = rng.integers(0, k, size=
|
|
83
|
-
|
|
100
|
+
rows = np.arange(n_mis)
|
|
101
|
+
pick = rng.integers(0, k, size=n_mis) # one donor per row
|
|
102
|
+
chosen_win_col = knn[rows, pick] # (n_mis,)
|
|
103
|
+
chosen_sorted = win[rows, chosen_win_col] # idx into sorted_obs
|
|
104
|
+
return order[chosen_sorted] # back to original rows
|
|
84
105
|
|
|
85
106
|
|
|
86
107
|
register(PMMMethod())
|