Skip to content

Commit 6441692

Browse files
sampler: allow without replacement sampling for LogUniformSampler (#85)
Co-authored-by: Albert Zeyer <albzey@gmail.com>
1 parent 799dd7a commit 6441692

1 file changed

Lines changed: 13 additions & 8 deletions

File tree

i6_models/parts/samplers/log_uniform.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,43 @@
88

99
class LogUniformSampler(nn.Module):
1010
def __init__(
11-
self, num_classes: int, *, distribution_clamp_min: float = 1e-10, device: Optional[torch.device] = None
11+
self,
12+
num_classes: int,
13+
*,
14+
with_replacement: bool = True,
15+
distribution_clamp_min: float = 1e-10,
16+
device: Optional[torch.device] = None,
1217
):
1318
"""
14-
Samples from a log uniform distribution from classes. Sampling is performed with replacement, i.e. sampled
15-
indices can appear more than once in sampled set. This can be implemented with
16-
`torch.distributions.multinomial.Multinomial` or `torch.multinomial`.
19+
Samples from a log uniform distribution from classes. This assumes that the vocabulary is sorted according to
20+
word count descending.
1721
1822
:param num_classes: number of classes from which the distribution is sampled. The class indices are sorted in
1923
descending order according to their frequency.
24+
:param with_replacement: wether to sample with replacement or not.
25+
:param distribution_clamp_min: minimum probability mass.
2026
:param device: device on which the distribution is sampled.
2127
"""
2228
super().__init__()
2329

2430
# assumes count-sorted vocabulary, descending
2531
self.num_classes = num_classes
32+
self.with_replacement = with_replacement
2633

2734
# approximately zipf distribution
2835
ws = torch.arange(self.num_classes, dtype=torch.get_default_dtype(), device=device)
2936
self._distribution = (torch.log1p(ws + 1) - torch.log1p(ws)) / torch.log1p(torch.tensor(self.num_classes))
3037
self._distribution.clamp_(min=distribution_clamp_min)
3138
self._distribution /= self._distribution.sum()
3239

33-
self._cat_sampler = torch.distributions.categorical.Categorical(probs=self._distribution)
34-
3540
def sample(self, num_samples: int) -> torch.Tensor:
3641
"""
3742
Returns a random tensor in the size of [num_samples].
3843
3944
:param num_samples: number of samples.
4045
:return: [num_samples]
4146
"""
42-
return self._cat_sampler.sample(torch.Size([num_samples]))
47+
return torch.multinomial(self._distribution, num_samples, replacement=self.with_replacement)
4348

4449
def log_prob(self, indices: torch.Tensor) -> torch.Tensor:
4550
"""
@@ -48,4 +53,4 @@ def log_prob(self, indices: torch.Tensor) -> torch.Tensor:
4853
:param indices: the ground truth target labels as indices.
4954
:return: [B x T]
5055
"""
51-
return self._cat_sampler.log_prob(indices)
56+
return torch.log(self._distribution[indices])

0 commit comments

Comments
 (0)