sample()
:从概率分布中随机抽样。所以,我们cannot反向传播,因为它是随机的! (计算图为cut off).
查看源代码sample
in torch.distributions.normal.Normal
:
def sample(self, sample_shape=torch.Size()):
shape = self._extended_shape(sample_shape)
with torch.no_grad():
return torch.normal(self.loc.expand(shape), self.scale.expand(shape))
torch.normal
返回一个张量random数字。还,torch.no_grad()
上下文阻止计算图进一步增长。
你看,我们不能反向传播。返回的张量为sample()
仅包含一些数字,而不是整个计算图。
那么,什么是rsample()
?
通过使用rsample
, we can反向传播,因为它保留计算图 alive.
如何?通过将随机性放在单独的参数中。这称为“重新参数化技巧”。
r样本:使用抽样r重新参数化技巧。
有eps
在源代码中:
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
# `self.loc` is the mean and `self.scale` is the standard deviation.
eps
是负责采样随机性的单独参数。
看返回值:平均值+eps
* 标准差
eps
does not取决于您想要区分的参数。
所以,现在你可以自由地反向传播(=微分),因为eps
当参数改变时不改变。
(如果我们改变参数,重新参数化样本的分布does改变因为self.loc
and self.scale
变化,但分布eps
does not改变。)
请注意,抽样的随机性来自于随机抽样eps
。有no计算图本身的随机性。一次eps
被选择了,就被固定了。 (元素的分布eps
在采样后是固定的。)
例如,在强化学习中SAC(Soft Actor-Critic)算法的实现中,eps
可能由对应于单个小批量操作的元素组成(并且一个操作可能由许多元素组成)。