pystatistics 2.0.0__tar.gz → 2.1.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-2.0.0 → pystatistics-2.1.0}/CHANGELOG.md +251 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/PKG-INFO +128 -1
- {pystatistics-2.0.0 → pystatistics-2.1.0}/README.md +127 -0
- pystatistics-2.1.0/benchmarks/mvnmle_bench.py +194 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pyproject.toml +1 -1
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/GPU_BACKEND_CONVENTION.md +43 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/__init__.py +1 -1
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mvnmle/__init__.py +14 -1
- pystatistics-2.1.0/pystatistics/mvnmle/_monotone.py +230 -0
- pystatistics-2.1.0/pystatistics/mvnmle/backends/_em_batched.py +795 -0
- pystatistics-2.1.0/pystatistics/mvnmle/backends/_squarem.py +235 -0
- pystatistics-2.1.0/pystatistics/mvnmle/backends/em.py +469 -0
- pystatistics-2.1.0/pystatistics/mvnmle/mcar_test.py +654 -0
- pystatistics-2.1.0/pystatistics/mvnmle/solvers.py +338 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/_arima_order.py +30 -5
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mvnmle/test_gpu.py +84 -0
- pystatistics-2.1.0/tests/mvnmle/test_mcar.py +123 -0
- pystatistics-2.1.0/tests/mvnmle/test_mom_mcar.py +169 -0
- pystatistics-2.1.0/tests/mvnmle/test_monotone.py +241 -0
- pystatistics-2.1.0/tests/mvnmle/test_no_silent_fallback.py +96 -0
- pystatistics-2.1.0/tests/mvnmle/test_squarem.py +120 -0
- pystatistics-2.0.0/pystatistics/mvnmle/backends/em.py +0 -330
- pystatistics-2.0.0/pystatistics/mvnmle/mcar_test.py +0 -216
- pystatistics-2.0.0/pystatistics/mvnmle/solvers.py +0 -195
- pystatistics-2.0.0/tests/mvnmle/test_no_silent_fallback.py +0 -55
- {pystatistics-2.0.0 → pystatistics-2.1.0}/.github/workflows/publish.yml +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/.github/workflows/trigger-docs-rebuild.yml +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/.gitignore +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/.release/CHECKLIST.md +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/.release/UNRELEASED.md +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/.release/release.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/CLAUDE.md +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/LICENSE +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/DESIGN.md +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/Forge.md +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/GPU_BACKEND_NOTES.md +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/Makefile +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/PYSTATSBIO_CONTEXT.md +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/ROADMAP.md +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/_static/custom.css +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/anova.rst +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/conf.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/core.rst +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/descriptive.rst +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/hypothesis.rst +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/index.rst +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/mixed.rst +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/montecarlo.rst +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/mvnmle.rst +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/regression.rst +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/docs/survival.rst +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/anova/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/anova/_common.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/anova/_contrasts.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/anova/_levene.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/anova/_posthoc.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/anova/_repeated.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/anova/_ss.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/anova/design.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/anova/solution.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/anova/solvers.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/capabilities.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/compute/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/compute/device.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/compute/linalg/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/compute/linalg/batched.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/compute/linalg/cholesky.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/compute/linalg/determinant.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/compute/linalg/qr.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/compute/linalg/solve.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/compute/linalg/svd.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/compute/optimization/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/compute/optimization/convergence.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/compute/precision.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/compute/timing.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/compute/tolerances.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/datasource.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/exceptions.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/protocols.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/result.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/core/validation.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/descriptive/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/descriptive/_missing.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/descriptive/_quantile_types.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/descriptive/backends/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/descriptive/backends/cpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/descriptive/backends/gpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/descriptive/design.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/descriptive/solution.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/descriptive/solvers.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/gam/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/gam/_basis.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/gam/_common.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/gam/_fit.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/gam/_gam.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/gam/_gcv.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/gam/_smooth.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/gam/backends/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/gam/backends/_gpu_family.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/gam/backends/gpu_pirls.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/gam/solution.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/_common.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/_design_factories.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/_p_adjust.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/backends/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/backends/_chisq_test.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/backends/_fisher_test.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/backends/_ks_test.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/backends/_prop_test.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/backends/_t_test.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/backends/_var_test.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/backends/_wilcox_test.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/backends/cpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/backends/gpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/design.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/solution.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/hypothesis/solvers.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mixed/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mixed/_common.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mixed/_deviance.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mixed/_pirls.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mixed/_pls.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mixed/_random_effects.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mixed/_satterthwaite.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mixed/design.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mixed/solution.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mixed/solvers.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/montecarlo/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/montecarlo/_ci.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/montecarlo/_common.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/montecarlo/_influence.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/montecarlo/backends/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/montecarlo/backends/cpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/montecarlo/backends/gpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/montecarlo/design.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/montecarlo/solution.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/montecarlo/solvers.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/multinomial/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/multinomial/_common.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/multinomial/_likelihood.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/multinomial/_solver.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/multinomial/backends/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/multinomial/backends/gpu_likelihood.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/multinomial/solution.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/multivariate/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/multivariate/_common.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/multivariate/_factor.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/multivariate/_pca.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/multivariate/_rotation.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/multivariate/backends/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/multivariate/backends/gpu_pca.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mvnmle/_objectives/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mvnmle/_objectives/base.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mvnmle/_objectives/cpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mvnmle/_objectives/gpu_fp32.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mvnmle/_objectives/gpu_fp64.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mvnmle/_objectives/parameterizations.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mvnmle/_utils.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mvnmle/backends/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mvnmle/backends/cpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mvnmle/backends/gpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mvnmle/datasets.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mvnmle/design.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mvnmle/patterns.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/mvnmle/solution.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/ordinal/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/ordinal/_common.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/ordinal/_likelihood.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/ordinal/_solver.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/ordinal/backends/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/ordinal/backends/gpu_likelihood.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/ordinal/solution.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/py.typed +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/regression/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/regression/_formatting.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/regression/_glm.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/regression/_linear.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/regression/_nb_theta.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/regression/backends/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/regression/backends/cpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/regression/backends/cpu_glm.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/regression/backends/gpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/regression/backends/gpu_glm.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/regression/design.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/regression/families.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/regression/solution.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/regression/solvers.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/survival/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/survival/_common.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/survival/_cox.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/survival/_discrete.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/survival/_km.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/survival/_logrank.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/survival/backends/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/survival/backends/cpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/survival/backends/gpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/survival/design.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/survival/solution.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/survival/solvers.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/_acf.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/_arima_batch.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/_arima_factored.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/_arima_fit.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/_arima_forecast.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/_arima_kalman.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/_arima_likelihood.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/_common.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/_decomposition.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/_differencing.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/_ets_fit.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/_ets_forecast.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/_ets_models.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/_stationarity.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/_whittle.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/backends/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/backends/whittle_batch_gpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/pystatistics/timeseries/backends/whittle_gpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/anova/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/anova/conftest.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/anova/test_contrasts.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/anova/test_design.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/anova/test_factorial.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/anova/test_levene.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/anova/test_oneway.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/anova/test_posthoc.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/anova/test_r_validation.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/anova/test_repeated_measures.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/benchmark_gpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/conftest.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/core/test_datasource.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/core/test_exceptions.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/core/test_result.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/core/test_validation.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/descriptive/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/descriptive/conftest.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/descriptive/test_cor.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/descriptive/test_cov.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/descriptive/test_describe.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/descriptive/test_gpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/descriptive/test_missing.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/descriptive/test_moments.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/descriptive/test_quantile.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/descriptive/test_r_validation.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_ancova_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_ancova_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_bonferroni_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_bonferroni_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_eta_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_eta_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_levene_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_levene_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_oneway_balanced_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_oneway_balanced_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_oneway_unbalanced_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_oneway_unbalanced_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_rm_mixed_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_rm_mixed_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_rm_within_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_rm_within_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_tukey_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_tukey_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_twoway_balanced_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_twoway_balanced_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_twoway_unbalanced_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/anova_twoway_unbalanced_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/basic_100x3.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/basic_100x3_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/basic_100x3_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/collinear_almost.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/collinear_almost_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/collinear_almost_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_basic_100x5.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_basic_100x5_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_basic_100x5_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_constant_column.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_constant_column_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_constant_column_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_extreme_values.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_extreme_values_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_extreme_values_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_large_1000x10.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_large_1000x10_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_large_1000x10_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_nan_columnwise.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_nan_columnwise_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_nan_columnwise_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_nan_scattered.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_nan_scattered_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_nan_scattered_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_negative_correlation.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_negative_correlation_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_negative_correlation_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_perfect_correlation.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_perfect_correlation_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_perfect_correlation_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_single_column.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_single_column_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_single_column_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_ties.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_ties_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/desc_ties_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/different_scales.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/different_scales_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/different_scales_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/generate_anova_fixtures.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/generate_descriptive_fixtures.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/generate_fixtures.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/generate_glm_fixtures.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/generate_hypothesis_fixtures.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/generate_mixed_fixtures.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/generate_montecarlo_fixtures.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/generate_survival_fixtures.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_binomial_balanced.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_binomial_balanced_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_binomial_balanced_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_binomial_basic.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_binomial_basic_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_binomial_basic_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_binomial_large.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_binomial_large_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_binomial_large_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_binomial_separated.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_binomial_separated_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_binomial_separated_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_gaussian_basic.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_gaussian_basic_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_gaussian_basic_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_gaussian_large.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_gaussian_large_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_gaussian_large_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_poisson_basic.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_poisson_basic_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_poisson_basic_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_poisson_large_counts.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_poisson_large_counts_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_poisson_large_counts_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_poisson_zeros.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_poisson_zeros_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/glm_poisson_zeros_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/high_noise.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/high_noise_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/high_noise_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_chisq_2x2_yates_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_chisq_2x2_yates_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_chisq_3x3_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_chisq_3x3_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_chisq_gof_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_chisq_gof_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_chisq_gof_unequal_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_chisq_gof_unequal_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_fisher_2x2_less_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_fisher_2x2_less_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_fisher_2x2_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_fisher_2x2_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_fisher_3x3_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_fisher_3x3_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_ks_onesample_norm_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_ks_onesample_norm_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_ks_twosample_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_ks_twosample_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_prop_onesample_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_prop_onesample_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_prop_twosample_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_prop_twosample_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_t_onesample_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_t_onesample_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_t_paired_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_t_paired_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_t_pooled_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_t_pooled_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_t_welch_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_t_welch_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_var_basic_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_var_basic_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_wilcox_ranksum_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_wilcox_ranksum_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_wilcox_signed_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/htest_wilcox_signed_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/ill_conditioned.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/ill_conditioned_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/ill_conditioned_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/large_coeffs.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/large_coeffs_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/large_coeffs_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_boot_ci_90_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_boot_ci_90_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_boot_ci_normal_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_boot_ci_normal_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_boot_ci_skewed_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_boot_ci_skewed_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_boot_mean_balanced_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_boot_mean_balanced_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_boot_mean_ordinary_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_boot_mean_ordinary_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_boot_median_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_boot_median_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_boot_variance_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_boot_variance_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_perm_greater_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_perm_greater_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_perm_not_significant_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_perm_not_significant_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_perm_significant_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mc_perm_significant_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mixed/glmm_binomial.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mixed/glmm_poisson.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mixed/lmm_crossed.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mixed/lmm_intercept.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mixed/lmm_ml.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mixed/lmm_no_effect.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mixed/lmm_slope.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mixed/mixed_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/mixed/mixed_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/near_square.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/near_square_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/near_square_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/no_intercept.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/no_intercept_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/no_intercept_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/run_r_anova_validation.R +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/run_r_descriptive_validation.R +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/run_r_glm_validation.R +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/run_r_hypothesis_validation.R +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/run_r_mixed_validation.R +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/run_r_montecarlo_validation.R +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/run_r_survival_validation.R +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/run_r_validation.R +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/run_validation.sh +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/small_noise.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/small_noise_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/small_noise_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_cox_breslow_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_cox_breslow_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_cox_single_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_cox_single_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_cox_ties_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_cox_ties_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_cox_two_cov_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_cox_two_cov_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_km_basic_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_km_basic_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_km_heavy_cens_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_km_heavy_cens_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_km_loglog_ci_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_km_loglog_ci_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_km_no_cens_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_km_no_cens_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_km_plain_ci_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_km_plain_ci_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_km_ties_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_km_ties_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_lr_peto_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_lr_peto_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_lr_three_group_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_lr_three_group_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_lr_two_group_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/surv_lr_two_group_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/tall_skinny.csv +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/tall_skinny_meta.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/tall_skinny_r_results.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/fixtures/validate_against_r.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/gam/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/gam/test_gam.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/hypothesis/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/hypothesis/conftest.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/hypothesis/test_chisq_test.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/hypothesis/test_design_split.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/hypothesis/test_fisher_test.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/hypothesis/test_gpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/hypothesis/test_ks_test.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/hypothesis/test_p_adjust.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/hypothesis/test_prop_test.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/hypothesis/test_r_validation.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/hypothesis/test_t_test.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/hypothesis/test_var_test.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/hypothesis/test_wilcox_test.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mixed/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mixed/conftest.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mixed/test_glmm.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mixed/test_lmm_crossed.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mixed/test_lmm_intercept.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mixed/test_lmm_nested.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mixed/test_lmm_slope.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mixed/test_pls.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mixed/test_r_validation.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mixed/test_random_effects.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mixed/test_satterthwaite.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/montecarlo/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/montecarlo/conftest.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/montecarlo/test_batched_solver.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/montecarlo/test_boot_ci.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/montecarlo/test_bootstrap.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/montecarlo/test_gpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/montecarlo/test_influence.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/montecarlo/test_permutation.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/montecarlo/test_r_validation.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/multinomial/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/multinomial/test_multinom.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/multivariate/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/multivariate/test_multivariate.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mvnmle/references/apple_em_reference.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mvnmle/references/apple_reference.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mvnmle/references/generate_em_fixtures.R +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mvnmle/references/little_mcar_apple.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mvnmle/references/little_mcar_complete.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mvnmle/references/little_mcar_extreme.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mvnmle/references/little_mcar_missvals.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mvnmle/references/little_mcar_simple_mcar.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mvnmle/references/little_mcar_summary.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mvnmle/references/missvals_em_reference.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mvnmle/references/missvals_reference.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mvnmle/references/small_test_reference.json +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mvnmle/test_em.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/mvnmle/test_mlest.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/ordinal/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/ordinal/test_ordinal.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/regression/benchmark.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/regression/benchmark.r +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/regression/conftest.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/regression/test_fit.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/regression/test_gamma_nb.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/regression/test_glm.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/regression/test_glm_gpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/regression/test_glm_r_validation.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/regression/test_module_split.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/regression/test_r_validation.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/regression/test_stress_gpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/survival/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/survival/conftest.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/survival/test_coxph.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/survival/test_discrete_time.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/survival/test_gpu.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/survival/test_kaplan_meier.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/survival/test_logrank.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/survival/test_r_validation.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/test_code_quality.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/timeseries/__init__.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/timeseries/test_acf_stationarity.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/timeseries/test_arima.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/timeseries/test_decomposition.py +0 -0
- {pystatistics-2.0.0 → pystatistics-2.1.0}/tests/timeseries/test_ets.py +0 -0
|
@@ -1,5 +1,256 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.1.0
|
|
4
|
+
|
|
5
|
+
- **`mom_mcar_test`: new method-of-moments MCAR test**
|
|
6
|
+
(``pystatistics/mvnmle/mcar_test.py``). A separate function — not
|
|
7
|
+
a new mode on ``little_mcar_test`` — because the method-of-moments
|
|
8
|
+
variant **is not Little's test**. Little (1988) specifically calls
|
|
9
|
+
for MLE plug-in estimators; swapping in pairwise-deletion sample
|
|
10
|
+
moments gives a statistic of the same shape with different
|
|
11
|
+
asymptotic properties, and calling it Little's test would be a
|
|
12
|
+
polite but concrete lie. The separate function preserves the
|
|
13
|
+
``little_mcar_test`` contract exactly (matches R ``mvnmle`` bit-
|
|
14
|
+
for-bit as before) while giving users a documented fast alternative.
|
|
15
|
+
|
|
16
|
+
End-to-end timings at 15 % MCAR:
|
|
17
|
+
|
|
18
|
+
| dataset | shape | little_mcar_test | mom_mcar_test |
|
|
19
|
+
|----------------|-----------|------------------|---------------|
|
|
20
|
+
| iris | 150 × 4 | 2.9 ms | 0.31 ms |
|
|
21
|
+
| wine | 178 × 13 | 60.9 ms | 2.17 ms |
|
|
22
|
+
| breast_cancer | 569 × 30 | 1491 ms | 28.7 ms |
|
|
23
|
+
|
|
24
|
+
For repeated-diagnostic workflows (e.g. an MCAR sweep over 3410
|
|
25
|
+
datasets), this is **1.6 minutes vs ~50 minutes** end-to-end. The
|
|
26
|
+
statistical trade-off is asymptotic efficiency: MoM is consistent
|
|
27
|
+
under the MCAR null but not asymptotically efficient, and the
|
|
28
|
+
finite-sample distribution deviates more from chi-square than
|
|
29
|
+
Little's does. The docstring spells out when to use which:
|
|
30
|
+
diagnostic screens → MoM; regulated submissions or anywhere the
|
|
31
|
+
exact asymptotic distribution matters → Little's.
|
|
32
|
+
|
|
33
|
+
Implementation details:
|
|
34
|
+
- ``_pairwise_deletion_moments``: O(n v^2) pairwise mean and
|
|
35
|
+
covariance via a single matmul. No per-column loop.
|
|
36
|
+
- ``chi_square_mcar_batched_np`` / ``_torch``: fully batched
|
|
37
|
+
chi-square assembly (batched SVD for conditioning,
|
|
38
|
+
well-conditioned patterns through batched solve, ill-conditioned
|
|
39
|
+
patterns through batched pinv as separate groups — no
|
|
40
|
+
per-pattern Python loop).
|
|
41
|
+
- ``backend`` parameter with same size-heuristic + visible-warning
|
|
42
|
+
discipline as the EM path. GPU is supported but does not
|
|
43
|
+
out-perform CPU on any tested shape — MoM's compute is small
|
|
44
|
+
enough that transfer + launch overhead loses to CPU numpy.
|
|
45
|
+
Auto-dispatch warns when this is the case.
|
|
46
|
+
- Honesty: ``MCARTestResult`` gained a ``method`` field so
|
|
47
|
+
downstream code knows which test produced a given result.
|
|
48
|
+
``little_mcar_test`` reports ``"Little (MLE plug-in)"``;
|
|
49
|
+
``mom_mcar_test`` reports ``"Method-of-moments
|
|
50
|
+
(pairwise-deletion plug-in)"``.
|
|
51
|
+
|
|
52
|
+
New tests (``tests/mvnmle/test_mom_mcar.py``, 10 tests):
|
|
53
|
+
name-honesty, MLE-vs-MoM agreement on MCAR data, correct rejection
|
|
54
|
+
on non-MCAR data, all-missing-row handling, speed guard of
|
|
55
|
+
≥ 10× over MLE on breast_cancer.
|
|
56
|
+
|
|
57
|
+
- **Fully-batched device-resident EM on GPU** (``_em_batched.py``
|
|
58
|
+
/ ``_run_em_loop_gpu``). Pre-2.1.0 the "GPU EM" path set up a
|
|
59
|
+
torch device in the constructor but none of the per-iteration
|
|
60
|
+
work actually ran on-device — the numpy E-step ran for every
|
|
61
|
+
backend, which is why pre-2.1.0 benchmarks showed identical CPU
|
|
62
|
+
and GPU timings. This release implements the real thing: one
|
|
63
|
+
batched Cholesky + one batched solve over patterns for the
|
|
64
|
+
regression betas, one batched gather + bmm over all N
|
|
65
|
+
observations for the filled data, two dense gemms for the
|
|
66
|
+
sufficient-statistic accumulators, all on-device. SQUAREM also
|
|
67
|
+
runs fully on-device.
|
|
68
|
+
|
|
69
|
+
EM-only timings (without the MCAR-assembly wrapper):
|
|
70
|
+
|
|
71
|
+
| dataset | shape | CPU EM | GPU EM | speedup |
|
|
72
|
+
|----------------|-----------|----------|----------|---------|
|
|
73
|
+
| wine | 178 × 13 | 38 ms | 24 ms | 1.6× |
|
|
74
|
+
| breast_cancer | 569 × 30 | 2142 ms | 147 ms | 14.6× |
|
|
75
|
+
|
|
76
|
+
Small-data cases (apple, iris, missvals) lose on GPU because
|
|
77
|
+
transfer + launch overhead exceeds the per-iteration work.
|
|
78
|
+
Empirically calibrated heuristic: GPU is worth it when
|
|
79
|
+
``n_obs * n_vars > 1500``.
|
|
80
|
+
|
|
81
|
+
- **Size-heuristic dispatch with Rule-1 visibility** for both EM and
|
|
82
|
+
MoM backends. When ``backend='auto'`` makes a non-obvious choice
|
|
83
|
+
(e.g. picking CPU despite GPU availability because the data are
|
|
84
|
+
too small), a ``UserWarning`` explains the decision and tells
|
|
85
|
+
users how to override. When ``backend='gpu'`` is explicitly
|
|
86
|
+
requested on small data, the request is honored (user knows best)
|
|
87
|
+
but a warning notes that CPU would likely be faster. No silent
|
|
88
|
+
fallbacks anywhere. New tests pin these behaviours.
|
|
89
|
+
|
|
90
|
+
- **Monotone-missingness closed-form MLE** (Anderson 1957; new
|
|
91
|
+
``pystatistics.mvnmle._monotone``). When the missingness pattern
|
|
92
|
+
is monotone — when variables can be ordered such that each
|
|
93
|
+
observation's missing entries form a contiguous suffix — the MVN
|
|
94
|
+
MLE has a closed form via a chain of OLS regressions, with no
|
|
95
|
+
iteration. Common on longitudinal data with attrition, panel
|
|
96
|
+
surveys with dropout, and most sequentially-administered
|
|
97
|
+
instruments. New public helpers:
|
|
98
|
+
|
|
99
|
+
- ``pystatistics.mvnmle.is_monotone(data) -> bool``
|
|
100
|
+
- ``pystatistics.mvnmle.monotone_permutation(data) -> ndarray | None``
|
|
101
|
+
- ``pystatistics.mvnmle.mlest_monotone_closed_form(data) -> (mu, sigma, n)``
|
|
102
|
+
- ``mlest(data, algorithm='monotone')`` routes through the
|
|
103
|
+
closed-form; raises ``ValidationError`` if the data are not
|
|
104
|
+
monotone (Rule 1: no silent dispatch). Users who want
|
|
105
|
+
"use the closed form when applicable, fall back otherwise"
|
|
106
|
+
should call ``is_monotone`` first and branch explicitly.
|
|
107
|
+
|
|
108
|
+
The closed-form is the exact MLE (no tolerance-bounded
|
|
109
|
+
approximation), matches R ``mvnmle`` reference output on both
|
|
110
|
+
``apple`` and ``missvals`` to machine precision, and is
|
|
111
|
+
dramatically faster than iterative algorithms at larger v
|
|
112
|
+
(a 1500 × 20 monotone dataset completes in ~2 ms vs EM's
|
|
113
|
+
~40 ms). For non-monotone random MCAR data (the common case
|
|
114
|
+
in MCAR diagnostic use), detection is cheap (~O(v² n)) and
|
|
115
|
+
correctly returns False so iterative algorithms run.
|
|
116
|
+
|
|
117
|
+
New tests (``tests/mvnmle/test_monotone.py``, 12 tests):
|
|
118
|
+
detection true-positive / true-negative on several canonical
|
|
119
|
+
shapes; closed-form vs EM agreement; permutation invariance;
|
|
120
|
+
non-monotone data raises; performance guard at v=20.
|
|
121
|
+
|
|
122
|
+
- **EM MLE: substantial real-data speedup via batched per-pattern
|
|
123
|
+
linear algebra + SQUAREM acceleration** (Project Lacuna-driven).
|
|
124
|
+
|
|
125
|
+
End-to-end ``little_mcar_test`` wall-clock at 15 % MCAR, seed 0:
|
|
126
|
+
|
|
127
|
+
| dataset | shape | 2.0.1 | 2.1.0 | speedup |
|
|
128
|
+
|----------------|-----------|----------|----------|---------|
|
|
129
|
+
| apple | 18 × 2 | 1.9 ms | 2.0 ms | flat |
|
|
130
|
+
| missvals | 13 × 5 | 19.9 ms | 9.5 ms | 2.1× |
|
|
131
|
+
| iris | 150 × 4 | 2.8 ms | 2.8 ms | flat |
|
|
132
|
+
| wine | 178 × 13 | 79.4 ms | 41.5 ms | 1.9× |
|
|
133
|
+
| breast_cancer | 569 × 30 | 3278 ms | 2089 ms | 1.6× |
|
|
134
|
+
|
|
135
|
+
For workloads that run MCAR repeatedly over many datasets
|
|
136
|
+
(e.g. a 3410-entry MCAR sweep), this is roughly a 1-hour reduction
|
|
137
|
+
per full pass at Lacuna's current scale.
|
|
138
|
+
|
|
139
|
+
Three changes stack:
|
|
140
|
+
|
|
141
|
+
1. **Batched per-pattern conditional parameters** (new
|
|
142
|
+
``pystatistics.mvnmle.backends._em_batched``). The E-step used
|
|
143
|
+
to loop in Python over missingness patterns, issuing a scalar
|
|
144
|
+
Cholesky + triangular solve per pattern. It now stacks all P
|
|
145
|
+
pattern-sigma submatrices into a single
|
|
146
|
+
``(P, v_max, v_max)`` tensor (identity-padded in the unused
|
|
147
|
+
slots so the Cholesky stays well-defined) and runs one batched
|
|
148
|
+
Cholesky + one batched solve for the whole iteration. The
|
|
149
|
+
accumulator loop over patterns remains in Python because
|
|
150
|
+
``n_k`` varies and full observation-level padding hurt more
|
|
151
|
+
than it helped on the representative shapes we benchmarked.
|
|
152
|
+
|
|
153
|
+
2. **SQUAREM acceleration** (Varadhan & Roland 2008; new
|
|
154
|
+
``pystatistics.mvnmle.backends._squarem``). EM's linear
|
|
155
|
+
convergence is sped up by a Steffensen-style extrapolation of
|
|
156
|
+
three consecutive EM iterates, safeguarded by a monotonicity
|
|
157
|
+
check on the observed-data log-likelihood. Typical effect on
|
|
158
|
+
well-behaved EM problems: 2–4× reduction in underlying
|
|
159
|
+
EM-step-equivalents. Preserves the MLE — the convergence
|
|
160
|
+
point is unchanged, only the path is shorter. On by default
|
|
161
|
+
via a new ``accelerate=True`` kwarg on ``EMBackend.solve``;
|
|
162
|
+
pass ``accelerate=False`` for the plain-EM reference path.
|
|
163
|
+
|
|
164
|
+
3. **Fully batched observed-data log-likelihood**
|
|
165
|
+
(``compute_loglik_batched_np``). The SQUAREM monotonicity
|
|
166
|
+
safeguard calls the log-likelihood often, so that path
|
|
167
|
+
needed to be cheap. The implementation now does one batched
|
|
168
|
+
Cholesky over all patterns for log-determinants and one
|
|
169
|
+
batched solve across all N observations for the quadratic-
|
|
170
|
+
form contribution — no per-pattern Python loop.
|
|
171
|
+
|
|
172
|
+
- **Benchmark harness** (``benchmarks/mvnmle_bench.py``). Runs the
|
|
173
|
+
five reference shapes (apple, missvals, iris, wine,
|
|
174
|
+
breast_cancer) across the (algorithm, backend) matrix and
|
|
175
|
+
prints wall-clock / iteration counts per case. Use
|
|
176
|
+
``--quick`` to skip the BFGS cases that don't converge on
|
|
177
|
+
high-$v$ data; ``--tag`` labels a run for diff against prior
|
|
178
|
+
baselines.
|
|
179
|
+
|
|
180
|
+
- **Documented why direct-BFGS is not always the right default.**
|
|
181
|
+
Internal notes and the 2.0.0 / 2.0.1 release narrative already
|
|
182
|
+
covered why ``algorithm='em'`` became the ``little_mcar_test``
|
|
183
|
+
default; this release adds the story of why batching helps EM
|
|
184
|
+
significantly but does *not* rescue direct-BFGS on realistic
|
|
185
|
+
high-$v$ data (layer-3 Hessian conditioning is parameterization-
|
|
186
|
+
invariant; batching only addresses layer-1 launch overhead).
|
|
187
|
+
See ``GPU_BACKEND_CONVENTION.md`` Section 0 for the "when to
|
|
188
|
+
add a GPU backend and when not" rule that drove the 2.0.1
|
|
189
|
+
cleanup; this release extends that logic with
|
|
190
|
+
"accelerating the algorithm by reducing iteration count
|
|
191
|
+
(SQUAREM) is cheaper than accelerating each iteration."
|
|
192
|
+
|
|
193
|
+
- **Finding: the "GPU EM" backend was never actually running on
|
|
194
|
+
GPU.** The ``device='cuda'`` / ``'mps'`` constructor flag set
|
|
195
|
+
up ``self._torch`` but none of ``_e_step`` / ``_m_step`` /
|
|
196
|
+
``_compute_loglik`` used it — the numpy path ran for every
|
|
197
|
+
backend. That's why pre-2.1.0 benchmarks showed identical
|
|
198
|
+
CPU and GPU EM timings. We attempted to implement a real
|
|
199
|
+
device-resident EM loop and found it was slower than CPU for
|
|
200
|
+
all the shapes we care about (per-pattern kernel-launch
|
|
201
|
+
overhead dominates the small per-pattern matrix work). The
|
|
202
|
+
honest answer for now is that GPU EM stays CPU-equivalent
|
|
203
|
+
by design; a future release may revisit with fully N-parallel
|
|
204
|
+
observation-level batching if a workload appears where the
|
|
205
|
+
GPU can actually win. This behaviour is unchanged from prior
|
|
206
|
+
releases — we're just documenting what was already true.
|
|
207
|
+
|
|
208
|
+
- **SQUAREM test coverage** (new ``tests/mvnmle/test_squarem.py``).
|
|
209
|
+
Four tests pinning the invariants: same MLE as plain EM on
|
|
210
|
+
apple; substantially fewer EM-equivalent steps on missvals;
|
|
211
|
+
monotonicity of log-likelihood preserved across iteration
|
|
212
|
+
caps; same MLE as plain EM on a realistic shape (sklearn
|
|
213
|
+
wine with 15 % MCAR).
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
## 2.0.1
|
|
217
|
+
|
|
218
|
+
- **GPU Backend Convention: codified when NOT to add a GPU backend**
|
|
219
|
+
(`pystatistics/GPU_BACKEND_CONVENTION.md`, new Section 0). Formalises
|
|
220
|
+
the Oprah-test rule: don't give every module a GPU backend — only
|
|
221
|
+
those where the algorithm is actually a good fit for GPU hardware
|
|
222
|
+
(large dense linear algebra, big-N likelihoods, batched independent
|
|
223
|
+
fits). Explicitly calls out the non-targets (many-small-fits,
|
|
224
|
+
sequential algorithms, transfer-bound cheap compute) and the ~100 ms
|
|
225
|
+
CPU-time threshold below which launch + PCIe overhead eats any
|
|
226
|
+
speedup. Names the deliberate CPU-only modules (`anova`,
|
|
227
|
+
`timeseries.ets`, `survival.coxph`, `multivariate.factor_analysis`,
|
|
228
|
+
acf / stationarity) so future contributors know these omissions are
|
|
229
|
+
intentional, not oversights.
|
|
230
|
+
- **`auto_arima` now accepts `backend=` and `method=`**
|
|
231
|
+
(`pystatistics/timeseries/_arima_order.py`). Parameters are threaded
|
|
232
|
+
through `_stepwise_search` / `_grid_search` / `_try_fit` to every
|
|
233
|
+
candidate `arima()` call. Previously there was no way to route the
|
|
234
|
+
per-candidate fits through the GPU Whittle path, so on a
|
|
235
|
+
GPU-equipped box the search was stuck on CPU even if the user
|
|
236
|
+
wanted frequency-domain speedups. Default `backend=None` → CPU
|
|
237
|
+
(R-reference); pass `method='Whittle', backend='gpu'` to run each
|
|
238
|
+
candidate on GPU.
|
|
239
|
+
- **`little_mcar_test` now accepts `backend=` and `algorithm=`**
|
|
240
|
+
(`pystatistics/mvnmle/mcar_test.py`). Previously the function had no
|
|
241
|
+
backend knob and always ran `mlest()` with the default — which after
|
|
242
|
+
2.0.0's CPU-default sweep meant there was no way to route Little's
|
|
243
|
+
MCAR test through the GPU path, defeating the purpose of having a
|
|
244
|
+
GPU MLE backend at all. The new `backend` parameter is forwarded
|
|
245
|
+
straight to `mlest`; default None → CPU (consistent with the 2.0.0
|
|
246
|
+
convention), `'gpu'` / `'auto'` opt in to GPU. The per-pattern
|
|
247
|
+
test-statistic accumulation still runs on CPU — it's O(P × v³) for
|
|
248
|
+
v = observed vars per pattern (typically < 50) and was never the
|
|
249
|
+
bottleneck; the ML estimation step is where GPU matters. Verified
|
|
250
|
+
GPU/CPU results agree within FP32 tolerance (Δ stat ≈ 1.4e-4 on
|
|
251
|
+
the apple dataset).
|
|
252
|
+
|
|
253
|
+
|
|
3
254
|
## 2.0.0
|
|
4
255
|
|
|
5
256
|
- **BREAKING: Default backend is now CPU across all public solvers**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pystatistics
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.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/
|
|
@@ -51,6 +51,133 @@ GPU-accelerated statistical computing for Python.
|
|
|
51
51
|
|
|
52
52
|
## What's New
|
|
53
53
|
|
|
54
|
+
### 2.1.0 — Real-data EM speedup + monotone closed-form MLE
|
|
55
|
+
|
|
56
|
+
Dogfooding via Project Lacuna surfaced that ``little_mcar_test`` on
|
|
57
|
+
realistic tabular data (sklearn's iris / wine / breast_cancer with
|
|
58
|
+
random MCAR injection) was bottlenecked by EM: the E-step was a
|
|
59
|
+
Python loop over missingness patterns, and each SQUAREM-style
|
|
60
|
+
safeguard pass re-ran a per-pattern log-likelihood. This release
|
|
61
|
+
batches both and adds Varadhan & Roland's SQUAREM acceleration.
|
|
62
|
+
|
|
63
|
+
End-to-end ``little_mcar_test`` wall-clock at 15 % MCAR, seed 0:
|
|
64
|
+
|
|
65
|
+
| dataset | shape | 2.0.1 | 2.1.0 | speedup |
|
|
66
|
+
|----------------|-----------|----------|----------|---------|
|
|
67
|
+
| missvals | 13 × 5 | 19.9 ms | 9.5 ms | 2.1× |
|
|
68
|
+
| wine | 178 × 13 | 79.4 ms | 41.5 ms | 1.9× |
|
|
69
|
+
| breast_cancer | 569 × 30 | 3278 ms | 2089 ms | 1.6× |
|
|
70
|
+
|
|
71
|
+
For repeated-diagnostic workflows (e.g. an MCAR sweep over several
|
|
72
|
+
thousand datasets), this turns a 3-hour run into a 2-hour run.
|
|
73
|
+
|
|
74
|
+
Three stacked improvements, all preserving bit-equivalence on the R
|
|
75
|
+
mvnmle reference cases (apple, missvals):
|
|
76
|
+
|
|
77
|
+
- **Batched per-pattern conditional parameters.** The E-step's
|
|
78
|
+
per-pattern Cholesky + triangular solve now runs as a single
|
|
79
|
+
batched kernel pair across all missingness patterns. The
|
|
80
|
+
unused padding slots are identity-filled so the Cholesky stays
|
|
81
|
+
well-defined.
|
|
82
|
+
- **SQUAREM acceleration on top of EM.** Three EM steps + one
|
|
83
|
+
Steffensen-style extrapolation, safeguarded by a monotonicity
|
|
84
|
+
check on the observed-data log-likelihood. Typical effect:
|
|
85
|
+
2–4× fewer EM-step equivalents to convergence. Convergence
|
|
86
|
+
point is the same MLE — only the path is shorter. On by
|
|
87
|
+
default; ``EMBackend.solve(..., accelerate=False)`` recovers
|
|
88
|
+
the plain-EM reference.
|
|
89
|
+
- **Fully batched log-likelihood.** The SQUAREM monotonicity
|
|
90
|
+
check calls ``loglik`` often, so it was batched too — one
|
|
91
|
+
Cholesky over all patterns, one solve across all N
|
|
92
|
+
observations, no per-pattern Python loop.
|
|
93
|
+
|
|
94
|
+
**`mom_mcar_test`: fast method-of-moments MCAR test.** A new *separate
|
|
95
|
+
function* (not a mode on ``little_mcar_test``, because the MoM variant
|
|
96
|
+
is not Little's test) that uses pairwise-deletion sample moments
|
|
97
|
+
instead of MLE plug-in. The test is consistent under MCAR but not
|
|
98
|
+
asymptotically efficient, trading a small amount of statistical
|
|
99
|
+
efficiency for dramatic speed. At 15 % MCAR on sklearn demos:
|
|
100
|
+
|
|
101
|
+
| dataset | shape | little_mcar_test | mom_mcar_test |
|
|
102
|
+
|----------------|-----------|------------------|---------------|
|
|
103
|
+
| iris | 150 × 4 | 2.9 ms | 0.31 ms |
|
|
104
|
+
| wine | 178 × 13 | 60.9 ms | 2.17 ms |
|
|
105
|
+
| breast_cancer | 569 × 30 | 1491 ms | 28.7 ms |
|
|
106
|
+
|
|
107
|
+
For a 3410-dataset MCAR sweep: **~50 minutes → ~1.6 minutes**. Use
|
|
108
|
+
``little_mcar_test`` when you need Little 1988's asymptotic
|
|
109
|
+
distribution exactly (regulated submissions, citing R reference);
|
|
110
|
+
use ``mom_mcar_test`` for high-throughput diagnostic screens. The
|
|
111
|
+
``MCARTestResult.method`` field records which test produced a given
|
|
112
|
+
result so downstream code can disambiguate without tracking the
|
|
113
|
+
calling function.
|
|
114
|
+
|
|
115
|
+
**Fully-batched device-resident EM on GPU.** Pre-2.1.0 the
|
|
116
|
+
``device='cuda'`` EM path set up a torch device but never used it —
|
|
117
|
+
numpy ran for every backend. This release implements a real
|
|
118
|
+
device-resident loop with fully batched E-step / M-step / log-
|
|
119
|
+
likelihood, SQUAREM acceleration on top, all on device. On breast-
|
|
120
|
+
cancer-scale (569 × 30) EM drops from 2142 ms CPU to 147 ms GPU
|
|
121
|
+
(14.6×). Small data remains CPU-faster; an empirical size heuristic
|
|
122
|
+
(``n * v >= 1500``) with visible dispatch warnings keeps this
|
|
123
|
+
correct in user-facing behaviour.
|
|
124
|
+
|
|
125
|
+
**Monotone-missingness closed-form MLE** (Anderson 1957). Longitudinal
|
|
126
|
+
cohorts with attrition, panel surveys with dropout, and most
|
|
127
|
+
sequentially-administered instruments produce *monotone* missingness
|
|
128
|
+
— the variables can be ordered such that each observation's missing
|
|
129
|
+
entries form a contiguous suffix. When the pattern is monotone, the
|
|
130
|
+
MVN MLE has a closed form via a chain of OLS regressions, with no
|
|
131
|
+
iteration. New helpers: ``mvnmle.is_monotone(data)``,
|
|
132
|
+
``mvnmle.monotone_permutation(data)``, and
|
|
133
|
+
``mlest(data, algorithm='monotone')``. The closed-form matches R
|
|
134
|
+
``mvnmle`` bit-for-bit on canonical datasets and is orders of
|
|
135
|
+
magnitude faster than EM on larger-v longitudinal data. Per Rule 1
|
|
136
|
+
the algorithm raises on non-monotone input rather than silently
|
|
137
|
+
falling back — call ``is_monotone`` first if you want conditional
|
|
138
|
+
dispatch.
|
|
139
|
+
|
|
140
|
+
Also in this release:
|
|
141
|
+
|
|
142
|
+
- **Benchmark harness** under ``benchmarks/mvnmle_bench.py`` for
|
|
143
|
+
tracking wall-clock and iteration counts across the reference
|
|
144
|
+
shapes; use the ``--tag`` flag to label a baseline for diff
|
|
145
|
+
against future changes.
|
|
146
|
+
- **Documented finding**: the ``device='cuda'`` EM path was never
|
|
147
|
+
actually running on the GPU prior to this release — it stored
|
|
148
|
+
a torch device but never used it. We tried to wire up a real
|
|
149
|
+
device-resident loop and found GPU is slower than CPU for all
|
|
150
|
+
shapes we tested (per-pattern launch overhead still dominates
|
|
151
|
+
the tiny per-pattern matrix work). GPU EM therefore remains
|
|
152
|
+
CPU-equivalent by design; a future release will revisit if a
|
|
153
|
+
workload appears where full observation-level batching makes
|
|
154
|
+
GPU actually win.
|
|
155
|
+
|
|
156
|
+
### 2.0.1 — GPU-backend exposure gaps and a convention rule
|
|
157
|
+
|
|
158
|
+
Two public functions had GPU-capable inner calls but no `backend=`
|
|
159
|
+
parameter, so there was no way to route them through the GPU path —
|
|
160
|
+
exactly the regression the 2.0.0 CPU-default sweep was trying *not*
|
|
161
|
+
to create. Both fixed:
|
|
162
|
+
|
|
163
|
+
- **`little_mcar_test`** now accepts `backend=` and `algorithm=`,
|
|
164
|
+
forwarded to `mlest`. The per-pattern test-statistic accumulation
|
|
165
|
+
still runs on CPU (O(P × v³) for tiny v — never the bottleneck).
|
|
166
|
+
GPU results match CPU within FP32 tolerance (Δ stat ≈ 1.4e-4 on
|
|
167
|
+
the apple dataset).
|
|
168
|
+
- **`auto_arima`** now accepts `backend=` and `method=`, threaded
|
|
169
|
+
through `_stepwise_search` / `_grid_search` / `_try_fit` so every
|
|
170
|
+
candidate fit honours the same backend. Pass
|
|
171
|
+
`method='Whittle', backend='gpu'` to run each candidate on GPU.
|
|
172
|
+
|
|
173
|
+
Also codified the "when to add a GPU backend, and when not to" rule
|
|
174
|
+
as Section 0 of `pystatistics/GPU_BACKEND_CONVENTION.md` — the
|
|
175
|
+
absence of `backends/gpu*.py` in a module (`anova`, `ets`, `coxph`,
|
|
176
|
+
`factor_analysis`, acf / stationarity) is a deliberate statement,
|
|
177
|
+
not an oversight. GPU backends belong on workloads that actually
|
|
178
|
+
map to GPU hardware (large dense linear algebra, big-N likelihoods,
|
|
179
|
+
batched fits, frequency-domain transforms), not on everything.
|
|
180
|
+
|
|
54
181
|
### 2.0.0 — CPU is now the default backend everywhere (breaking)
|
|
55
182
|
|
|
56
183
|
Every public solver that previously defaulted to `backend='auto'` now
|
|
@@ -4,6 +4,133 @@ GPU-accelerated statistical computing for Python.
|
|
|
4
4
|
|
|
5
5
|
## What's New
|
|
6
6
|
|
|
7
|
+
### 2.1.0 — Real-data EM speedup + monotone closed-form MLE
|
|
8
|
+
|
|
9
|
+
Dogfooding via Project Lacuna surfaced that ``little_mcar_test`` on
|
|
10
|
+
realistic tabular data (sklearn's iris / wine / breast_cancer with
|
|
11
|
+
random MCAR injection) was bottlenecked by EM: the E-step was a
|
|
12
|
+
Python loop over missingness patterns, and each SQUAREM-style
|
|
13
|
+
safeguard pass re-ran a per-pattern log-likelihood. This release
|
|
14
|
+
batches both and adds Varadhan & Roland's SQUAREM acceleration.
|
|
15
|
+
|
|
16
|
+
End-to-end ``little_mcar_test`` wall-clock at 15 % MCAR, seed 0:
|
|
17
|
+
|
|
18
|
+
| dataset | shape | 2.0.1 | 2.1.0 | speedup |
|
|
19
|
+
|----------------|-----------|----------|----------|---------|
|
|
20
|
+
| missvals | 13 × 5 | 19.9 ms | 9.5 ms | 2.1× |
|
|
21
|
+
| wine | 178 × 13 | 79.4 ms | 41.5 ms | 1.9× |
|
|
22
|
+
| breast_cancer | 569 × 30 | 3278 ms | 2089 ms | 1.6× |
|
|
23
|
+
|
|
24
|
+
For repeated-diagnostic workflows (e.g. an MCAR sweep over several
|
|
25
|
+
thousand datasets), this turns a 3-hour run into a 2-hour run.
|
|
26
|
+
|
|
27
|
+
Three stacked improvements, all preserving bit-equivalence on the R
|
|
28
|
+
mvnmle reference cases (apple, missvals):
|
|
29
|
+
|
|
30
|
+
- **Batched per-pattern conditional parameters.** The E-step's
|
|
31
|
+
per-pattern Cholesky + triangular solve now runs as a single
|
|
32
|
+
batched kernel pair across all missingness patterns. The
|
|
33
|
+
unused padding slots are identity-filled so the Cholesky stays
|
|
34
|
+
well-defined.
|
|
35
|
+
- **SQUAREM acceleration on top of EM.** Three EM steps + one
|
|
36
|
+
Steffensen-style extrapolation, safeguarded by a monotonicity
|
|
37
|
+
check on the observed-data log-likelihood. Typical effect:
|
|
38
|
+
2–4× fewer EM-step equivalents to convergence. Convergence
|
|
39
|
+
point is the same MLE — only the path is shorter. On by
|
|
40
|
+
default; ``EMBackend.solve(..., accelerate=False)`` recovers
|
|
41
|
+
the plain-EM reference.
|
|
42
|
+
- **Fully batched log-likelihood.** The SQUAREM monotonicity
|
|
43
|
+
check calls ``loglik`` often, so it was batched too — one
|
|
44
|
+
Cholesky over all patterns, one solve across all N
|
|
45
|
+
observations, no per-pattern Python loop.
|
|
46
|
+
|
|
47
|
+
**`mom_mcar_test`: fast method-of-moments MCAR test.** A new *separate
|
|
48
|
+
function* (not a mode on ``little_mcar_test``, because the MoM variant
|
|
49
|
+
is not Little's test) that uses pairwise-deletion sample moments
|
|
50
|
+
instead of MLE plug-in. The test is consistent under MCAR but not
|
|
51
|
+
asymptotically efficient, trading a small amount of statistical
|
|
52
|
+
efficiency for dramatic speed. At 15 % MCAR on sklearn demos:
|
|
53
|
+
|
|
54
|
+
| dataset | shape | little_mcar_test | mom_mcar_test |
|
|
55
|
+
|----------------|-----------|------------------|---------------|
|
|
56
|
+
| iris | 150 × 4 | 2.9 ms | 0.31 ms |
|
|
57
|
+
| wine | 178 × 13 | 60.9 ms | 2.17 ms |
|
|
58
|
+
| breast_cancer | 569 × 30 | 1491 ms | 28.7 ms |
|
|
59
|
+
|
|
60
|
+
For a 3410-dataset MCAR sweep: **~50 minutes → ~1.6 minutes**. Use
|
|
61
|
+
``little_mcar_test`` when you need Little 1988's asymptotic
|
|
62
|
+
distribution exactly (regulated submissions, citing R reference);
|
|
63
|
+
use ``mom_mcar_test`` for high-throughput diagnostic screens. The
|
|
64
|
+
``MCARTestResult.method`` field records which test produced a given
|
|
65
|
+
result so downstream code can disambiguate without tracking the
|
|
66
|
+
calling function.
|
|
67
|
+
|
|
68
|
+
**Fully-batched device-resident EM on GPU.** Pre-2.1.0 the
|
|
69
|
+
``device='cuda'`` EM path set up a torch device but never used it —
|
|
70
|
+
numpy ran for every backend. This release implements a real
|
|
71
|
+
device-resident loop with fully batched E-step / M-step / log-
|
|
72
|
+
likelihood, SQUAREM acceleration on top, all on device. On breast-
|
|
73
|
+
cancer-scale (569 × 30) EM drops from 2142 ms CPU to 147 ms GPU
|
|
74
|
+
(14.6×). Small data remains CPU-faster; an empirical size heuristic
|
|
75
|
+
(``n * v >= 1500``) with visible dispatch warnings keeps this
|
|
76
|
+
correct in user-facing behaviour.
|
|
77
|
+
|
|
78
|
+
**Monotone-missingness closed-form MLE** (Anderson 1957). Longitudinal
|
|
79
|
+
cohorts with attrition, panel surveys with dropout, and most
|
|
80
|
+
sequentially-administered instruments produce *monotone* missingness
|
|
81
|
+
— the variables can be ordered such that each observation's missing
|
|
82
|
+
entries form a contiguous suffix. When the pattern is monotone, the
|
|
83
|
+
MVN MLE has a closed form via a chain of OLS regressions, with no
|
|
84
|
+
iteration. New helpers: ``mvnmle.is_monotone(data)``,
|
|
85
|
+
``mvnmle.monotone_permutation(data)``, and
|
|
86
|
+
``mlest(data, algorithm='monotone')``. The closed-form matches R
|
|
87
|
+
``mvnmle`` bit-for-bit on canonical datasets and is orders of
|
|
88
|
+
magnitude faster than EM on larger-v longitudinal data. Per Rule 1
|
|
89
|
+
the algorithm raises on non-monotone input rather than silently
|
|
90
|
+
falling back — call ``is_monotone`` first if you want conditional
|
|
91
|
+
dispatch.
|
|
92
|
+
|
|
93
|
+
Also in this release:
|
|
94
|
+
|
|
95
|
+
- **Benchmark harness** under ``benchmarks/mvnmle_bench.py`` for
|
|
96
|
+
tracking wall-clock and iteration counts across the reference
|
|
97
|
+
shapes; use the ``--tag`` flag to label a baseline for diff
|
|
98
|
+
against future changes.
|
|
99
|
+
- **Documented finding**: the ``device='cuda'`` EM path was never
|
|
100
|
+
actually running on the GPU prior to this release — it stored
|
|
101
|
+
a torch device but never used it. We tried to wire up a real
|
|
102
|
+
device-resident loop and found GPU is slower than CPU for all
|
|
103
|
+
shapes we tested (per-pattern launch overhead still dominates
|
|
104
|
+
the tiny per-pattern matrix work). GPU EM therefore remains
|
|
105
|
+
CPU-equivalent by design; a future release will revisit if a
|
|
106
|
+
workload appears where full observation-level batching makes
|
|
107
|
+
GPU actually win.
|
|
108
|
+
|
|
109
|
+
### 2.0.1 — GPU-backend exposure gaps and a convention rule
|
|
110
|
+
|
|
111
|
+
Two public functions had GPU-capable inner calls but no `backend=`
|
|
112
|
+
parameter, so there was no way to route them through the GPU path —
|
|
113
|
+
exactly the regression the 2.0.0 CPU-default sweep was trying *not*
|
|
114
|
+
to create. Both fixed:
|
|
115
|
+
|
|
116
|
+
- **`little_mcar_test`** now accepts `backend=` and `algorithm=`,
|
|
117
|
+
forwarded to `mlest`. The per-pattern test-statistic accumulation
|
|
118
|
+
still runs on CPU (O(P × v³) for tiny v — never the bottleneck).
|
|
119
|
+
GPU results match CPU within FP32 tolerance (Δ stat ≈ 1.4e-4 on
|
|
120
|
+
the apple dataset).
|
|
121
|
+
- **`auto_arima`** now accepts `backend=` and `method=`, threaded
|
|
122
|
+
through `_stepwise_search` / `_grid_search` / `_try_fit` so every
|
|
123
|
+
candidate fit honours the same backend. Pass
|
|
124
|
+
`method='Whittle', backend='gpu'` to run each candidate on GPU.
|
|
125
|
+
|
|
126
|
+
Also codified the "when to add a GPU backend, and when not to" rule
|
|
127
|
+
as Section 0 of `pystatistics/GPU_BACKEND_CONVENTION.md` — the
|
|
128
|
+
absence of `backends/gpu*.py` in a module (`anova`, `ets`, `coxph`,
|
|
129
|
+
`factor_analysis`, acf / stationarity) is a deliberate statement,
|
|
130
|
+
not an oversight. GPU backends belong on workloads that actually
|
|
131
|
+
map to GPU hardware (large dense linear algebra, big-N likelihoods,
|
|
132
|
+
batched fits, frequency-domain transforms), not on everything.
|
|
133
|
+
|
|
7
134
|
### 2.0.0 — CPU is now the default backend everywhere (breaking)
|
|
8
135
|
|
|
9
136
|
Every public solver that previously defaulted to `backend='auto'` now
|