torch.distributions.categorical 的源代码
# mypy: 允许未类型化定义
导入
火炬
来自
火炬
导入
纳尼,
张量
来自 torch.distributions
导入
约束
来自 torch.distributions.distribution
导入
分布
来自 torch.distributions.utils
导入
懒属性,
logits 转概率, probs_to_logits
全部 = [
"分类"]
[文档]
类
离散型随机变量分布(
分发):
r""
通过:attr:`probs`或:attr:`logits`(但不能同时使用)参数化一个分类分布。
它等价于:func:`torch.multinomial`从该分布中采样的分布。
.. 注意::
它等价于:func:`torch.multinomial`从该分布中采样的分布。
它等价于:func:`torch.multinomial`从该分布中采样的分布。
样本是从集合:math:`{0, ..., K-1}`中的整数,其中`K`是`probs.size(-1)`。
如果`probs`是一维且长度为`K`,则每个元素是该索引处采样类别的相对概率。
如果`probs`是 N 维的,则前 N-1 个维度被视为一个批次。
如果`probs`是 N 维的,则前 N-1 个维度被视为一个批次。
相对概率向量。
.. 注意:: `probs` 参数必须是非负的、有限的,并且总和不为零,
它将在最后一个维度上归一化,使其总和为 1。:attr:`probs`
将返回这个归一化的值。
`logits` 参数将被解释为未归一化的对数概率
因此可以是任何实数。它同样会被归一化,以便
结果概率在最后一个维度上求和为 1。:attr:`logits`
将返回这个归一化值。
参见::func:`torch.multinomial`
示例::
>>> # xdoctest: +IGNORE_WANT("非确定性")
>>> m = Categorical(torch.tensor([ 0.25, 0.25, 0.25, 0.25 ]))
>>> m.sample() # 等概率选择 0, 1, 2, 3
tensor(3)
参数:
probs (Tensor):事件概率
logits (Tensor):事件对数概率(未归一化)
"沉浸式翻译"
约束参数 = {
"概率":
约束.
单形, "logits":
约束.
实向量}
支持枚举 =
真实
def __init__(self, probs=无, logits=
无,
验证参数=
无):
如果 (
概率
是
无) == (
对数几率
是
无):
抛出
值错误(
"必须指定 `概率` 或 `对数几率` 中的一个,但不能同时指定。"
)
如果
概率
是
不是
无:
如果 probs.
暗淡() < 1:
抛出
值错误(
"必须至少是一维的 `probs` 参数。")
self.概率 =
概率 / probs.
总和(-1,
保持维度=
是)
否则:
如果 logits.
暗淡() < 1:
抛出
值错误(
"必须至少是一维的 `logits` 参数。")
# 正规化
self.对数几率 =
对数几率 - logits.logsumexp(
暗淡=-1,
保持维度=
是)
self._参数 = self.
概率
如果
概率
是
不是
无
否则 self.
对数几率
self.事件数量 = self.
参数.
尺寸()[-1]
批量形状 = (
self.参数.
尺寸()[:-1]
如果 self.
_参数.
维度() > 1
否则 torch.
尺寸()
)
超级().__init__(
批量形状,
验证参数=
验证参数)
[文档] def expand(self, batch_shape, _instance=None):
new = self._get_checked_instance(Categorical, _instance)
batch_shape = torch.Size(batch_shape)
param_shape = batch_shape + torch.Size((self._num_events,))
if "probs" in self.__dict__:
new.probs = self.probs.expand(param_shape)
new._param = new.probs
如果 "logits" 在 self.__dict__ 中:
new.logits = self.logits.expand(param_shape)
new._param = new.logits
new._num_events = self._num_events
super(Categorical, new).__init__(batch_shape, validate_args=False)
new._validate_args = self._validate_args
return new
def 新(self, *
参数, **kwargs):
返回 self.
参数.
新(*
参数, **kwargs)
@constraints.依赖属性(
是否离散=
是,
事件维度=0)
def 支持(self):
返回
约束.
整数区间(0, self.
_事件数 - 1)
@lazy_property
def logits(self) -> 张量:
返回
概率转 logits(self.
概率)
@lazy_property
def 概率(self) ->
张量:
返回
logits 转概率(self.logits)
@property
def 参数形状(self) -> torch.
尺寸:
返回 self.
_参数.
尺寸()
@property
def 均值(self) ->
张量:
返回 torch.full(
self._扩展形状(),
纳尼,
数据类型=self.
概率.
数据类型,
设备=self.
概率.
设备,
)
@property
def 模式(self) ->
张量:
返回 self.
概率.argmax(
暗淡=-1)
@property
def 方差(self) ->
张量:
返回 torch.full(
self.扩展形状(),
纳尼,
数据类型=self.
概率.
数据类型,
设备=self.
概率.
设备,
)
[文档] def sample(self, sample_shape=torch.Size()):
if not isinstance(sample_shape, torch.Size):
sample_shape = torch.Size(sample_shape)
probs_2d = self.probs.reshape(-1, self._num_events)
samples_2d = torch.multinomial(probs_2d, sample_shape.numel(), True).T
return samples_2d.reshape(self._extended_shape(sample_shape))
[文档] def log_prob(self, value):
if self._validate_args:
self._validate_sample(value)
value = value.long().unsqueeze(-1)
value, log_pmf = torch.broadcast_tensors(value, self.logits)
value = value[..., :1]
return log_pmf.gather(-1, value).squeeze(-1)
[文档] def entropy(self):
min_real = torch.finfo(self.logits.dtype).min
logits = torch.clamp(self.logits, min=min_real)
p_log_p = logits * self.probs
return -p_log_p.sum(-1)
[文档] def enumerate_support(self, expand=True):
事件数量 = self._num_events
values = torch.arange(num_events, dtype=torch.long, device=self._param.device)
values = values.view((-1,) + (1,) * len(self._batch_shape))
if expand:
values = values.expand((-1,) + self._batch_shape)
return values