torch.distributions.relaxed_bernoulli 源代码
# mypy: 允许未类型化定义
导入
火炬
from 火炬
导入
张量
from torch.distributions 导入
约束
from torch.distributions.distribution 导入
分布
from torch.distributions.transformed_distribution 导入
转换分布
from torch.distributions.transforms 导入
Sigmoid 变换
from torch.distributions.utils 导入 (
广播全部,
clamp_probs,
懒属性,
logits 转概率,
概率转对数概率,
)
from torch.types 导入
数,
_大小
全部 = [
LogitRelaxedBernoulli, "RelaxedBernoulli"]
[文档]
类
对数伯努利分布(
分发):
r""
创建一个由 :attr:`probs` 或 :attr:`logits` (但不能同时使用)参数化的 LogitRelaxedBernoulli 分布
它是 RelaxedBernoulli 分布的对数几率
。
样本是对(0, 1)区间内值的 logits。参见[1]获取更多详细信息。
参数:
温度(张量):松弛温度
probs (Number, Tensor): 采样 `1` 的概率
logits (Number, Tensor): 采样 `1` 的对数几率
[1] 《混凝土分布:离散随机变量的连续松弛》(Maddison 等人,2017 年)
变量(Maddison 等人,2017)
[2] 基于 Gumbel-Softmax 的类别重参数化
(Jang 等人,2017)
""
约束参数 = {
"概率":
约束.
单位区间, "logits":
约束.
真实}
支持 =
约束.
真实
def __init__(self, 温度,
概率=
无, logits=
无,
验证参数=
无):
self.温度 =
温度
如果 (
概率 is
无) == (logits is
无):
提升 ValueError(
"必须指定 `probs` 或 `logits` 中的一个,但不能同时指定。"
)
如果
概率 is
不是
无:
是否为标量 = isinstance(
概率,
数)
(self.概率,) =
广播全部(
概率)
else:
是否为标量 = isinstance(logits,
数)
(self.logits,) = 广播全部(logits)
self._参数 = self.
概率
如果
概率 is
不是
无
否则 self.logits
如果 is_scalar:
批量形状 =
火炬.
尺寸()
else:
批量形状 = self._param.
尺寸()
超级().__init__(
批量形状,
验证参数=
验证参数)
[文档] def expand(self, batch_shape, _instance=None):
new = self._get_checked_instance(LogitRelaxedBernoulli, _instance)
batch_shape = torch.Size(batch_shape)
new.temperature = self.temperature
if "probs" in self.__dict__:
new.probs = self.probs.expand(batch_shape)
new._param = new.probs
if "logits" in self.__dict__:
new.logits = self.logits.expand(batch_shape)
new._param = new.logits
super(LogitRelaxedBernoulli, new).__init__(batch_shape, validate_args=False)
new._validate_args = self._validate_args
return new
def 新(self, *
参数, **kwargs):
返回 self._param.
新(*
参数, **kwargs)
@lazy_property
def logits(self) 翻译
张量:
返回
概率转对数概率(self.
概率,
是否二进制=
是)
@lazy_property
def 概率(self)
翻译
张量:
返回
logits 转概率(self.logits,
是否二进制=
是)
@property
def 参数形状(self)
翻译
火炬.
尺寸:
返回 self._param.
尺寸()
[文档] def rsample(self, sample_shape: _size = torch.Size()) -> Tensor:
shape = self._extended_shape(sample_shape)
probs = clamp_probs(self.probs.expand(shape))
uniforms = clamp_probs(
torch.rand(shape, dtype=probs.dtype, device=probs.device)
)
return (
uniforms.log() - (-uniforms).log1p() + probs.log() - (-probs).log1p()
) / self.temperature
[文档] def log_prob(self, value):
if self._validate_args:
self._validate_sample(value)
logits, value = broadcast_all(self.logits, value)
diff = logits - value.mul(self.temperature)
return self.temperature.log() + diff - 2 * diff.exp().log1p()
[文档]class RelaxedBernoulli(TransformedDistribution):
r"""
创建一个由参数化的 RelaxedBernoulli 分布
`温度`,以及`probs`或`logits`之一
(但不能同时使用)。这是`伯努利`分布的宽松版本,
因此值在(0,1)之间,并且具有可重新参数化的样本。
示例::
>>> # xdoctest: +IGNORE_WANT("非确定性")
>>> m = RelaxedBernoulli(torch.tensor([2.2]),
... torch.tensor([0.1, 0.2, 0.3, 0.99]))
>>> m.sample()
tensor([ 0.2951, 0.3442, 0.8918, 0.9021])
Args:
temperature (Tensor): 松弛温度
probs (Number, Tensor): 抽样 `1` 的概率
logits (数字,张量):采样 `1` 的对数几率
"""
arg_constraints = {"probs": constraints.unit_interval, "logits": constraints.real}
support = constraints.unit_interval
has_rsample = True
def __init__(self, temperature, probs=None, logits=None, validate_args=None):
base_dist = LogitRelaxedBernoulli(temperature, probs, logits)
super().__init__(base_dist, SigmoidTransform(), validate_args=validate_args)
[文档] def expand(self, batch_shape, _instance=None):
new = self._get_checked_instance(RelaxedBernoulli, _instance)
return super().expand(batch_shape, _instance=new)
@property
def temperature(self) -> Tensor:
return self.base_dist.temperature
@property
def logits(self) -> Tensor:
return self.base_dist.logits
@property
def probs(self) -> Tensor:
return self.base_dist.probs