What the difference between the sample() and rsample()?
I can see the implementation in the source code as the following, but still not really understand when and why should use sample() not rsample()?
def rsample(self, sample_shape=torch.Size()): shape = self._extended_shape(sample_shape) eps = _standard_normal(shape, dtype=self.loc.dtype, device=self.loc.device) return self.loc + eps * self.scale def sample(self, sample_shape=torch.Size()): shape = self._extended_shape(sample_shape) with torch.no_grad(): return torch.bernoulli(self.probs.expand(shape)) class no_grad(_DecoratorContextManager): r"""Context-manager that disabled gradient calculation. Disabling gradient calculation is useful for inference, when you are sure that you will not call :meth:`Tensor.backward()`. It will reduce memory consumption for computations that would otherwise have `requires_grad=True`. In this mode, the result of every computation will have `requires_grad=False`, even when the inputs have `requires_grad=True`. This mode has no effect when using :class:`~enable_grad` context manager . This context manager is thread local; it will not affect computation in other threads. Also functions as a decorator. (Make sure to instantiate with parenthesis.) Example:: >>> x = torch.tensor(, requires_grad=True) >>> with torch.no_grad(): ... y = x * 2 >>> y.requires_grad False >>> @torch.no_grad() ... def doubler(x): ... return x * 2 >>> z = doubler(x) >>> z.requires_grad False """ def __enter__(self): self.prev = torch.is_grad_enabled() torch._C.set_grad_enabled(False) def __exit__(self, *args): torch.set_grad_enabled(self.prev)