gmml 2026.9.dev0__tar.gz → 2026.9.dev1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gmml
3
- Version: 2026.9.dev0
3
+ Version: 2026.9.dev1
4
4
  Summary: Pytorch implementation of a Gaussian mixture modeling layer
5
5
  Author: algmarques
6
6
  Maintainer: algmarques
@@ -18,22 +18,22 @@ This package contains a Pytorch implementation of a
18
18
  **Gaussian mixture modeling layer**.
19
19
 
20
20
  A **Gaussian mixture modeling layer** maps $d$-dimensional input vectors
21
- onto categorical probability distributions. Such distributions measures the
21
+ onto categorical probability distributions. Such distributions measure the
22
22
  likelihood of the input vectors belonging to each component of a Gaussian
23
23
  mixture model. The underlying Gaussian mixture distribution is parametrized
24
- by a collection of: mean-vectors (`mean`), Cholesky factors (`*_fct`),
25
- and a logit vector (`norm_logit`). The logit vector defines the relative
24
+ by a collection of: mean-vectors (`means`), Cholesky factors (`*_factors`),
25
+ and a logits vector (`norm_logits`). The logits vector defines the relative
26
26
  importance of each Gaussian component within the mixture, and the collection
27
- of Cholesky factors (`*_fct`) - each resulting from the Cholesky decomposition
28
- of the precision matrices of the Gaussian components - defines the shape of
29
- the Gaussians. Under such parametrization, the computational complexity of the
30
- functional form of the forward and backward calls to this layer is reduced,
31
- leading to more efficient evaluations. The forward and backward calls of
32
- Gaussian mixture modeling layer parameterized by a general Cholesky factor
33
- (`full_fct`) have a computational complexity of $O(n \times d ^ 2)$, where $n$
34
- is the number of components of the underlying Gaussian mixture distribution.
35
- Moreover, its functional form is differentiable in all of its inputs and
36
- parameters, hence it is autograd compatible.
27
+ of Cholesky factors (`*_factors`) - each resulting from the Cholesky
28
+ decomposition of the precision matrices of the Gaussian components - defines
29
+ the shape of the Gaussians. Under such parametrization, the computational
30
+ complexity of the functional form of the forward and backward calls to this
31
+ layer is reduced, leading to more efficient evaluations. The forward and
32
+ backward calls of Gaussian mixture modeling layer parametrized by a general
33
+ Cholesky factor (`full_factors`) have a computational complexity of
34
+ $O(n \times d ^ 2)$, where $n$ is the number of components of the underlying
35
+ Gaussian mixture distribution. Moreover, its functional form is differentiable
36
+ in all of its inputs and parameters, hence it is autograd compatible.
37
37
 
38
38
  A **Gaussian mixture modeling layer** can be instantiated in the following way:
39
39
 
@@ -49,7 +49,7 @@ batch_size = 4
49
49
  gmml = GMMLayer(n_components, dim)
50
50
 
51
51
  inpt = rand(batch_size, dim)
52
- prob = gmml(inpt)
52
+ probs = gmml(inpt)
53
53
  ```
54
54
 
55
55
  The **Gaussian mixture modeling layer** fits the input data by maximizing the
@@ -4,22 +4,22 @@ This package contains a Pytorch implementation of a
4
4
  **Gaussian mixture modeling layer**.
5
5
 
6
6
  A **Gaussian mixture modeling layer** maps $d$-dimensional input vectors
7
- onto categorical probability distributions. Such distributions measures the
7
+ onto categorical probability distributions. Such distributions measure the
8
8
  likelihood of the input vectors belonging to each component of a Gaussian
9
9
  mixture model. The underlying Gaussian mixture distribution is parametrized
10
- by a collection of: mean-vectors (`mean`), Cholesky factors (`*_fct`),
11
- and a logit vector (`norm_logit`). The logit vector defines the relative
10
+ by a collection of: mean-vectors (`means`), Cholesky factors (`*_factors`),
11
+ and a logits vector (`norm_logits`). The logits vector defines the relative
12
12
  importance of each Gaussian component within the mixture, and the collection
13
- of Cholesky factors (`*_fct`) - each resulting from the Cholesky decomposition
14
- of the precision matrices of the Gaussian components - defines the shape of
15
- the Gaussians. Under such parametrization, the computational complexity of the
16
- functional form of the forward and backward calls to this layer is reduced,
17
- leading to more efficient evaluations. The forward and backward calls of
18
- Gaussian mixture modeling layer parameterized by a general Cholesky factor
19
- (`full_fct`) have a computational complexity of $O(n \times d ^ 2)$, where $n$
20
- is the number of components of the underlying Gaussian mixture distribution.
21
- Moreover, its functional form is differentiable in all of its inputs and
22
- parameters, hence it is autograd compatible.
13
+ of Cholesky factors (`*_factors`) - each resulting from the Cholesky
14
+ decomposition of the precision matrices of the Gaussian components - defines
15
+ the shape of the Gaussians. Under such parametrization, the computational
16
+ complexity of the functional form of the forward and backward calls to this
17
+ layer is reduced, leading to more efficient evaluations. The forward and
18
+ backward calls of Gaussian mixture modeling layer parametrized by a general
19
+ Cholesky factor (`full_factors`) have a computational complexity of
20
+ $O(n \times d ^ 2)$, where $n$ is the number of components of the underlying
21
+ Gaussian mixture distribution. Moreover, its functional form is differentiable
22
+ in all of its inputs and parameters, hence it is autograd compatible.
23
23
 
24
24
  A **Gaussian mixture modeling layer** can be instantiated in the following way:
25
25
 
@@ -35,7 +35,7 @@ batch_size = 4
35
35
  gmml = GMMLayer(n_components, dim)
36
36
 
37
37
  inpt = rand(batch_size, dim)
38
- prob = gmml(inpt)
38
+ probs = gmml(inpt)
39
39
  ```
40
40
 
41
41
  The **Gaussian mixture modeling layer** fits the input data by maximizing the
@@ -0,0 +1,19 @@
1
+ """
2
+ Public package exports for gmml.
3
+ """
4
+
5
+ __all__ = [
6
+ "GMMLayer", "DiagGMMLayer", "IsoGMMLayer", "SharedIsoGMMLayer",
7
+ "get_kl_divs", "get_log_joint_probs", "get_samples",
8
+ "get_diag_kl_divs", "get_diag_log_joint_probs", "get_diag_samples",
9
+ "get_iso_kl_divs", "get_iso_log_joint_probs", "get_iso_samples",
10
+ ]
11
+
12
+
13
+ from gmml.functional import get_kl_divs, get_log_joint_probs, get_samples
14
+ from gmml.functional import get_diag_kl_divs, get_diag_log_joint_probs, \
15
+ get_diag_samples
16
+ from gmml.functional import get_iso_kl_divs, get_iso_log_joint_probs, \
17
+ get_iso_samples
18
+
19
+ from gmml.layer import GMMLayer, DiagGMMLayer, IsoGMMLayer, SharedIsoGMMLayer
@@ -0,0 +1,415 @@
1
+ """
2
+ Codebook abstractions for Gaussian mixture models.
3
+ """
4
+
5
+ from typing import Any, Optional, Self
6
+
7
+ import abc
8
+
9
+
10
+ import torch
11
+ import torch.nn as nn
12
+ import torch.nn.functional as F
13
+
14
+ from torch import Tensor
15
+
16
+
17
+ import gmml.utils as utils
18
+
19
+
20
+ class CodeBook(nn.Module, abc.ABC):
21
+ """
22
+ Base class for codebooks with learned component vectors.
23
+ Codevectors are represented by the 'means' parameter.
24
+ """
25
+
26
+ def _init_means(
27
+ self: Self,
28
+ size: int,
29
+ dim: int,
30
+ device: Optional[torch.device] = None,
31
+ dtype: Optional[torch.dtype] = None
32
+ ) -> nn.Parameter:
33
+ """
34
+ Initializes the means parameter according to a standard multivariate
35
+ normal distribution.
36
+
37
+ Args:
38
+ size: Number of codebook entries.
39
+ dim: Dimensionality of each code vector.
40
+ device: Optional device on which to allocate the parameter.
41
+ dtype: Optional dtype used to allocate the parameter.
42
+
43
+ Returns:
44
+ Parameter: The initialized means parameter.
45
+ """
46
+
47
+ return nn.Parameter(
48
+ utils.sample_standard_multivariate_normal(
49
+ size, dim, device=device, dtype=dtype
50
+ ),
51
+ requires_grad=True
52
+ )
53
+
54
+ def __init__(
55
+ self: Self,
56
+ size: int,
57
+ dim: int,
58
+ *args: Any,
59
+ device: Optional[torch.device] = None,
60
+ dtype: Optional[torch.dtype] = None,
61
+ **kwargs: Any
62
+ ) -> None:
63
+ """
64
+ Initializes the codebook means.
65
+
66
+ Args:
67
+ size: Number of codebook entries.
68
+ dim: Dimensionality of each code vector.
69
+ *args: Positional arguments forwarded to the base module.
70
+ device: Optional device on which to allocate parameters.
71
+ dtype: Optional dtype used to allocate parameters.
72
+ **kwargs: Keyword arguments forwarded to the base module.
73
+
74
+ Returns:
75
+ None: This constructor returns after initializing the module.
76
+ """
77
+
78
+ super().__init__(*args, **kwargs)
79
+
80
+ self.size = size
81
+ self.dim = dim
82
+
83
+ self.means = self._init_means(
84
+ size, dim, device=device, dtype=dtype
85
+ )
86
+
87
+ def reset_parameters(self: Self) -> None:
88
+ """
89
+ Reinitializes the means parameter in place.
90
+
91
+ Args:
92
+ None.
93
+
94
+ Returns:
95
+ None: This method returns after reinitializing the parameter.
96
+ """
97
+
98
+ self.means.data.copy_(
99
+ self._init_means(
100
+ self.size,
101
+ self.dim,
102
+ device=self.means.device,
103
+ dtype=self.means.dtype
104
+ )
105
+ )
106
+
107
+ def extra_repr(self: Self) -> str:
108
+ """
109
+ Returns the extra representation string for this codebook.
110
+
111
+ Args:
112
+ None.
113
+
114
+ Returns:
115
+ str: String describing the codebook's size and dimensionality.
116
+ """
117
+
118
+ return f"size={self.size}, dim={self.dim}"
119
+
120
+ @abc.abstractmethod
121
+ def forward(self: Self, inpt: torch.Tensor) -> torch.Tensor:
122
+ """
123
+ Abstract forward method.
124
+
125
+ Args:
126
+ inpt: Input tensor passed to the codebook.
127
+
128
+ Returns:
129
+ Tensor: Output tensor produced by the codebook.
130
+ """
131
+
132
+ raise NotImplementedError()
133
+
134
+
135
+ class WeightedCodeBook(CodeBook, abc.ABC):
136
+ """
137
+ Codebook base class with learnable component weights.
138
+ """
139
+
140
+ def _init_logits(
141
+ self: Self,
142
+ size: int,
143
+ equi_weighted: bool,
144
+ device: Optional[torch.device] = None,
145
+ dtype: Optional[torch.dtype] = None
146
+ ) -> nn.Parameter:
147
+ """
148
+ Initializes the logits parameter, fixed to zero when equi_weighted.
149
+
150
+ Args:
151
+ size: Number of codebook entries.
152
+ equi_weighted: Whether to keep all mixture weights equal.
153
+ device: Optional device on which to allocate the parameter.
154
+ dtype: Optional dtype used to allocate the parameter.
155
+
156
+ Returns:
157
+ Parameter: The initialized logits parameter.
158
+ """
159
+
160
+ return nn.Parameter(
161
+ torch.zeros(size, device=device, dtype=dtype),
162
+ requires_grad=not equi_weighted
163
+ )
164
+
165
+ def __init__(
166
+ self: Self,
167
+ size: int,
168
+ dim: int,
169
+ equi_weighted: bool = False,
170
+ *args: Any,
171
+ device: Optional[torch.device] = None,
172
+ dtype: Optional[torch.dtype] = None,
173
+ **kwargs: Any
174
+ ) -> None:
175
+ """
176
+ Initializes the codebook means and mixture logits.
177
+
178
+ Args:
179
+ size: Number of codebook entries.
180
+ dim: Dimensionality of each code vector.
181
+ equi_weighted: Whether to keep all mixture weights equal.
182
+ *args: Positional arguments forwarded to the base module.
183
+ device: Optional device on which to allocate parameters.
184
+ dtype: Optional dtype used to allocate parameters.
185
+ **kwargs: Keyword arguments forwarded to the base module.
186
+
187
+ Returns:
188
+ None: This constructor returns after initializing the module.
189
+ """
190
+
191
+ super().__init__(
192
+ size, dim, *args, device=device, dtype=dtype, **kwargs
193
+ )
194
+
195
+ self.equi_weighted = equi_weighted
196
+ self.logits = self._init_logits(
197
+ size, equi_weighted, device=device, dtype=dtype
198
+ )
199
+
200
+ def reset_parameters(self: Self) -> None:
201
+ """
202
+ Reinitializes the means and logits parameters in place.
203
+
204
+ Args:
205
+ None.
206
+
207
+ Returns:
208
+ None: This method returns after reinitializing the parameters.
209
+ """
210
+
211
+ super().reset_parameters()
212
+ self.logits.data.copy_(
213
+ self._init_logits(
214
+ self.size,
215
+ self.equi_weighted,
216
+ device=self.logits.device,
217
+ dtype=self.logits.dtype
218
+ )
219
+ )
220
+
221
+ @property
222
+ def norm_logits(self: Self) -> torch.Tensor:
223
+ """
224
+ Returns the normalized logit vector.
225
+
226
+ Args:
227
+ None.
228
+
229
+ Returns:
230
+ Tensor: Log-softmax-normalized logits.
231
+ """
232
+
233
+ return F.log_softmax(self.logits, dim=-1)
234
+
235
+ @property
236
+ def weights(self: Self) -> torch.Tensor:
237
+ """
238
+ Returns the weights vector.
239
+
240
+ Args:
241
+ None.
242
+
243
+ Returns:
244
+ Tensor: Softmax-normalized weights.
245
+ """
246
+
247
+ return F.softmax(self.logits, dim=-1)
248
+
249
+ def get_balance(self: Self) -> torch.Tensor:
250
+ """
251
+ Returns the balance between the entries of the codebook.
252
+ Higher values indicate more balanced components.
253
+
254
+ Args:
255
+ None.
256
+
257
+ Returns:
258
+ Tensor: Balance between the codebook entries.
259
+ """
260
+
261
+ return - (self.norm_logits.exp() * self.norm_logits).sum(-1)
262
+
263
+ def extra_repr(self: Self) -> str:
264
+ """
265
+ Returns the extra representation string for this codebook.
266
+
267
+ Args:
268
+ None.
269
+
270
+ Returns:
271
+ str: String describing the codebook's size, dimensionality, and
272
+ weighting mode.
273
+ """
274
+
275
+ return f"{super().extra_repr()}, equi_weighted={self.equi_weighted}"
276
+
277
+
278
+ class ProbCodeBook(CodeBook, abc.ABC):
279
+ """
280
+ Codebook base class that exposes conditional probabilities.
281
+ """
282
+
283
+ def forward(self: Self, inpt: Tensor) -> Tensor:
284
+ """
285
+ Returns the conditional probability distribution over components.
286
+
287
+ Args:
288
+ inpt: Input tensor passed to the probabilistic codebook.
289
+
290
+ Returns:
291
+ Tensor: Conditional probability distribution over components.
292
+ """
293
+
294
+ return self.get_cond_probs(inpt)
295
+
296
+ def get_cond_probs(self: Self, inpt: Tensor) -> Tensor:
297
+ """
298
+ Returns the conditional categorical probability distributions.
299
+
300
+ Args:
301
+ inpt: Input tensor passed to the probabilistic codebook.
302
+
303
+ Returns:
304
+ Tensor: Conditional categorical probability distributions.
305
+ """
306
+
307
+ return F.softmax(self.get_log_cond_probs(inpt), dim=-1)
308
+
309
+ def get_cond_entropies(self: Self, inpt: Tensor) -> Tensor:
310
+ """
311
+ Returns the entropy associated with the conditional categorical
312
+ probability distributions.
313
+
314
+ Args:
315
+ inpt: Input tensor passed to the probabilistic codebook.
316
+
317
+ Returns:
318
+ Tensor: Conditional entropy value for each input.
319
+ """
320
+
321
+ log_cond_probs = self.get_log_cond_probs(inpt)
322
+
323
+ return - (log_cond_probs.exp() * log_cond_probs).sum(-1)
324
+
325
+ @abc.abstractmethod
326
+ def get_log_cond_probs(self: Self, inpt: Tensor) -> Tensor:
327
+ """
328
+ Abstract method for returning the logarithm of the conditional
329
+ categorical probability distributions over components.
330
+
331
+ Args:
332
+ inpt: Input tensor passed to the probabilistic codebook.
333
+
334
+ Returns:
335
+ Tensor: Log-conditional probability distributions.
336
+ """
337
+
338
+ raise NotImplementedError()
339
+
340
+
341
+ class GaussianCodeBook(ProbCodeBook, abc.ABC):
342
+ """
343
+ Codebook base class specialized for Gaussian components.
344
+ """
345
+
346
+ def get_log_cond_probs(self: Self, inpt: Tensor) -> Tensor:
347
+ """
348
+ Returns the logarithm of the conditional categorical probability
349
+ distributions over components.
350
+
351
+ Args:
352
+ inpt: Input tensor passed to the Gaussian codebook.
353
+
354
+ Returns:
355
+ Tensor: Log-conditional probability distributions.
356
+ """
357
+
358
+ return F.log_softmax(self.get_log_joint_probs(inpt), dim=-1)
359
+
360
+ @property
361
+ def precisions(self: Self) -> Tensor:
362
+ """
363
+ Returns the precision matrices.
364
+
365
+ Args:
366
+ None.
367
+
368
+ Returns:
369
+ Tensor: Precision matrices of the Gaussian components.
370
+ """
371
+
372
+ return self.full_factors.mT @ self.full_factors
373
+
374
+ @property
375
+ @abc.abstractmethod
376
+ def full_factors(self: Self) -> Tensor:
377
+ """
378
+ Returns the Cholesky factors.
379
+
380
+ Args:
381
+ None.
382
+
383
+ Returns:
384
+ Tensor: Cholesky factors of the Gaussian components.
385
+ """
386
+
387
+ raise NotImplementedError()
388
+
389
+ def get_log_likelihoods(self: Self, inpt: Tensor) -> Tensor:
390
+ """
391
+ Returns the log-likelihoods.
392
+
393
+ Args:
394
+ inpt: Input tensor passed to the Gaussian codebook.
395
+
396
+ Returns:
397
+ Tensor: Log-likelihood values.
398
+ """
399
+
400
+ return torch.logsumexp(self.get_log_joint_probs(inpt), dim=-1)
401
+
402
+ @abc.abstractmethod
403
+ def get_log_joint_probs(self: Self, inpt: Tensor) -> Tensor:
404
+ """
405
+ Abstract method for returning the logarithm of the joint probability
406
+ distributions.
407
+
408
+ Args:
409
+ inpt: Input tensor passed to the Gaussian codebook.
410
+
411
+ Returns:
412
+ Tensor: Log joint probability distributions.
413
+ """
414
+
415
+ raise NotImplementedError()