bayesian-sparse-gmm 0.1.2__tar.gz → 0.2.2__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.
Files changed (46) hide show
  1. bayesian_sparse_gmm-0.2.2/PKG-INFO +190 -0
  2. bayesian_sparse_gmm-0.2.2/README.md +164 -0
  3. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/evaluate.py +173 -80
  4. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/pyproject.toml +11 -0
  5. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/src/bayesian_sparse_gmm/__init__.py +1 -1
  6. bayesian_sparse_gmm-0.2.2/src/bayesian_sparse_gmm/backends/__init__.py +59 -0
  7. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/src/bayesian_sparse_gmm/backends/_cuda.py +22 -21
  8. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/src/bayesian_sparse_gmm/backends/_numba.py +32 -7
  9. bayesian_sparse_gmm-0.2.2/src/bayesian_sparse_gmm/config.py +32 -0
  10. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/src/bayesian_sparse_gmm/model.py +81 -33
  11. bayesian_sparse_gmm-0.2.2/src/bayesian_sparse_gmm/postprocessing.py +74 -0
  12. bayesian_sparse_gmm-0.2.2/src/bayesian_sparse_gmm/sampler.py +252 -0
  13. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/src/bayesian_sparse_gmm/state.py +2 -1
  14. bayesian_sparse_gmm-0.2.2/src/bayesian_sparse_gmm/urn.py +67 -0
  15. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/tests/test_backends.py +51 -0
  16. bayesian_sparse_gmm-0.2.2/tests/test_cuda.py +129 -0
  17. bayesian_sparse_gmm-0.2.2/tests/test_identity_cov.py +188 -0
  18. bayesian_sparse_gmm-0.2.2/tests/test_laplace.py +19 -0
  19. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/tests/test_model.py +31 -2
  20. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/tests/test_numba.py +1 -1
  21. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/tests/test_phase1.py +6 -6
  22. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/tests/test_sampler.py +28 -22
  23. bayesian_sparse_gmm-0.2.2/tests/test_synthetic.py +54 -0
  24. bayesian_sparse_gmm-0.2.2/tests/test_theta_update.py +98 -0
  25. bayesian_sparse_gmm-0.2.2/tests/test_urn_weight.py +44 -0
  26. bayesian_sparse_gmm-0.2.2/tests/test_variable_k.py +42 -0
  27. bayesian_sparse_gmm-0.2.2/tests/test_xi.py +36 -0
  28. bayesian_sparse_gmm-0.2.2/tests/test_xi_update.py +77 -0
  29. bayesian_sparse_gmm-0.2.2/uv.lock +2210 -0
  30. bayesian_sparse_gmm-0.1.2/PKG-INFO +0 -107
  31. bayesian_sparse_gmm-0.1.2/README.md +0 -83
  32. bayesian_sparse_gmm-0.1.2/src/bayesian_sparse_gmm/backends/__init__.py +0 -52
  33. bayesian_sparse_gmm-0.1.2/src/bayesian_sparse_gmm/config.py +0 -29
  34. bayesian_sparse_gmm-0.1.2/src/bayesian_sparse_gmm/postprocessing.py +0 -46
  35. bayesian_sparse_gmm-0.1.2/src/bayesian_sparse_gmm/sampler.py +0 -167
  36. bayesian_sparse_gmm-0.1.2/tests/test_cuda.py +0 -38
  37. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/.flake8 +0 -0
  38. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/.github/workflows/release.yml +0 -0
  39. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/.gitignore +0 -0
  40. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/LICENSE +0 -0
  41. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/src/bayesian_sparse_gmm/backends/_base.py +0 -0
  42. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/src/bayesian_sparse_gmm/backends/_numpy.py +0 -0
  43. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/src/bayesian_sparse_gmm/diagnostics.py +0 -0
  44. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/src/bayesian_sparse_gmm/utils.py +0 -0
  45. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/tests/__init__.py +0 -0
  46. {bayesian_sparse_gmm-0.1.2 → bayesian_sparse_gmm-0.2.2}/tests/test_diagnostics.py +0 -0
@@ -0,0 +1,190 @@
1
+ Metadata-Version: 2.4
2
+ Name: bayesian-sparse-gmm
3
+ Version: 0.2.2
4
+ Summary: Bayesian Sparse Gaussian Mixture Model implementation in Python
5
+ Author-email: Nam Nam <nampvh4436@gmail.com>
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
12
+ Requires-Python: >=3.9
13
+ Requires-Dist: numpy>=1.20.0
14
+ Requires-Dist: scikit-learn>=1.0.0
15
+ Requires-Dist: scipy>=1.7.0
16
+ Requires-Dist: tqdm>=4.60.0
17
+ Provides-Extra: cuda
18
+ Requires-Dist: cupy-cuda12x>=12.0.0; extra == 'cuda'
19
+ Provides-Extra: dev
20
+ Requires-Dist: black>=22.0.0; extra == 'dev'
21
+ Requires-Dist: flake8>=4.0.0; extra == 'dev'
22
+ Requires-Dist: isort>=5.10.0; extra == 'dev'
23
+ Requires-Dist: matplotlib>=3.5.0; extra == 'dev'
24
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
25
+ Description-Content-Type: text/markdown
26
+
27
+ # Bayesian Sparse GMM
28
+
29
+ Bayesian Sparse Gaussian Mixture Model (GMM) implementation in Python.
30
+
31
+ ## Installation
32
+
33
+ To install the latest release:
34
+
35
+ ```bash
36
+ pip install bayesian-sparse-gmm
37
+ ```
38
+
39
+ Or for development (editable mode):
40
+
41
+ ```bash
42
+ git clone https://github.com/Coalyx/bayesian-sparse-gmm.git
43
+ cd bayesian-sparse-gmm
44
+ pip install -e .
45
+ ```
46
+
47
+ ## Quick Start
48
+
49
+ ```python
50
+ import numpy as np
51
+ from sklearn.datasets import make_blobs
52
+ from sklearn.preprocessing import StandardScaler
53
+ from bayesian_sparse_gmm import BayesianSparseGMM
54
+
55
+ # Append noise dimensions to true clusters to verify that the model successfully performs feature selection.
56
+ rng = np.random.default_rng(42)
57
+ X_clean, _ = make_blobs(n_samples=200, centers=3, n_features=2, cluster_std=0.5, random_state=42)
58
+ X_noise = rng.normal(loc=0.0, scale=1.0, size=(200, 8))
59
+ X = np.hstack([X_clean, X_noise])
60
+
61
+ # Standardize features to satisfy the zero-mean assumptions in the prior structure.
62
+ X = StandardScaler().fit_transform(X)
63
+
64
+ model = BayesianSparseGMM(
65
+ K_max=5,
66
+ n_iter=300,
67
+ burn_in=100,
68
+ lambda_0=10.0,
69
+ lambda_1=0.05,
70
+ random_state=42,
71
+ verbose=0
72
+ )
73
+ model.fit(X)
74
+
75
+ print(f"Number of active clusters: {model.n_clusters_}")
76
+ print(f"Selected informative features: {model.selected_features_}")
77
+ print(f"Feature inclusion probabilities: {model.feature_probabilities_.round(3)}")
78
+
79
+ labels = model.predict(X)
80
+ ```
81
+
82
+ ## GPU / CUDA Acceleration
83
+
84
+ The model supports three backends, selected via the `backend` parameter:
85
+
86
+ | Backend | Value | Description |
87
+ |---------|-------|-------------|
88
+ | NumPy | `"numpy"` | Pure NumPy — always available, no extras needed |
89
+ | Numba CPU | `"numba"` | Parallel CPU via Numba JIT (**default**) |
90
+ | CUDA GPU | `"cuda"` | GPU via CuPy or Numba CUDA |
91
+ | Auto | `"auto"` | Numba CPU if available, else NumPy |
92
+
93
+ ### Install GPU support
94
+
95
+ ```bash
96
+ # CuPy (recommended — more flexible with driver versions)
97
+ pip install "bayesian-sparse-gmm[cuda]"
98
+ # or install directly for your CUDA version, e.g.:
99
+ pip install cupy-cuda12x # CUDA 12.x
100
+ pip install cupy-cuda11x # CUDA 11.x
101
+ ```
102
+
103
+ ### Run with GPU (Python API)
104
+
105
+ ```python
106
+ model = BayesianSparseGMM(
107
+ K_max=10,
108
+ n_iter=500,
109
+ backend="cuda", # GPU via CuPy → Numba CUDA → NumPy fallback
110
+ random_state=42,
111
+ )
112
+ model.fit(X)
113
+ ```
114
+
115
+
116
+ > [!NOTE]
117
+ > **Graceful fallback.** When `backend="cuda"` is requested, the library
118
+ > probes available backends in order: CuPy → Numba CUDA → NumPy. If a GPU
119
+ > backend is unavailable or incompatible, it falls back automatically and
120
+ > emits a `UserWarning` explaining why.
121
+
122
+ > [!WARNING]
123
+ > **Numba CUDA / PTX version mismatch.** Numba bundles its own CUDA
124
+ > toolkit. If the PTX version Numba generates is newer than what the
125
+ > installed NVIDIA driver supports (e.g., `Unsupported .version 8.7;
126
+ > current version is '8.2'`), Numba CUDA will be disabled automatically.
127
+ > Solutions:
128
+ > - **Preferred:** Install CuPy (`pip install cupy-cuda12x`) — it ships
129
+ > its own CUDA runtime and handles driver compatibility independently.
130
+ > - **Alternative:** Update the NVIDIA driver (≥ 545 for CUDA 12.3+).
131
+ > - **Alternative:** Pin Numba to a version matching your driver's CUDA
132
+ > support level.
133
+
134
+ ---
135
+
136
+ ## Development and Testing
137
+
138
+ Install development dependencies:
139
+
140
+ ```bash
141
+ pip install -e ".[dev]"
142
+ ```
143
+
144
+ Run tests using `pytest`:
145
+
146
+ ```bash
147
+ pytest
148
+ ```
149
+
150
+ ## Algorithm Overview
151
+
152
+ Bayesian Sparse Gaussian Mixture Model (BSGMM) is a robust clustering algorithm designed specifically for high-dimensional data where the number of features significantly exceeds the number of samples ($p \gg n$). It integrates a Spike-and-Slab LASSO prior to perform simultaneous clustering and feature selection.
153
+
154
+ ### Suitable Use Cases
155
+
156
+ 1. **High-Dimensional Clustering ($p \gg n$)**: When dealing with datasets where traditional clustering algorithms (like K-Means or standard GMM) fail due to the "curse of dimensionality". Examples include bioinformatics (e.g., single-cell RNA-seq, genomics), text mining (high-dimensional TF-IDF matrices), and high-resolution images.
157
+ 2. **Automatic Feature Selection (Interpretability)**: When the goal is not only to cluster the samples but also to identify which specific features (biomarkers, keywords, pixels) drive the cluster assignments. The model automatically shrinks noisy features to exactly zero.
158
+ 3. **Unknown Number of Clusters**: When the true number of clusters is unknown. BSGMM can dynamically infer the optimal number of clusters from the data (bounded by `K_max`).
159
+ 4. **Weak Signals in Noisy Backgrounds**: When the discriminative signal is weak and dispersed among thousands of irrelevant features, the model's sparsity mechanism is highly effective at pooling signals.
160
+
161
+ ## Hyperparameters
162
+
163
+ Understanding the key hyperparameters is crucial for fine-tuning the model's sparsity and clustering behavior:
164
+
165
+ | Parameter | Type | Default | Description |
166
+ |-----------|------|---------|-------------|
167
+ | `K_max` | `int` | `15` | The maximum possible number of clusters. The algorithm will automatically find the active number of clusters $K \le K_{max}$. Should be set safely higher than the expected number of true clusters. |
168
+ | `lambda_0` | `float` | `1000.0` | **Spike rate** of the Spike-and-Slab LASSO prior. A larger value aggressively forces non-informative (noise) features closer to zero. Must satisfy `lambda_0 >> lambda_1`. |
169
+ | `lambda_1` | `float` | `0.1` | **Slab rate**. A smaller value allows informative features to deviate freely from zero to capture the cluster structure. |
170
+ | `alpha` | `float` | `1.0` | Dirichlet concentration parameter for the cluster weight prior. Controls the prior belief over the distribution of cluster sizes. |
171
+ | `theta` | `float` | `0.1` | Prior probability of a feature being included in the active set (the slab component). Smaller values induce stronger sparsity (fewer features selected). |
172
+ | `burn_in` | `int` | `500` | Number of initial MCMC iterations discarded to allow the Markov chain to converge to the stationary distribution. |
173
+ | `n_iter` | `int` | `1000` | Total number of MCMC iterations. The number of samples used for posterior inference is `n_iter - burn_in`. |
174
+
175
+ *Tip: For extremely high-dimensional datasets with heavy noise, tuning `lambda_0` to be larger and `theta` to be smaller will encourage more aggressive feature selection.*
176
+
177
+ ## Reference
178
+
179
+ ```bib
180
+ @article{JMLR:v26:23-0142,
181
+ author = {Dapeng Yao and Fangzheng Xie and Yanxun Xu},
182
+ title = {Bayesian Sparse Gaussian Mixture Model for Clustering in High Dimensions},
183
+ journal = {Journal of Machine Learning Research},
184
+ year = {2025},
185
+ volume = {26},
186
+ number = {21},
187
+ pages = {1--50},
188
+ url = {http://jmlr.org/papers/v26/23-0142.html}
189
+ }
190
+ ```
@@ -0,0 +1,164 @@
1
+ # Bayesian Sparse GMM
2
+
3
+ Bayesian Sparse Gaussian Mixture Model (GMM) implementation in Python.
4
+
5
+ ## Installation
6
+
7
+ To install the latest release:
8
+
9
+ ```bash
10
+ pip install bayesian-sparse-gmm
11
+ ```
12
+
13
+ Or for development (editable mode):
14
+
15
+ ```bash
16
+ git clone https://github.com/Coalyx/bayesian-sparse-gmm.git
17
+ cd bayesian-sparse-gmm
18
+ pip install -e .
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ```python
24
+ import numpy as np
25
+ from sklearn.datasets import make_blobs
26
+ from sklearn.preprocessing import StandardScaler
27
+ from bayesian_sparse_gmm import BayesianSparseGMM
28
+
29
+ # Append noise dimensions to true clusters to verify that the model successfully performs feature selection.
30
+ rng = np.random.default_rng(42)
31
+ X_clean, _ = make_blobs(n_samples=200, centers=3, n_features=2, cluster_std=0.5, random_state=42)
32
+ X_noise = rng.normal(loc=0.0, scale=1.0, size=(200, 8))
33
+ X = np.hstack([X_clean, X_noise])
34
+
35
+ # Standardize features to satisfy the zero-mean assumptions in the prior structure.
36
+ X = StandardScaler().fit_transform(X)
37
+
38
+ model = BayesianSparseGMM(
39
+ K_max=5,
40
+ n_iter=300,
41
+ burn_in=100,
42
+ lambda_0=10.0,
43
+ lambda_1=0.05,
44
+ random_state=42,
45
+ verbose=0
46
+ )
47
+ model.fit(X)
48
+
49
+ print(f"Number of active clusters: {model.n_clusters_}")
50
+ print(f"Selected informative features: {model.selected_features_}")
51
+ print(f"Feature inclusion probabilities: {model.feature_probabilities_.round(3)}")
52
+
53
+ labels = model.predict(X)
54
+ ```
55
+
56
+ ## GPU / CUDA Acceleration
57
+
58
+ The model supports three backends, selected via the `backend` parameter:
59
+
60
+ | Backend | Value | Description |
61
+ |---------|-------|-------------|
62
+ | NumPy | `"numpy"` | Pure NumPy — always available, no extras needed |
63
+ | Numba CPU | `"numba"` | Parallel CPU via Numba JIT (**default**) |
64
+ | CUDA GPU | `"cuda"` | GPU via CuPy or Numba CUDA |
65
+ | Auto | `"auto"` | Numba CPU if available, else NumPy |
66
+
67
+ ### Install GPU support
68
+
69
+ ```bash
70
+ # CuPy (recommended — more flexible with driver versions)
71
+ pip install "bayesian-sparse-gmm[cuda]"
72
+ # or install directly for your CUDA version, e.g.:
73
+ pip install cupy-cuda12x # CUDA 12.x
74
+ pip install cupy-cuda11x # CUDA 11.x
75
+ ```
76
+
77
+ ### Run with GPU (Python API)
78
+
79
+ ```python
80
+ model = BayesianSparseGMM(
81
+ K_max=10,
82
+ n_iter=500,
83
+ backend="cuda", # GPU via CuPy → Numba CUDA → NumPy fallback
84
+ random_state=42,
85
+ )
86
+ model.fit(X)
87
+ ```
88
+
89
+
90
+ > [!NOTE]
91
+ > **Graceful fallback.** When `backend="cuda"` is requested, the library
92
+ > probes available backends in order: CuPy → Numba CUDA → NumPy. If a GPU
93
+ > backend is unavailable or incompatible, it falls back automatically and
94
+ > emits a `UserWarning` explaining why.
95
+
96
+ > [!WARNING]
97
+ > **Numba CUDA / PTX version mismatch.** Numba bundles its own CUDA
98
+ > toolkit. If the PTX version Numba generates is newer than what the
99
+ > installed NVIDIA driver supports (e.g., `Unsupported .version 8.7;
100
+ > current version is '8.2'`), Numba CUDA will be disabled automatically.
101
+ > Solutions:
102
+ > - **Preferred:** Install CuPy (`pip install cupy-cuda12x`) — it ships
103
+ > its own CUDA runtime and handles driver compatibility independently.
104
+ > - **Alternative:** Update the NVIDIA driver (≥ 545 for CUDA 12.3+).
105
+ > - **Alternative:** Pin Numba to a version matching your driver's CUDA
106
+ > support level.
107
+
108
+ ---
109
+
110
+ ## Development and Testing
111
+
112
+ Install development dependencies:
113
+
114
+ ```bash
115
+ pip install -e ".[dev]"
116
+ ```
117
+
118
+ Run tests using `pytest`:
119
+
120
+ ```bash
121
+ pytest
122
+ ```
123
+
124
+ ## Algorithm Overview
125
+
126
+ Bayesian Sparse Gaussian Mixture Model (BSGMM) is a robust clustering algorithm designed specifically for high-dimensional data where the number of features significantly exceeds the number of samples ($p \gg n$). It integrates a Spike-and-Slab LASSO prior to perform simultaneous clustering and feature selection.
127
+
128
+ ### Suitable Use Cases
129
+
130
+ 1. **High-Dimensional Clustering ($p \gg n$)**: When dealing with datasets where traditional clustering algorithms (like K-Means or standard GMM) fail due to the "curse of dimensionality". Examples include bioinformatics (e.g., single-cell RNA-seq, genomics), text mining (high-dimensional TF-IDF matrices), and high-resolution images.
131
+ 2. **Automatic Feature Selection (Interpretability)**: When the goal is not only to cluster the samples but also to identify which specific features (biomarkers, keywords, pixels) drive the cluster assignments. The model automatically shrinks noisy features to exactly zero.
132
+ 3. **Unknown Number of Clusters**: When the true number of clusters is unknown. BSGMM can dynamically infer the optimal number of clusters from the data (bounded by `K_max`).
133
+ 4. **Weak Signals in Noisy Backgrounds**: When the discriminative signal is weak and dispersed among thousands of irrelevant features, the model's sparsity mechanism is highly effective at pooling signals.
134
+
135
+ ## Hyperparameters
136
+
137
+ Understanding the key hyperparameters is crucial for fine-tuning the model's sparsity and clustering behavior:
138
+
139
+ | Parameter | Type | Default | Description |
140
+ |-----------|------|---------|-------------|
141
+ | `K_max` | `int` | `15` | The maximum possible number of clusters. The algorithm will automatically find the active number of clusters $K \le K_{max}$. Should be set safely higher than the expected number of true clusters. |
142
+ | `lambda_0` | `float` | `1000.0` | **Spike rate** of the Spike-and-Slab LASSO prior. A larger value aggressively forces non-informative (noise) features closer to zero. Must satisfy `lambda_0 >> lambda_1`. |
143
+ | `lambda_1` | `float` | `0.1` | **Slab rate**. A smaller value allows informative features to deviate freely from zero to capture the cluster structure. |
144
+ | `alpha` | `float` | `1.0` | Dirichlet concentration parameter for the cluster weight prior. Controls the prior belief over the distribution of cluster sizes. |
145
+ | `theta` | `float` | `0.1` | Prior probability of a feature being included in the active set (the slab component). Smaller values induce stronger sparsity (fewer features selected). |
146
+ | `burn_in` | `int` | `500` | Number of initial MCMC iterations discarded to allow the Markov chain to converge to the stationary distribution. |
147
+ | `n_iter` | `int` | `1000` | Total number of MCMC iterations. The number of samples used for posterior inference is `n_iter - burn_in`. |
148
+
149
+ *Tip: For extremely high-dimensional datasets with heavy noise, tuning `lambda_0` to be larger and `theta` to be smaller will encourage more aggressive feature selection.*
150
+
151
+ ## Reference
152
+
153
+ ```bib
154
+ @article{JMLR:v26:23-0142,
155
+ author = {Dapeng Yao and Fangzheng Xie and Yanxun Xu},
156
+ title = {Bayesian Sparse Gaussian Mixture Model for Clustering in High Dimensions},
157
+ journal = {Journal of Machine Learning Research},
158
+ year = {2025},
159
+ volume = {26},
160
+ number = {21},
161
+ pages = {1--50},
162
+ url = {http://jmlr.org/papers/v26/23-0142.html}
163
+ }
164
+ ```