vector-quantize-pytorch 1.23.4__tar.gz → 1.24.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.
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/PKG-INFO +13 -1
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/README.md +12 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/examples/autoencoder.py +3 -2
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/pyproject.toml +1 -1
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/tests/test_readme.py +22 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/vector_quantize_pytorch/vector_quantize_pytorch.py +43 -8
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/.github/workflows/build.yml +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/.github/workflows/python-publish.yml +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/.github/workflows/test.yml +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/.gitignore +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/LICENSE +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/examples/autoencoder_fsq.py +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/examples/autoencoder_lfq.py +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/examples/autoencoder_sim_vq.py +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/images/fsq.png +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/images/lfq.png +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/images/simvq.png +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/images/vq.png +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/ruff.toml +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/tests/test_latent_quantization.py +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/tests/test_lfq.py +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/vector_quantize_pytorch/__init__.py +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/vector_quantize_pytorch/finite_scalar_quantization.py +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/vector_quantize_pytorch/latent_quantization.py +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/vector_quantize_pytorch/lookup_free_quantization.py +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/vector_quantize_pytorch/random_projection_quantizer.py +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/vector_quantize_pytorch/residual_fsq.py +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/vector_quantize_pytorch/residual_lfq.py +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/vector_quantize_pytorch/residual_sim_vq.py +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/vector_quantize_pytorch/residual_vq.py +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/vector_quantize_pytorch/sim_vq.py +0 -0
- {vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/vector_quantize_pytorch/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vector-quantize-pytorch
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.24.0
|
|
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
|
|
@@ -823,3 +823,15 @@ assert loss.item() >= 0
|
|
|
823
823
|
url = {https://api.semanticscholar.org/CorpusID:274423406}
|
|
824
824
|
}
|
|
825
825
|
```
|
|
826
|
+
|
|
827
|
+
```bibtex
|
|
828
|
+
@misc{vali2025diveqdifferentiablevectorquantization,
|
|
829
|
+
title = {DiVeQ: Differentiable Vector Quantization Using the Reparameterization Trick},
|
|
830
|
+
author = {Mohammad Hassan Vali and Tom Bäckström and Arno Solin},
|
|
831
|
+
year = {2025},
|
|
832
|
+
eprint = {2509.26469},
|
|
833
|
+
archivePrefix = {arXiv},
|
|
834
|
+
primaryClass = {cs.LG},
|
|
835
|
+
url = {https://arxiv.org/abs/2509.26469},
|
|
836
|
+
}
|
|
837
|
+
```
|
|
@@ -779,3 +779,15 @@ assert loss.item() >= 0
|
|
|
779
779
|
url = {https://api.semanticscholar.org/CorpusID:274423406}
|
|
780
780
|
}
|
|
781
781
|
```
|
|
782
|
+
|
|
783
|
+
```bibtex
|
|
784
|
+
@misc{vali2025diveqdifferentiablevectorquantization,
|
|
785
|
+
title = {DiVeQ: Differentiable Vector Quantization Using the Reparameterization Trick},
|
|
786
|
+
author = {Mohammad Hassan Vali and Tom Bäckström and Arno Solin},
|
|
787
|
+
year = {2025},
|
|
788
|
+
eprint = {2509.26469},
|
|
789
|
+
archivePrefix = {arXiv},
|
|
790
|
+
primaryClass = {cs.LG},
|
|
791
|
+
url = {https://arxiv.org/abs/2509.26469},
|
|
792
|
+
}
|
|
793
|
+
```
|
|
@@ -75,8 +75,9 @@ torch.random.manual_seed(seed)
|
|
|
75
75
|
|
|
76
76
|
model = SimpleVQAutoEncoder(
|
|
77
77
|
codebook_size = num_codes,
|
|
78
|
-
rotation_trick =
|
|
79
|
-
straight_through = False
|
|
78
|
+
rotation_trick = False,
|
|
79
|
+
straight_through = False,
|
|
80
|
+
directional_reparam = True
|
|
80
81
|
).to(device)
|
|
81
82
|
|
|
82
83
|
opt = torch.optim.AdamW(model.parameters(), lr=lr)
|
|
@@ -224,6 +224,28 @@ def test_tiger():
|
|
|
224
224
|
|
|
225
225
|
assert torch.allclose(quantized, quantized_out, atol = 1e-5)
|
|
226
226
|
|
|
227
|
+
def test_directional_reparam():
|
|
228
|
+
from vector_quantize_pytorch import VectorQuantize, ResidualVQ
|
|
229
|
+
|
|
230
|
+
vq = VectorQuantize(
|
|
231
|
+
dim = 256,
|
|
232
|
+
codebook_size = 512, # codebook size
|
|
233
|
+
directional_reparam = True
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
x = torch.randn(1, 1024, 256).requires_grad_()
|
|
237
|
+
|
|
238
|
+
quantized, indices, _ = vq(x)
|
|
239
|
+
|
|
240
|
+
rq = ResidualVQ(
|
|
241
|
+
dim = 256,
|
|
242
|
+
num_quantizers = 8,
|
|
243
|
+
codebook_size = 128,
|
|
244
|
+
directional_reparam = True
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
quantized, indices, _ = rq(x)
|
|
248
|
+
|
|
227
249
|
@pytest.mark.parametrize('preserve_symmetry', (True, False))
|
|
228
250
|
def test_fsq(
|
|
229
251
|
preserve_symmetry
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from math import sqrt
|
|
3
4
|
from functools import partial, cache
|
|
4
5
|
from collections import namedtuple
|
|
5
6
|
|
|
@@ -28,6 +29,9 @@ def noop(*args, **kwargs):
|
|
|
28
29
|
def identity(t):
|
|
29
30
|
return t
|
|
30
31
|
|
|
32
|
+
def at_most_one_of(*bools):
|
|
33
|
+
return sum([*map(int, bools)]) <= 1
|
|
34
|
+
|
|
31
35
|
def l2norm(t, dim = -1, eps = 1e-6):
|
|
32
36
|
return F.normalize(t, p = 2, dim = dim, eps = eps)
|
|
33
37
|
|
|
@@ -264,6 +268,11 @@ def kmeans(
|
|
|
264
268
|
|
|
265
269
|
return means, bins
|
|
266
270
|
|
|
271
|
+
# straight through
|
|
272
|
+
|
|
273
|
+
def straight_through(src, tgt):
|
|
274
|
+
return src + (tgt + src).detach()
|
|
275
|
+
|
|
267
276
|
# rotation trick related
|
|
268
277
|
|
|
269
278
|
def efficient_rotation_trick_transform(u, q, e):
|
|
@@ -279,7 +288,7 @@ def efficient_rotation_trick_transform(u, q, e):
|
|
|
279
288
|
2 * (e @ rearrange(u, 'b d -> b d 1').detach() @ rearrange(q, 'b d -> b 1 d').detach())
|
|
280
289
|
)
|
|
281
290
|
|
|
282
|
-
return rearrange(out, '... 1 -> ...')
|
|
291
|
+
return rearrange(out, '... 1 d -> ... d')
|
|
283
292
|
|
|
284
293
|
def rotate_to(src, tgt):
|
|
285
294
|
# rotation trick STE (https://arxiv.org/abs/2410.06424) to get gradients through VQ layer.
|
|
@@ -299,6 +308,18 @@ def rotate_to(src, tgt):
|
|
|
299
308
|
|
|
300
309
|
return inverse(rotated)
|
|
301
310
|
|
|
311
|
+
# directional reparam related
|
|
312
|
+
# figure 1. https://openreview.net/forum?id=KRVnpTbx7R
|
|
313
|
+
|
|
314
|
+
def directional_reparam(src, tgt, noise_variance = 5e-3):
|
|
315
|
+
error_dir = tgt - src
|
|
316
|
+
error_dir_norm = error_dir.norm(dim = -1, keepdim = True)
|
|
317
|
+
|
|
318
|
+
noised_dir = error_dir + sqrt(noise_variance) * torch.randn_like(error_dir)
|
|
319
|
+
unit_noised_dir = l2norm(noised_dir)
|
|
320
|
+
|
|
321
|
+
return src + unit_noised_dir * error_dir_norm
|
|
322
|
+
|
|
302
323
|
# distributed helpers
|
|
303
324
|
|
|
304
325
|
@cache
|
|
@@ -898,12 +919,14 @@ class VectorQuantize(Module):
|
|
|
898
919
|
stochastic_sample_codes = False,
|
|
899
920
|
sample_codebook_temp = 1.,
|
|
900
921
|
straight_through = False,
|
|
901
|
-
rotation_trick = None,
|
|
922
|
+
rotation_trick = None, # propagate grads through VQ layer w/ rotation trick: https://arxiv.org/abs/2410.06424 by @cfifty
|
|
923
|
+
directional_reparam = False, # add the difference between the nearest code and input vector, with some noise on the direction
|
|
924
|
+
directional_reparam_variance = 5e-3,
|
|
902
925
|
sync_codebook = None,
|
|
903
926
|
sync_affine_param = False,
|
|
904
|
-
ema_update =
|
|
927
|
+
ema_update = None,
|
|
905
928
|
manual_ema_update = False,
|
|
906
|
-
learnable_codebook =
|
|
929
|
+
learnable_codebook = None,
|
|
907
930
|
in_place_codebook_optimizer: Callable[..., Optimizer] = None, # Optimizer used to update the codebook embedding if using learnable_codebook
|
|
908
931
|
manual_in_place_optimizer_update = False,
|
|
909
932
|
affine_param = False,
|
|
@@ -913,7 +936,14 @@ class VectorQuantize(Module):
|
|
|
913
936
|
return_zeros_for_masked_padding = True
|
|
914
937
|
):
|
|
915
938
|
super().__init__()
|
|
916
|
-
|
|
939
|
+
|
|
940
|
+
# defaults
|
|
941
|
+
|
|
942
|
+
ema_update = default(ema_update, not directional_reparam)
|
|
943
|
+
learnable_codebook = default(learnable_codebook, directional_reparam)
|
|
944
|
+
rotation_trick = default(rotation_trick, not directional_reparam and dim > 1) # only use rotation trick if feature dimension greater than 1
|
|
945
|
+
|
|
946
|
+
# basic variables
|
|
917
947
|
|
|
918
948
|
self.dim = dim
|
|
919
949
|
self.heads = heads
|
|
@@ -935,7 +965,7 @@ class VectorQuantize(Module):
|
|
|
935
965
|
|
|
936
966
|
self.eps = eps
|
|
937
967
|
|
|
938
|
-
self.has_commitment_loss = commitment_weight > 0.
|
|
968
|
+
self.has_commitment_loss = commitment_weight > 0. and not directional_reparam
|
|
939
969
|
self.commitment_weight = commitment_weight
|
|
940
970
|
self.commitment_use_cross_entropy_loss = commitment_use_cross_entropy_loss # whether to use cross entropy loss to codebook as commitment loss
|
|
941
971
|
|
|
@@ -953,9 +983,12 @@ class VectorQuantize(Module):
|
|
|
953
983
|
self.codebook_diversity_temperature = codebook_diversity_temperature
|
|
954
984
|
self.codebook_diversity_loss_weight = codebook_diversity_loss_weight
|
|
955
985
|
|
|
956
|
-
assert
|
|
986
|
+
assert at_most_one_of(straight_through, rotation_trick, directional_reparam)
|
|
957
987
|
self.rotation_trick = rotation_trick
|
|
958
988
|
|
|
989
|
+
self.directional_reparam = directional_reparam
|
|
990
|
+
self.directional_reparam_variance = directional_reparam_variance
|
|
991
|
+
|
|
959
992
|
assert not (ema_update and learnable_codebook), 'learnable codebook not compatible with EMA update'
|
|
960
993
|
|
|
961
994
|
assert 0 <= sync_update_v <= 1.
|
|
@@ -1213,9 +1246,11 @@ class VectorQuantize(Module):
|
|
|
1213
1246
|
if input_requires_grad:
|
|
1214
1247
|
if self.rotation_trick:
|
|
1215
1248
|
quantize = rotate_to(x, quantize)
|
|
1249
|
+
elif self.directional_reparam:
|
|
1250
|
+
quantize = directional_reparam(x, quantize, self.directional_reparam_variance)
|
|
1216
1251
|
else:
|
|
1217
1252
|
# standard STE to get gradients through VQ layer.
|
|
1218
|
-
quantize = x
|
|
1253
|
+
quantize = straight_through(x, quantize)
|
|
1219
1254
|
|
|
1220
1255
|
if self.sync_update_v > 0.:
|
|
1221
1256
|
# (21) in https://minyoungg.github.io/vqtorch/assets/draft_050523.pdf
|
{vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/.github/workflows/build.yml
RENAMED
|
File without changes
|
|
File without changes
|
{vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/.github/workflows/test.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/examples/autoencoder_fsq.py
RENAMED
|
File without changes
|
{vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/examples/autoencoder_lfq.py
RENAMED
|
File without changes
|
{vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/examples/autoencoder_sim_vq.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/tests/test_latent_quantization.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/vector_quantize_pytorch/sim_vq.py
RENAMED
|
File without changes
|
{vector_quantize_pytorch-1.23.4 → vector_quantize_pytorch-1.24.0}/vector_quantize_pytorch/utils.py
RENAMED
|
File without changes
|