vector-quantize-pytorch 1.18.3__tar.gz → 1.18.6__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 (26) hide show
  1. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/PKG-INFO +1 -11
  2. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/README.md +0 -10
  3. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/pyproject.toml +1 -1
  4. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/vector_quantize_pytorch/lookup_free_quantization.py +1 -10
  5. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/vector_quantize_pytorch/residual_fsq.py +46 -4
  6. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/vector_quantize_pytorch/residual_lfq.py +21 -2
  7. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/vector_quantize_pytorch/vector_quantize_pytorch.py +2 -17
  8. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/.github/workflows/build.yml +0 -0
  9. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/.github/workflows/python-publish.yml +0 -0
  10. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/.github/workflows/test.yml +0 -0
  11. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/.gitignore +0 -0
  12. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/LICENSE +0 -0
  13. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/examples/autoencoder.py +0 -0
  14. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/examples/autoencoder_fsq.py +0 -0
  15. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/examples/autoencoder_lfq.py +0 -0
  16. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/images/fsq.png +0 -0
  17. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/images/lfq.png +0 -0
  18. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/images/vq.png +0 -0
  19. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/ruff.toml +0 -0
  20. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/tests/test_latent_quantization.py +0 -0
  21. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/tests/test_readme.py +0 -0
  22. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/vector_quantize_pytorch/__init__.py +0 -0
  23. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/vector_quantize_pytorch/finite_scalar_quantization.py +0 -0
  24. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/vector_quantize_pytorch/latent_quantization.py +0 -0
  25. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/vector_quantize_pytorch/random_projection_quantizer.py +0 -0
  26. {vector_quantize_pytorch-1.18.3 → vector_quantize_pytorch-1.18.6}/vector_quantize_pytorch/residual_vq.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: vector-quantize-pytorch
3
- Version: 1.18.3
3
+ Version: 1.18.6
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
@@ -655,16 +655,6 @@ assert loss.item() >= 0
655
655
  }
656
656
  ```
657
657
 
658
- ```bibtex
659
- @article{Liu2023BridgingDA,
660
- title = {Bridging Discrete and Backpropagation: Straight-Through and Beyond},
661
- author = {Liyuan Liu and Chengyu Dong and Xiaodong Liu and Bin Yu and Jianfeng Gao},
662
- journal = {ArXiv},
663
- year = {2023},
664
- volume = {abs/2304.08612}
665
- }
666
- ```
667
-
668
658
  ```bibtex
669
659
  @inproceedings{huh2023improvedvqste,
670
660
  title = {Straightening Out the Straight-Through Estimator: Overcoming Optimization Challenges in Vector Quantized Networks},
@@ -611,16 +611,6 @@ assert loss.item() >= 0
611
611
  }
612
612
  ```
613
613
 
614
- ```bibtex
615
- @article{Liu2023BridgingDA,
616
- title = {Bridging Discrete and Backpropagation: Straight-Through and Beyond},
617
- author = {Liyuan Liu and Chengyu Dong and Xiaodong Liu and Bin Yu and Jianfeng Gao},
618
- journal = {ArXiv},
619
- year = {2023},
620
- volume = {abs/2304.08612}
621
- }
622
- ```
623
-
624
614
  ```bibtex
625
615
  @inproceedings{huh2023improvedvqste,
626
616
  title = {Straightening Out the Straight-Through Estimator: Overcoming Optimization Challenges in Vector Quantized Networks},
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "vector-quantize-pytorch"
3
- version = "1.18.3"
3
+ version = "1.18.6"
4
4
  description = "Vector Quantization - Pytorch"
5
5
  authors = [
6
6
  { name = "Phil Wang", email = "lucidrains@gmail.com" }
@@ -103,7 +103,6 @@ class LFQ(Module):
103
103
  commitment_loss_weight = 0.,
104
104
  diversity_gamma = 1.,
105
105
  straight_through_activation = nn.Identity(),
106
- scale_trick = False, # @cfifty Fifty et al. https://arxiv.org/abs/2410.06424
107
106
  num_codebooks = 1,
108
107
  keep_num_codebooks_dim = None,
109
108
  codebook_scale = 1., # for residual LFQ, codebook scaled down by 2x at each layer
@@ -161,9 +160,6 @@ class LFQ(Module):
161
160
 
162
161
  self.activation = straight_through_activation
163
162
 
164
- assert not (scale_trick and spherical)
165
- self.scale_trick = scale_trick
166
-
167
163
  # whether to use BSQ (binary spherical quantization)
168
164
 
169
165
  self.spherical = spherical
@@ -326,12 +322,7 @@ class LFQ(Module):
326
322
 
327
323
  if self.training:
328
324
  x = self.activation(x)
329
-
330
- if self.scale_trick:
331
- x = x * (quantized / x).detach()
332
- else:
333
- x = x + (quantized - x).detach()
334
-
325
+ x = x + (quantized - x).detach()
335
326
  else:
336
327
  x = quantized
337
328
 
@@ -1,6 +1,6 @@
1
1
  import random
2
2
  from math import log2
3
- from functools import partial
3
+ from functools import partial, cache
4
4
 
5
5
  from typing import List
6
6
 
@@ -9,6 +9,7 @@ from torch import nn
9
9
  from torch.nn import Module, ModuleList
10
10
  import torch.nn.functional as F
11
11
  from torch.amp import autocast
12
+ import torch.distributed as dist
12
13
 
13
14
  from vector_quantize_pytorch.finite_scalar_quantization import FSQ
14
15
 
@@ -30,6 +31,12 @@ def default(val, d):
30
31
  def round_up_multiple(num, mult):
31
32
  return ceil(num / mult) * mult
32
33
 
34
+ # distributed helpers
35
+
36
+ @cache
37
+ def is_distributed():
38
+ return dist.is_initialized() and dist.get_world_size() > 1
39
+
33
40
  # main class
34
41
 
35
42
  class ResidualFSQ(Module):
@@ -38,9 +45,10 @@ class ResidualFSQ(Module):
38
45
  def __init__(
39
46
  self,
40
47
  *,
41
- dim,
42
48
  levels: List[int],
43
49
  num_quantizers,
50
+ dim = None,
51
+ is_channel_first = False,
44
52
  quantize_dropout = False,
45
53
  quantize_dropout_cutoff_index = 0,
46
54
  quantize_dropout_multiple_of = 1,
@@ -48,12 +56,14 @@ class ResidualFSQ(Module):
48
56
  ):
49
57
  super().__init__()
50
58
  codebook_dim = len(levels)
59
+ dim = default(dim, codebook_dim)
51
60
 
52
61
  requires_projection = codebook_dim != dim
53
62
  self.project_in = nn.Linear(dim, codebook_dim) if requires_projection else nn.Identity()
54
63
  self.project_out = nn.Linear(codebook_dim, dim) if requires_projection else nn.Identity()
55
64
  self.has_projections = requires_projection
56
65
 
66
+ self.is_channel_first = is_channel_first
57
67
  self.num_quantizers = num_quantizers
58
68
 
59
69
  self.levels = levels
@@ -143,10 +153,18 @@ class ResidualFSQ(Module):
143
153
  ):
144
154
  num_quant, quant_dropout_multiple_of, device = self.num_quantizers, self.quantize_dropout_multiple_of, x.device
145
155
 
156
+ # handle channel first
157
+
158
+ if self.is_channel_first:
159
+ x = rearrange(x, 'b d ... -> b ... d')
160
+ x, ps = pack([x], 'b * d')
161
+
162
+ # maybe project in
163
+
146
164
  x = self.project_in(x)
147
165
 
148
166
  quantized_out = 0.
149
- residual = first(self.layers).bound(x)
167
+ residual = x
150
168
 
151
169
  all_indices = []
152
170
 
@@ -156,7 +174,19 @@ class ResidualFSQ(Module):
156
174
  # also prepare null indices
157
175
 
158
176
  if should_quantize_dropout:
159
- rand = random.Random(rand_quantize_dropout_fixed_seed) if exists(rand_quantize_dropout_fixed_seed) else random
177
+
178
+ if exists(rand_quantize_dropout_fixed_seed):
179
+ # seed is manually passed in
180
+ rand = random.Random(rand_quantize_dropout_fixed_seed)
181
+
182
+ elif is_distributed():
183
+ # in distributed environment, synchronize a random seed value if not given
184
+ t = torch.tensor(random.randrange(10_000), device = device)
185
+ dropout_seed = dist.all_reduce(t).item()
186
+ rand = random.Random(dropout_seed)
187
+
188
+ else:
189
+ rand = random
160
190
 
161
191
  rand_quantize_dropout_index = rand.randrange(self.quantize_dropout_cutoff_index, num_quant)
162
192
 
@@ -175,6 +205,7 @@ class ResidualFSQ(Module):
175
205
  continue
176
206
 
177
207
  quantized, indices = layer(residual / scale)
208
+
178
209
  quantized = quantized * scale
179
210
 
180
211
  residual = residual - quantized.detach()
@@ -190,6 +221,17 @@ class ResidualFSQ(Module):
190
221
 
191
222
  all_indices = torch.stack(all_indices, dim = -1)
192
223
 
224
+ # channel first out
225
+
226
+ if self.is_channel_first:
227
+ quantized_out, = unpack(quantized_out, ps, 'b * d')
228
+ all_indices, = unpack(all_indices, ps, 'b * d')
229
+
230
+ quantized_out = rearrange(quantized_out, 'b ... d -> b d ...')
231
+ all_indices = rearrange(all_indices, 'b ... d -> b d ...')
232
+
233
+ # return
234
+
193
235
  ret = (quantized_out, all_indices)
194
236
 
195
237
  if not return_all_codes:
@@ -1,12 +1,13 @@
1
1
  import random
2
2
  from math import log2
3
- from functools import partial
3
+ from functools import partial, cache
4
4
 
5
5
  import torch
6
6
  from torch import nn
7
7
  from torch.nn import Module, ModuleList
8
8
  import torch.nn.functional as F
9
9
  from torch.amp import autocast
10
+ import torch.distributed as dist
10
11
 
11
12
  from vector_quantize_pytorch.lookup_free_quantization import LFQ
12
13
 
@@ -25,6 +26,12 @@ def default(val, d):
25
26
  def round_up_multiple(num, mult):
26
27
  return ceil(num / mult) * mult
27
28
 
29
+ # distributed helpers
30
+
31
+ @cache
32
+ def is_distributed():
33
+ return dist.is_initialized() and dist.get_world_size() > 1
34
+
28
35
  # main class
29
36
 
30
37
  class ResidualLFQ(Module):
@@ -144,7 +151,19 @@ class ResidualLFQ(Module):
144
151
  # also prepare null indices and loss
145
152
 
146
153
  if should_quantize_dropout:
147
- rand = random.Random(rand_quantize_dropout_fixed_seed) if exists(rand_quantize_dropout_fixed_seed) else random
154
+
155
+ if exists(rand_quantize_dropout_fixed_seed):
156
+ # seed is manually passed in
157
+ rand = random.Random(rand_quantize_dropout_fixed_seed)
158
+
159
+ elif is_distributed():
160
+ # in distributed environment, synchronize a random seed value if not given
161
+ t = torch.tensor(random.randrange(10_000), device = device)
162
+ dropout_seed = dist.all_reduce(t).item()
163
+ rand = random.Random(dropout_seed)
164
+
165
+ else:
166
+ rand = random
148
167
 
149
168
  rand_quantize_dropout_index = rand.randrange(self.quantize_dropout_cutoff_index, num_quant)
150
169
 
@@ -103,7 +103,6 @@ def gumbel_sample(
103
103
  temperature = 1.,
104
104
  stochastic = False,
105
105
  straight_through = False,
106
- reinmax = False,
107
106
  dim = -1,
108
107
  training = True
109
108
  ):
@@ -117,23 +116,11 @@ def gumbel_sample(
117
116
  ind = sampling_logits.argmax(dim = dim)
118
117
  one_hot = F.one_hot(ind, size).type(dtype)
119
118
 
120
- assert not (reinmax and not straight_through), 'reinmax can only be turned on if using straight through gumbel softmax'
121
-
122
119
  if not straight_through or temperature <= 0. or not training:
123
120
  return ind, one_hot
124
121
 
125
- # use reinmax for better second-order accuracy - https://arxiv.org/abs/2304.08612
126
- # algorithm 2
127
-
128
- if reinmax:
129
- π0 = logits.softmax(dim = dim)
130
- π1 = (one_hot + (logits / temperature).softmax(dim = dim)) / 2
131
- π1 = ((log(π1) - logits).detach() + logits).softmax(dim = 1)
132
- π2 = 2 * π1 - 0.5 * π0
133
- one_hot = π2 - π2.detach() + one_hot
134
- else:
135
- π1 = (logits / temperature).softmax(dim = dim)
136
- one_hot = one_hot + π1 - π1.detach()
122
+ π1 = (logits / temperature).softmax(dim = dim)
123
+ one_hot = one_hot + π1 - π1.detach()
137
124
 
138
125
  return ind, one_hot
139
126
 
@@ -828,7 +815,6 @@ class VectorQuantize(Module):
828
815
  sample_codebook_temp = 1.,
829
816
  straight_through = False,
830
817
  rotation_trick = True, # Propagate grads through VQ layer w/ rotation trick: https://arxiv.org/abs/2410.06424 by @cfifty
831
- reinmax = False, # using reinmax for improved straight-through, assuming straight through helps at all
832
818
  sync_codebook = None,
833
819
  sync_affine_param = False,
834
820
  ema_update = True,
@@ -895,7 +881,6 @@ class VectorQuantize(Module):
895
881
  gumbel_sample_fn = partial(
896
882
  gumbel_sample,
897
883
  stochastic = stochastic_sample_codes,
898
- reinmax = reinmax,
899
884
  straight_through = straight_through
900
885
  )
901
886