vector-quantize-pytorch 1.24.2__tar.gz → 1.25.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.
Files changed (33) hide show
  1. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/PKG-INFO +14 -1
  2. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/README.md +13 -0
  3. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/pyproject.toml +1 -1
  4. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/vector_quantize_pytorch/__init__.py +2 -0
  5. vector_quantize_pytorch-1.25.1/vector_quantize_pytorch/binary_mapper.py +161 -0
  6. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/.github/workflows/build.yml +0 -0
  7. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/.github/workflows/python-publish.yml +0 -0
  8. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/.github/workflows/test.yml +0 -0
  9. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/.gitignore +0 -0
  10. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/LICENSE +0 -0
  11. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/examples/autoencoder.py +0 -0
  12. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/examples/autoencoder_fsq.py +0 -0
  13. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/examples/autoencoder_lfq.py +0 -0
  14. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/examples/autoencoder_sim_vq.py +0 -0
  15. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/images/fsq.png +0 -0
  16. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/images/lfq.png +0 -0
  17. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/images/simvq.png +0 -0
  18. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/images/vq.png +0 -0
  19. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/ruff.toml +0 -0
  20. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/tests/test_latent_quantization.py +0 -0
  21. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/tests/test_lfq.py +0 -0
  22. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/tests/test_readme.py +0 -0
  23. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/vector_quantize_pytorch/finite_scalar_quantization.py +0 -0
  24. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/vector_quantize_pytorch/latent_quantization.py +0 -0
  25. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/vector_quantize_pytorch/lookup_free_quantization.py +0 -0
  26. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/vector_quantize_pytorch/random_projection_quantizer.py +0 -0
  27. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/vector_quantize_pytorch/residual_fsq.py +0 -0
  28. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/vector_quantize_pytorch/residual_lfq.py +0 -0
  29. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/vector_quantize_pytorch/residual_sim_vq.py +0 -0
  30. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/vector_quantize_pytorch/residual_vq.py +0 -0
  31. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/vector_quantize_pytorch/sim_vq.py +0 -0
  32. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/vector_quantize_pytorch/utils.py +0 -0
  33. {vector_quantize_pytorch-1.24.2 → vector_quantize_pytorch-1.25.1}/vector_quantize_pytorch/vector_quantize_pytorch.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vector-quantize-pytorch
3
- Version: 1.24.2
3
+ Version: 1.25.1
4
4
  Summary: Vector Quantization - Pytorch
5
5
  Project-URL: Homepage, https://pypi.org/project/vector-quantize-pytorch/
6
6
  Project-URL: Repository, https://github.com/lucidrains/vector-quantizer-pytorch
@@ -835,3 +835,16 @@ assert loss.item() >= 0
835
835
  url = {https://arxiv.org/abs/2509.26469},
836
836
  }
837
837
  ```
838
+
839
+ ```bibtex
840
+ @misc{fleuret2025freetransformer,
841
+ title = {The Free Transformer},
842
+ author = {François Fleuret},
843
+ year = {2025},
844
+ eprint = {2510.17558},
845
+ archivePrefix = {arXiv},
846
+ primaryClass = {cs.LG},
847
+ url = {https://arxiv.org/abs/2510.17558},
848
+ }
849
+ ```
850
+
@@ -791,3 +791,16 @@ assert loss.item() >= 0
791
791
  url = {https://arxiv.org/abs/2509.26469},
792
792
  }
793
793
  ```
794
+
795
+ ```bibtex
796
+ @misc{fleuret2025freetransformer,
797
+ title = {The Free Transformer},
798
+ author = {François Fleuret},
799
+ year = {2025},
800
+ eprint = {2510.17558},
801
+ archivePrefix = {arXiv},
802
+ primaryClass = {cs.LG},
803
+ url = {https://arxiv.org/abs/2510.17558},
804
+ }
805
+ ```
806
+
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "vector-quantize-pytorch"
3
- version = "1.24.2"
3
+ version = "1.25.1"
4
4
  description = "Vector Quantization - Pytorch"
5
5
  authors = [
6
6
  { name = "Phil Wang", email = "lucidrains@gmail.com" }
@@ -10,4 +10,6 @@ from vector_quantize_pytorch.latent_quantization import LatentQuantize
10
10
  from vector_quantize_pytorch.sim_vq import SimVQ
11
11
  from vector_quantize_pytorch.residual_sim_vq import ResidualSimVQ
12
12
 
13
+ from vector_quantize_pytorch.binary_mapper import BinaryMapper
14
+
13
15
  from vector_quantize_pytorch.utils import Sequential
@@ -0,0 +1,161 @@
1
+ from __future__ import annotations
2
+
3
+ # proposed in https://arxiv.org/abs/2510.17558 as a more stable alternative to VAE by François Fleuret
4
+
5
+ from math import log
6
+
7
+ import torch
8
+ from torch import nn, tensor, arange
9
+ import torch.nn.functional as F
10
+ from torch.nn import Module
11
+
12
+ from einops import einsum, pack, unpack
13
+
14
+ # constants
15
+
16
+ NAT = log(2)
17
+
18
+ # helper functions
19
+
20
+ def exists(v):
21
+ return v is not None
22
+
23
+ def default(v, d):
24
+ return v if exists(v) else d
25
+
26
+ # tensor helpers
27
+
28
+ def binary_entropy(logits):
29
+ prob = logits.sigmoid()
30
+ not_prob = 1. - prob
31
+ return -(prob * F.logsigmoid(logits) + not_prob * F.logsigmoid(-logits)).sum(dim = -1)
32
+
33
+ def pack_with_inverse(t, pattern):
34
+ packed, ps = pack([t], pattern)
35
+
36
+ def inverse(out, inv_pattern = None):
37
+ inv_pattern = default(inv_pattern, pattern)
38
+ unpacked, = unpack(out, ps, inv_pattern)
39
+ return unpacked
40
+
41
+ return packed, inverse
42
+
43
+ # binary mapper
44
+
45
+ class BinaryMapper(Module):
46
+ def __init__(
47
+ self,
48
+ bits = 1,
49
+ kl_loss_threshold = NAT, # 1 bit
50
+ deterministic_on_eval = False
51
+ ):
52
+ super().__init__()
53
+
54
+ self.bits = bits
55
+ self.num_codes = 2 ** bits
56
+
57
+ power_two = 2 ** arange(bits)
58
+ codes = (arange(self.num_codes)[:, None].bitwise_and(power_two) != 0).byte().bool()
59
+
60
+ self.register_buffer('power_two', power_two, persistent = False)
61
+ self.register_buffer('codes', codes, persistent = False)
62
+
63
+ # aux loss
64
+
65
+ self.kl_loss_threshold = kl_loss_threshold
66
+ self.register_buffer('zero', tensor(0.), persistent = False)
67
+
68
+ # eval behavior
69
+
70
+ self.deterministic_on_eval = deterministic_on_eval
71
+
72
+ def forward(
73
+ self,
74
+ logits,
75
+ temperature = 1.,
76
+ straight_through = None,
77
+ calc_aux_loss = None,
78
+ deterministic = None,
79
+ return_indices = False,
80
+ ):
81
+ deterministic = default(deterministic, self.deterministic_on_eval and not self.training)
82
+
83
+ straight_through = default(straight_through, self.training)
84
+ calc_aux_loss = default(calc_aux_loss, self.training)
85
+
86
+ assert logits.shape[-1] == self.bits, f'logits must have a last dimension of {self.bits}'
87
+
88
+ # allow for any number of leading dimensions
89
+
90
+ logits, inverse_pack_lead_dims = pack_with_inverse(logits, '* bits')
91
+
92
+ # temperature and prob for sampling
93
+
94
+ prob_for_sample = (logits / temperature).sigmoid()
95
+
96
+ # sampling
97
+
98
+ compare_target = torch.rand_like(logits) if not deterministic else 0.5
99
+
100
+ sampled_bits = (compare_target <= prob_for_sample).long()
101
+
102
+ indices = (self.power_two * sampled_bits).sum(dim = -1)
103
+
104
+ one_hot = F.one_hot(indices, self.num_codes).float()
105
+
106
+ # maybe calculate aux loss
107
+
108
+ aux_kl_loss = self.zero
109
+
110
+ if calc_aux_loss:
111
+ # calculate negative entropy
112
+
113
+ kl_div = self.bits * NAT - binary_entropy(logits)
114
+ aux_kl_loss = F.relu(kl_div - self.kl_loss_threshold).mean()
115
+
116
+ # maybe straight through
117
+
118
+ if straight_through:
119
+ # get the soft G for the gradients and do a straight through
120
+
121
+ soft_G = (
122
+ einsum(F.logsigmoid(logits), self.codes.float(), '... bits, codes bits -> ... codes') +
123
+ einsum(F.logsigmoid(-logits), (~self.codes).float(), '... bits, codes bits -> ... codes')
124
+ ).exp()
125
+
126
+ # straight through
127
+
128
+ one_hot = one_hot + soft_G - soft_G.detach()
129
+
130
+ # inverse pack
131
+
132
+ one_hot = inverse_pack_lead_dims(one_hot)
133
+ indices = inverse_pack_lead_dims(indices, '*')
134
+
135
+ # returning
136
+
137
+ if not return_indices:
138
+ return one_hot, aux_kl_loss
139
+
140
+ # also allow for returning indices, even though it can be derived from sparse output with an argmax
141
+
142
+ return one_hot, indices, aux_kl_loss
143
+
144
+ # allow for quick copy paste
145
+
146
+ if __name__ == '__main__':
147
+
148
+ binary_mapper = BinaryMapper(bits = 8)
149
+
150
+ logits = torch.randn(3, 4, 8)
151
+
152
+ sparse_one_hot, indices, aux_loss = binary_mapper(logits, return_indices = True)
153
+
154
+ assert sparse_one_hot.shape == (3, 4, 2 ** 8)
155
+ assert indices.shape == (3, 4)
156
+ assert aux_loss.numel() == 1
157
+
158
+ binary_mapper.eval()
159
+ sparse_one_hot1, _ = binary_mapper(logits, deterministic = True)
160
+ sparse_one_hot2, _ = binary_mapper(logits, deterministic = True)
161
+ assert torch.allclose(sparse_one_hot1, sparse_one_hot2)