torch.distributions.binomial 的源代码
# mypy: 允许未类型化定义
导入
火炬
来自
火炬
导入
张量
来自 torch.distributions
导入
约束
来自 torch.distributions.distribution
导入
分布
来自 torch.distributions.utils
导入 (
broadcast_all,
懒属性,
logits 转概率,
概率转 logits,
)
全部 = [
二项式]
def _clamp_by_zero(x):
# 类似于 clamp(x, min=0) 但在 0 处的梯度为 0.5
返回 (x.
卡钳(
最小值=0) + x - x.
卡钳(
最大值=0)) / 2
[文档]
类
二项分布(
分发):
r""
创建一个参数化 by :attr:`total_count` 的二项分布
要么是 :attr:`probs` 或 :attr:`logits`(但不能同时使用)。:attr:`total_count` 必须是
可以与 :attr:`probs`/:attr:`logits` 广播
示例::
>>> # xdoctest: +IGNORE_WANT("非确定性")
>>> m = Binomial(100, torch.tensor([0 , .2, .8, 1]))
>>> x = m.sample()
tensor([ 0., 22., 71., 100.])
>>> m = Binomial(torch.tensor([[5.], [10.]]), torch.tensor([0.5, 0.8]))
>>> x = m.sample()
tensor([[ 4., 5.],
[[7., 6.]]
参数:
总数(整数或张量):伯努利试验次数
概率(张量):事件概率
对数几率(张量):事件对数几率
"沉浸式翻译"
arg_constraints = {
总数:
约束.
非负整数,
"概率":
约束.
单位区间,
"logits": 约束.
真实,
}
支持枚举 =
真实
def __init__(self, 总数=1,
概率=
无, logits=
无,
验证参数=
无):
如果 (
概率
是
无) == (logits
是
无):
抛出
值错误(
"必须指定 `probs` 或 `logits` 中的一个,但不能同时指定。"
)
如果 probs
是
不是
无:
(
self.总数,
self.probs,
) = broadcast_all(总数,
概率)
self.总数 = self.
总数.
转换为类型(self.
可能)
否则:
(
self.总数,
self.logits,
) = broadcast_all(总数, logits)
self.总数 = self.
总数.
转换为类型(self.logits)
self._参数 = self.
概率
如果
概率
是
不是
无
否则 self.logits
批处理形状 = self.
_参数.
尺寸()
超级().__init__(
批处理形状,
验证参数=
验证参数)
[文档] def expand(self, batch_shape, _instance=None):
new = self._get_checked_instance(Binomial, _instance)
batch_shape = torch.Size(batch_shape)
new.total_count = self.total_count.expand(batch_shape)
if "probs" in self.__dict__:
new.probs = self.probs.expand(batch_shape)
new._param = new.probs
如果 "logits" 在 self.__dict__ 中:
new.logits = self.logits.expand(batch_shape)
new._param = new.logits
super(二项式, new).__init__(batch_shape, validate_args=False)
new._validate_args = self._validate_args
返回 new
def _new(self, *参数, **kwargs):
返回 self.
参数.
新(*
参数, **kwargs)
@constraints.依赖属性(
是否离散=
是,
事件维度=0)
def 支持(self):
返回
约束.
整数区间(0, self.
总数)
@property
def 均值(self) ->
张量:
返回 self.
总数 * self.
概率
@property
def 模式(self) ->
张量:
返回 ((self.
总数 + 1) * self.
概率).
向下取整().
卡钳(
最大值=self.
总数)
@property
def 方差(self) ->
张量:
返回 self.
总数 * self.
概率 * (1 - self.
概率)
@lazy_property
def logits(self) -> 张量:
返回
概率转 logits(self.
可能,
是否二进制=
是)
@lazy_property
def 可能(self) ->
张量:
返回
logits 转概率(self.logits,
是否二进制=
是)
@property
def 参数形状(self) -> torch.
尺寸:
返回 self._param.
尺寸()
[文档] def sample(self, sample_shape=torch.Size()):
shape = self._extended_shape(sample_shape)
with torch.no_grad():
return torch.binomial(
self.total_count.expand(shape), self.probs.expand(shape)
)
[文档] def log_prob(self, value):
if self._validate_args:
self._validate_sample(value)
log_factorial_n = torch.lgamma(self.total_count + 1)
log_factorial_k = torch.lgamma(value + 1)
log_factorial_nmk = torch.lgamma(self.total_count - value + 1)
# k * log(p) + (n - k) * log(1 - p) = k * (log(p) - log(1 - p)) + n * log(1 - p)
# (case logit < 0) = k * logit - n * log1p(e^logit)
# (case logit > 0) = k * logit - n * (log(p) - log(1 - p)) + n * log(p)
# = k * logit - n * logit - n * log1p(e^-logit)
# (merge two cases) = k * logit - n * max(logit, 0) - n * log1p(e^-|logit|)
normalize_term = (
self.total_count * _clamp_by_zero(self.logits)
+ self.total_count * torch.log1p(torch.exp(-torch.abs(self.logits)))
- log_factorial_n
)
return (
value * self.logits - log_factorial_k - log_factorial_nmk - normalize_term
)
[文档] def entropy(self):
total_count = int(self.total_count.max())
if not self.total_count.min() == total_count:
raise NotImplementedError(
"Inhomogeneous total count not supported by `entropy`."
)
log_prob = self.log_prob(self.enumerate_support(False))
return -(torch.exp(log_prob) * log_prob).sum(0)
[文档] def enumerate_support(self, expand=True):
total_count = int(self.total_count.max())
if not self.total_count.min() == total_count:
raise NotImplementedError(
"不支持由 `enumerate_support` 提供的不均匀总数。"
)
values = torch.arange(
1 + total_count, dtype=self._param.dtype, device=self._param.device
)
values = values.view((-1,) + (1,) * len(self._batch_shape))
if expand:
values = values.expand((-1,) + self._batch_shape)
返回值