kerneltests 0.0.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.
- kerneltests-0.0.1/LICENSE +10 -0
- kerneltests-0.0.1/PKG-INFO +116 -0
- kerneltests-0.0.1/README.md +94 -0
- kerneltests-0.0.1/kerneltests.egg-info/PKG-INFO +116 -0
- kerneltests-0.0.1/kerneltests.egg-info/SOURCES.txt +24 -0
- kerneltests-0.0.1/kerneltests.egg-info/dependency_links.txt +1 -0
- kerneltests-0.0.1/kerneltests.egg-info/requires.txt +14 -0
- kerneltests-0.0.1/kerneltests.egg-info/top_level.txt +1 -0
- kerneltests-0.0.1/kt/__init__.py +5 -0
- kerneltests-0.0.1/kt/_common.py +21 -0
- kerneltests-0.0.1/kt/agginc.py +264 -0
- kerneltests-0.0.1/kt/api.py +74 -0
- kerneltests-0.0.1/kt/backends/__init__.py +15 -0
- kerneltests-0.0.1/kt/backends/jax_mmdagg.py +107 -0
- kerneltests-0.0.1/kt/ksdagg.py +129 -0
- kerneltests-0.0.1/kt/mmdagg.py +177 -0
- kerneltests-0.0.1/kt/mmdfuse.py +141 -0
- kerneltests-0.0.1/pyproject.toml +23 -0
- kerneltests-0.0.1/setup.cfg +4 -0
- kerneltests-0.0.1/tests/test_agginc.py +88 -0
- kerneltests-0.0.1/tests/test_api.py +46 -0
- kerneltests-0.0.1/tests/test_backends_missing.py +23 -0
- kerneltests-0.0.1/tests/test_jax_backend.py +56 -0
- kerneltests-0.0.1/tests/test_ksdagg.py +57 -0
- kerneltests-0.0.1/tests/test_mmdagg.py +60 -0
- kerneltests-0.0.1/tests/test_mmdfuse.py +80 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ankith Burki
|
|
4
|
+
Portions adapted from https://github.com/antoninschrab/mmdagg, Copyright (c) 2023 Antonin Schrab (MIT).
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
7
|
+
|
|
8
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
9
|
+
|
|
10
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kerneltests
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Unified, tested implementations of modern kernel hypothesis tests (MMDAgg, ...)
|
|
5
|
+
Author: Ankith Burki
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.9
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: numpy>=1.22
|
|
11
|
+
Requires-Dist: scipy>=1.8
|
|
12
|
+
Provides-Extra: test
|
|
13
|
+
Requires-Dist: pytest; extra == "test"
|
|
14
|
+
Requires-Dist: pytest-cov; extra == "test"
|
|
15
|
+
Provides-Extra: jax
|
|
16
|
+
Requires-Dist: jax>=0.4; extra == "jax"
|
|
17
|
+
Provides-Extra: docs
|
|
18
|
+
Requires-Dist: mkdocs; extra == "docs"
|
|
19
|
+
Requires-Dist: mkdocs-material; extra == "docs"
|
|
20
|
+
Requires-Dist: mkdocstrings[python]; extra == "docs"
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
# kerneltests
|
|
24
|
+
|
|
25
|
+
`kerneltests` (import name `kt`) gives you modern kernel hypothesis tests behind one small API: two-sample testing (**MMDAgg**, **MMDAggInc**, **MMD-FUSE**), goodness-of-fit testing (**KSDAgg**, **KSDAggInc**) and independence testing (**HSICAggInc**). Every port is checked against the original reference implementations by Schrab et al. and gives **bit-exact** agreement for the same seed (MMD-FUSE, whose reference is JAX, agrees to rtol 1e-6 given the same permutations) (identical decisions, statistics, quantiles, p-values and thresholds) when run with `fast=False`. The default `fast=True` path for equal sample sizes is 1.7–2.3× faster than the reference MMDAgg and agrees with it up to floating-point rounding (identical decisions in all tested cases; statistics within ~1e-12 relative). The ports also fix five confirmed bugs in the references (all listed in CHANGELOG.md), including:
|
|
26
|
+
|
|
27
|
+
1. **MMDAgg p-values.** With `kernel="laplace_gaussian"`, the reference reports Gaussian-kernel p-values that duplicate the Laplace ones, because `mmdagg/np.py` line 352 indexes `p_vals[i]` where it should use `p_vals[idx]`.
|
|
28
|
+
2. **KSDAgg internal assertion.** The reference can raise an `AssertionError` when its two equivalent rejection rules (`p-value <= threshold` and `KSD > quantile`) disagree because of floating-point rounding.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install git+<repository-url> # or, from a clone:
|
|
34
|
+
pip install -e .
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
You need Python 3.9 or newer, NumPy 1.22 or newer, and SciPy 1.8 or newer.
|
|
38
|
+
|
|
39
|
+
Optional JAX backend for MMDAgg (`mmdagg(X, Y, backend="jax")`, also accepted by `kt.two_sample`):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install -e .[jax]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
It uses the same random draws as the NumPy path and gives identical decisions; see the *Backends* section of the user guide and `experiments/jax_backend/results.md` for timings.
|
|
46
|
+
|
|
47
|
+
## Quickstart
|
|
48
|
+
|
|
49
|
+
Two-sample test (are `X` and `Y` drawn from the same distribution?):
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
import numpy as np
|
|
53
|
+
import kt
|
|
54
|
+
|
|
55
|
+
rng = np.random.default_rng(0)
|
|
56
|
+
X = rng.standard_normal((200, 2))
|
|
57
|
+
Y = rng.standard_normal((200, 2)) + 0.5
|
|
58
|
+
res = kt.two_sample(X, Y)
|
|
59
|
+
print(res) # TestResult(reject=True, method='mmdagg', alpha=0.05)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Goodness-of-fit test (does `X` come from N(0, I), whose score is `-x`?):
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
rng = np.random.default_rng(1)
|
|
66
|
+
X = rng.standard_normal((300, 2)) + 0.3
|
|
67
|
+
res = kt.goodness_of_fit(X, score_X=-X)
|
|
68
|
+
print(res.reject, int(res.details["reject"].sum()), "of", len(res.details["reject"]))
|
|
69
|
+
# True 10 of 10
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`res.details` holds diagnostics for each kernel and bandwidth (statistic, quantile, p-value, threshold, reject). See the [documentation](docs/index.md).
|
|
73
|
+
|
|
74
|
+
## Citing
|
|
75
|
+
|
|
76
|
+
If you use these tests, please cite the original papers:
|
|
77
|
+
|
|
78
|
+
```bibtex
|
|
79
|
+
@article{schrab2023mmdagg,
|
|
80
|
+
author = {Antonin Schrab and Ilmun Kim and M{\'e}lisande Albert and B{\'e}atrice Laurent and Benjamin Guedj and Arthur Gretton},
|
|
81
|
+
title = {{MMD} Aggregated Two-Sample Test},
|
|
82
|
+
journal = {Journal of Machine Learning Research},
|
|
83
|
+
year = {2023}, volume = {24}, number = {194}, pages = {1--81},
|
|
84
|
+
url = {http://jmlr.org/papers/v24/21-1289.html}
|
|
85
|
+
}
|
|
86
|
+
@inproceedings{schrab2022ksdagg,
|
|
87
|
+
author = {Antonin Schrab and Benjamin Guedj and Arthur Gretton},
|
|
88
|
+
title = {{KSD} Aggregated Goodness-of-fit Test},
|
|
89
|
+
booktitle = {Advances in Neural Information Processing Systems (NeurIPS)},
|
|
90
|
+
year = {2022}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The ports are adapted from the MIT-licensed reference packages [antoninschrab/mmdagg](https://github.com/antoninschrab/mmdagg), [antoninschrab/ksdagg](https://github.com/antoninschrab/ksdagg) and [antoninschrab/mmdfuse](https://github.com/antoninschrab/mmdfuse).
|
|
95
|
+
|
|
96
|
+
## Testing and verification
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pip install -e .[test]
|
|
100
|
+
pytest --cov=kt --cov-config=.coveragerc
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The unit tests check power against clear alternatives, Type I error control under the null (Monte Carlo, within 3 standard errors), determinism for a fixed seed, input validation, and a regression test for the p-value bug. Parity with the references is checked separately against every MMDAgg kernel option, all four weightings, both resampling schemes, and KSDAgg wild-bootstrap and parametric modes. See [docs/verification.md](docs/verification.md). CI runs on Linux, macOS and Windows with Python 3.9 to 3.13.
|
|
104
|
+
|
|
105
|
+
## Roadmap
|
|
106
|
+
|
|
107
|
+
- GPU benchmarks for the JAX backend (implemented, untested on GPU)
|
|
108
|
+
- Fast path for the permutation (unequal sample size) MMDAgg calibration
|
|
109
|
+
|
|
110
|
+
## Contributing
|
|
111
|
+
|
|
112
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). Every new port has to match its reference implementation exactly.
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# kerneltests
|
|
2
|
+
|
|
3
|
+
`kerneltests` (import name `kt`) gives you modern kernel hypothesis tests behind one small API: two-sample testing (**MMDAgg**, **MMDAggInc**, **MMD-FUSE**), goodness-of-fit testing (**KSDAgg**, **KSDAggInc**) and independence testing (**HSICAggInc**). Every port is checked against the original reference implementations by Schrab et al. and gives **bit-exact** agreement for the same seed (MMD-FUSE, whose reference is JAX, agrees to rtol 1e-6 given the same permutations) (identical decisions, statistics, quantiles, p-values and thresholds) when run with `fast=False`. The default `fast=True` path for equal sample sizes is 1.7–2.3× faster than the reference MMDAgg and agrees with it up to floating-point rounding (identical decisions in all tested cases; statistics within ~1e-12 relative). The ports also fix five confirmed bugs in the references (all listed in CHANGELOG.md), including:
|
|
4
|
+
|
|
5
|
+
1. **MMDAgg p-values.** With `kernel="laplace_gaussian"`, the reference reports Gaussian-kernel p-values that duplicate the Laplace ones, because `mmdagg/np.py` line 352 indexes `p_vals[i]` where it should use `p_vals[idx]`.
|
|
6
|
+
2. **KSDAgg internal assertion.** The reference can raise an `AssertionError` when its two equivalent rejection rules (`p-value <= threshold` and `KSD > quantile`) disagree because of floating-point rounding.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pip install git+<repository-url> # or, from a clone:
|
|
12
|
+
pip install -e .
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
You need Python 3.9 or newer, NumPy 1.22 or newer, and SciPy 1.8 or newer.
|
|
16
|
+
|
|
17
|
+
Optional JAX backend for MMDAgg (`mmdagg(X, Y, backend="jax")`, also accepted by `kt.two_sample`):
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install -e .[jax]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
It uses the same random draws as the NumPy path and gives identical decisions; see the *Backends* section of the user guide and `experiments/jax_backend/results.md` for timings.
|
|
24
|
+
|
|
25
|
+
## Quickstart
|
|
26
|
+
|
|
27
|
+
Two-sample test (are `X` and `Y` drawn from the same distribution?):
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
import numpy as np
|
|
31
|
+
import kt
|
|
32
|
+
|
|
33
|
+
rng = np.random.default_rng(0)
|
|
34
|
+
X = rng.standard_normal((200, 2))
|
|
35
|
+
Y = rng.standard_normal((200, 2)) + 0.5
|
|
36
|
+
res = kt.two_sample(X, Y)
|
|
37
|
+
print(res) # TestResult(reject=True, method='mmdagg', alpha=0.05)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Goodness-of-fit test (does `X` come from N(0, I), whose score is `-x`?):
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
rng = np.random.default_rng(1)
|
|
44
|
+
X = rng.standard_normal((300, 2)) + 0.3
|
|
45
|
+
res = kt.goodness_of_fit(X, score_X=-X)
|
|
46
|
+
print(res.reject, int(res.details["reject"].sum()), "of", len(res.details["reject"]))
|
|
47
|
+
# True 10 of 10
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`res.details` holds diagnostics for each kernel and bandwidth (statistic, quantile, p-value, threshold, reject). See the [documentation](docs/index.md).
|
|
51
|
+
|
|
52
|
+
## Citing
|
|
53
|
+
|
|
54
|
+
If you use these tests, please cite the original papers:
|
|
55
|
+
|
|
56
|
+
```bibtex
|
|
57
|
+
@article{schrab2023mmdagg,
|
|
58
|
+
author = {Antonin Schrab and Ilmun Kim and M{\'e}lisande Albert and B{\'e}atrice Laurent and Benjamin Guedj and Arthur Gretton},
|
|
59
|
+
title = {{MMD} Aggregated Two-Sample Test},
|
|
60
|
+
journal = {Journal of Machine Learning Research},
|
|
61
|
+
year = {2023}, volume = {24}, number = {194}, pages = {1--81},
|
|
62
|
+
url = {http://jmlr.org/papers/v24/21-1289.html}
|
|
63
|
+
}
|
|
64
|
+
@inproceedings{schrab2022ksdagg,
|
|
65
|
+
author = {Antonin Schrab and Benjamin Guedj and Arthur Gretton},
|
|
66
|
+
title = {{KSD} Aggregated Goodness-of-fit Test},
|
|
67
|
+
booktitle = {Advances in Neural Information Processing Systems (NeurIPS)},
|
|
68
|
+
year = {2022}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The ports are adapted from the MIT-licensed reference packages [antoninschrab/mmdagg](https://github.com/antoninschrab/mmdagg), [antoninschrab/ksdagg](https://github.com/antoninschrab/ksdagg) and [antoninschrab/mmdfuse](https://github.com/antoninschrab/mmdfuse).
|
|
73
|
+
|
|
74
|
+
## Testing and verification
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pip install -e .[test]
|
|
78
|
+
pytest --cov=kt --cov-config=.coveragerc
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The unit tests check power against clear alternatives, Type I error control under the null (Monte Carlo, within 3 standard errors), determinism for a fixed seed, input validation, and a regression test for the p-value bug. Parity with the references is checked separately against every MMDAgg kernel option, all four weightings, both resampling schemes, and KSDAgg wild-bootstrap and parametric modes. See [docs/verification.md](docs/verification.md). CI runs on Linux, macOS and Windows with Python 3.9 to 3.13.
|
|
82
|
+
|
|
83
|
+
## Roadmap
|
|
84
|
+
|
|
85
|
+
- GPU benchmarks for the JAX backend (implemented, untested on GPU)
|
|
86
|
+
- Fast path for the permutation (unequal sample size) MMDAgg calibration
|
|
87
|
+
|
|
88
|
+
## Contributing
|
|
89
|
+
|
|
90
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). Every new port has to match its reference implementation exactly.
|
|
91
|
+
|
|
92
|
+
## License
|
|
93
|
+
|
|
94
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kerneltests
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Unified, tested implementations of modern kernel hypothesis tests (MMDAgg, ...)
|
|
5
|
+
Author: Ankith Burki
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.9
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: numpy>=1.22
|
|
11
|
+
Requires-Dist: scipy>=1.8
|
|
12
|
+
Provides-Extra: test
|
|
13
|
+
Requires-Dist: pytest; extra == "test"
|
|
14
|
+
Requires-Dist: pytest-cov; extra == "test"
|
|
15
|
+
Provides-Extra: jax
|
|
16
|
+
Requires-Dist: jax>=0.4; extra == "jax"
|
|
17
|
+
Provides-Extra: docs
|
|
18
|
+
Requires-Dist: mkdocs; extra == "docs"
|
|
19
|
+
Requires-Dist: mkdocs-material; extra == "docs"
|
|
20
|
+
Requires-Dist: mkdocstrings[python]; extra == "docs"
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
# kerneltests
|
|
24
|
+
|
|
25
|
+
`kerneltests` (import name `kt`) gives you modern kernel hypothesis tests behind one small API: two-sample testing (**MMDAgg**, **MMDAggInc**, **MMD-FUSE**), goodness-of-fit testing (**KSDAgg**, **KSDAggInc**) and independence testing (**HSICAggInc**). Every port is checked against the original reference implementations by Schrab et al. and gives **bit-exact** agreement for the same seed (MMD-FUSE, whose reference is JAX, agrees to rtol 1e-6 given the same permutations) (identical decisions, statistics, quantiles, p-values and thresholds) when run with `fast=False`. The default `fast=True` path for equal sample sizes is 1.7–2.3× faster than the reference MMDAgg and agrees with it up to floating-point rounding (identical decisions in all tested cases; statistics within ~1e-12 relative). The ports also fix five confirmed bugs in the references (all listed in CHANGELOG.md), including:
|
|
26
|
+
|
|
27
|
+
1. **MMDAgg p-values.** With `kernel="laplace_gaussian"`, the reference reports Gaussian-kernel p-values that duplicate the Laplace ones, because `mmdagg/np.py` line 352 indexes `p_vals[i]` where it should use `p_vals[idx]`.
|
|
28
|
+
2. **KSDAgg internal assertion.** The reference can raise an `AssertionError` when its two equivalent rejection rules (`p-value <= threshold` and `KSD > quantile`) disagree because of floating-point rounding.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install git+<repository-url> # or, from a clone:
|
|
34
|
+
pip install -e .
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
You need Python 3.9 or newer, NumPy 1.22 or newer, and SciPy 1.8 or newer.
|
|
38
|
+
|
|
39
|
+
Optional JAX backend for MMDAgg (`mmdagg(X, Y, backend="jax")`, also accepted by `kt.two_sample`):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install -e .[jax]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
It uses the same random draws as the NumPy path and gives identical decisions; see the *Backends* section of the user guide and `experiments/jax_backend/results.md` for timings.
|
|
46
|
+
|
|
47
|
+
## Quickstart
|
|
48
|
+
|
|
49
|
+
Two-sample test (are `X` and `Y` drawn from the same distribution?):
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
import numpy as np
|
|
53
|
+
import kt
|
|
54
|
+
|
|
55
|
+
rng = np.random.default_rng(0)
|
|
56
|
+
X = rng.standard_normal((200, 2))
|
|
57
|
+
Y = rng.standard_normal((200, 2)) + 0.5
|
|
58
|
+
res = kt.two_sample(X, Y)
|
|
59
|
+
print(res) # TestResult(reject=True, method='mmdagg', alpha=0.05)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Goodness-of-fit test (does `X` come from N(0, I), whose score is `-x`?):
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
rng = np.random.default_rng(1)
|
|
66
|
+
X = rng.standard_normal((300, 2)) + 0.3
|
|
67
|
+
res = kt.goodness_of_fit(X, score_X=-X)
|
|
68
|
+
print(res.reject, int(res.details["reject"].sum()), "of", len(res.details["reject"]))
|
|
69
|
+
# True 10 of 10
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`res.details` holds diagnostics for each kernel and bandwidth (statistic, quantile, p-value, threshold, reject). See the [documentation](docs/index.md).
|
|
73
|
+
|
|
74
|
+
## Citing
|
|
75
|
+
|
|
76
|
+
If you use these tests, please cite the original papers:
|
|
77
|
+
|
|
78
|
+
```bibtex
|
|
79
|
+
@article{schrab2023mmdagg,
|
|
80
|
+
author = {Antonin Schrab and Ilmun Kim and M{\'e}lisande Albert and B{\'e}atrice Laurent and Benjamin Guedj and Arthur Gretton},
|
|
81
|
+
title = {{MMD} Aggregated Two-Sample Test},
|
|
82
|
+
journal = {Journal of Machine Learning Research},
|
|
83
|
+
year = {2023}, volume = {24}, number = {194}, pages = {1--81},
|
|
84
|
+
url = {http://jmlr.org/papers/v24/21-1289.html}
|
|
85
|
+
}
|
|
86
|
+
@inproceedings{schrab2022ksdagg,
|
|
87
|
+
author = {Antonin Schrab and Benjamin Guedj and Arthur Gretton},
|
|
88
|
+
title = {{KSD} Aggregated Goodness-of-fit Test},
|
|
89
|
+
booktitle = {Advances in Neural Information Processing Systems (NeurIPS)},
|
|
90
|
+
year = {2022}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The ports are adapted from the MIT-licensed reference packages [antoninschrab/mmdagg](https://github.com/antoninschrab/mmdagg), [antoninschrab/ksdagg](https://github.com/antoninschrab/ksdagg) and [antoninschrab/mmdfuse](https://github.com/antoninschrab/mmdfuse).
|
|
95
|
+
|
|
96
|
+
## Testing and verification
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pip install -e .[test]
|
|
100
|
+
pytest --cov=kt --cov-config=.coveragerc
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The unit tests check power against clear alternatives, Type I error control under the null (Monte Carlo, within 3 standard errors), determinism for a fixed seed, input validation, and a regression test for the p-value bug. Parity with the references is checked separately against every MMDAgg kernel option, all four weightings, both resampling schemes, and KSDAgg wild-bootstrap and parametric modes. See [docs/verification.md](docs/verification.md). CI runs on Linux, macOS and Windows with Python 3.9 to 3.13.
|
|
104
|
+
|
|
105
|
+
## Roadmap
|
|
106
|
+
|
|
107
|
+
- GPU benchmarks for the JAX backend (implemented, untested on GPU)
|
|
108
|
+
- Fast path for the permutation (unequal sample size) MMDAgg calibration
|
|
109
|
+
|
|
110
|
+
## Contributing
|
|
111
|
+
|
|
112
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). Every new port has to match its reference implementation exactly.
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
kerneltests.egg-info/PKG-INFO
|
|
5
|
+
kerneltests.egg-info/SOURCES.txt
|
|
6
|
+
kerneltests.egg-info/dependency_links.txt
|
|
7
|
+
kerneltests.egg-info/requires.txt
|
|
8
|
+
kerneltests.egg-info/top_level.txt
|
|
9
|
+
kt/__init__.py
|
|
10
|
+
kt/_common.py
|
|
11
|
+
kt/agginc.py
|
|
12
|
+
kt/api.py
|
|
13
|
+
kt/ksdagg.py
|
|
14
|
+
kt/mmdagg.py
|
|
15
|
+
kt/mmdfuse.py
|
|
16
|
+
kt/backends/__init__.py
|
|
17
|
+
kt/backends/jax_mmdagg.py
|
|
18
|
+
tests/test_agginc.py
|
|
19
|
+
tests/test_api.py
|
|
20
|
+
tests/test_backends_missing.py
|
|
21
|
+
tests/test_jax_backend.py
|
|
22
|
+
tests/test_ksdagg.py
|
|
23
|
+
tests/test_mmdagg.py
|
|
24
|
+
tests/test_mmdfuse.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
kt
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"""kerneltests: unified, tested implementations of modern kernel hypothesis tests."""
|
|
2
|
+
from .api import TestResult, two_sample, goodness_of_fit, independence
|
|
3
|
+
|
|
4
|
+
__version__ = "0.1.0.dev0"
|
|
5
|
+
__all__ = ["TestResult", "two_sample", "goodness_of_fit", "independence", "__version__"]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Shared helpers. Weights follow Schrab et al. (MIT reference code) in the same
|
|
2
|
+
floating-point evaluation order, which keeps results bit-identical to the references."""
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
WEIGHTS = ("uniform", "decreasing", "increasing", "centred")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def weights(N: int, weights_type: str) -> np.ndarray:
|
|
9
|
+
if weights_type not in WEIGHTS:
|
|
10
|
+
raise ValueError(f"weights_type must be one of {WEIGHTS}")
|
|
11
|
+
if weights_type == "uniform":
|
|
12
|
+
return np.array([1 / N] * N)
|
|
13
|
+
if weights_type == "decreasing":
|
|
14
|
+
z = sum(1 / k for k in range(1, N + 1))
|
|
15
|
+
return np.array([1 / (k * z) for k in range(1, N + 1)])
|
|
16
|
+
if weights_type == "increasing":
|
|
17
|
+
z = sum(1 / k for k in range(1, N + 1))
|
|
18
|
+
return np.array([1 / ((N + 1 - k) * z) for k in range(1, N + 1)])
|
|
19
|
+
off = 1 if N % 2 == 1 else 0.5
|
|
20
|
+
z = sum(1 / (abs((N + 1) / 2 - k) + off) for k in range(1, N + 1))
|
|
21
|
+
return np.array([1 / ((abs((N + 1) / 2 - k) + off) * z) for k in range(1, N + 1)])
|