概率分布 - torch.distributions
distributions 包含可参数化的概率分布和采样函数. 这允许构造用于优化的随机计算图和随机梯度估计器. 这个包一般遵循 TensorFlow Distributions 包的设计.
通常, 不可能直接通过随机样本反向传播. 但是, 有两种主要方法可创建可以反向传播的代理函数. 即得分函数估计器/似然比估计器/REINFORCE和pathwise derivative估计器. REINFORCE通常被视为强化学习中策略梯度方法的基础, 并且pathwise derivative估计器常见于变分自动编码器中的重新参数化技巧. 得分函数仅需要样本的值 , pathwise derivative 需要导数
. 接下来的部分将在一个强化学习示例中讨论这两个问题. 有关详细信息, 请参阅 Gradient Estimation Using Stochastic Computation Graphs .
得分函数
当概率密度函数相对于其参数可微分时, 我们只需要sample()和log_prob()来实现REINFORCE:
是参数,
是学习速率,
是奖励 并且
是在状态
以及给定策略
执行动作
的概率.
在实践中, 我们将从网络输出中采样一个动作, 将这个动作应用于一个环境中, 然后使用log_prob构造一个等效的损失函数. 请注意, 我们使用负数是因为优化器使用梯度下降, 而上面的规则假设梯度上升. 有了确定的策略, REINFORCE的实现代码如下:
probs = policy_network(state)
# Note that this is equivalent to what used to be called multinomial
m = Categorical(probs)
action = m.sample()
next_state, reward = env.step(action)
loss = -m.log_prob(action) * reward
loss.backward()
Pathwise derivative
实现这些随机/策略梯度的另一种方法是使用来自rsample()方法的重新参数化技巧, 其中参数化随机变量可以通过无参数随机变量的参数确定性函数构造. 因此, 重新参数化的样本变得可微分. 实现Pathwise derivative的代码如下:
params = policy_network(state)
m = Normal(*params)
# Any distribution with .has_rsample == True could work based on the application
action = m.rsample()
next_state, reward = env.step(action) # Assuming that reward is differentiable
loss = -reward
loss.backward()
分布
class torch.distributions.distribution.Distribution(batch_shape=torch.Size([]), event_shape=torch.Size([]), validate_args=None)
Distribution是概率分布的抽象基类.
arg_constraints
从参数名称返回字典到 Constraint 对象(应该满足这个分布的每个参数).不是张量的arg不需要出现在这个字典中.
batch_shape
返回批量参数的形状.
cdf(value)
返回value处的累积密度/质量函数估计.
| 参数: | value (Tensor) – |
entropy()
返回分布的熵, 批量的形状为 batch_shape.
| 返回值: | Tensor 形状为 batch_shape. |
enumerate_support(expand=True)
返回包含离散分布支持的所有值的张量. 结果将在维度0上枚举, 所以结果的形状将是 (cardinality,) + batch_shape + event_shape (对于单变量分布 event_shape = ()).
注意, 这在lock-step中枚举了所有批处理张量[[0, 0], [1, 1], …]. 当 expand=False, 枚举沿着维度 0进行, 但是剩下的批处理维度是单维度, [[0], [1], ...
遍历整个笛卡尔积的使用 itertools.product(m.enumerate_support()).
| 参数: | expand (bool) – 是否扩展对批处理dim的支持以匹配分布的 batch_shape. |
| 返回值: | 张量在维上0迭代. |
event_shape
返回单个样本的形状 (非批量).
expand(batch_shape, _instance=None)
返回一个新的分布实例(或填充派生类提供的现有实例), 其批处理维度扩展为 batch_shape. 这个方法调用 expand 在分布的参数上. 因此, 这不会为扩展的分布实例分配新的内存. 此外, 第一次创建实例时, 这不会在中重复任何参数检查或参数广播在 __init__.py.
参数:
batch_shape (torch.Size) – 所需的扩展尺寸.
_instance – 由需要重写.expand的子类提供的新实例.
| 返回值: | 批处理维度扩展为batch_size的新分布实例. |
icdf(value)
返回按value计算的反向累积密度/质量函数.
| 参数: | value (Tensor) – |
log_prob(value)
返回按value计算的概率密度/质量函数的对数.
| 参数: | value (Tensor) – |
mean
返回分布的平均值.
perplexity()
返回分布的困惑度, 批量的关于 batch_shape.
| 返回值: | 形状为 batch_shape 的张量. |
rsample(sample_shape=torch.Size([]))
如果分布的参数是批量的, 则生成sample_shape形状的重新参数化样本或sample_shape形状的批量重新参数化样本.
sample(sample_shape=torch.Size([]))
如果分布的参数是批量的, 则生成sample_shape形状的样本或sample_shape形状的批量样本.
sample_n(n)
如果分布参数是分批的, 则生成n个样本或n批样本.
stddev
返回分布的标准差.
support
返回Constraint 对象表示该分布的支持.
variance
返回分布的方差.
ExponentialFamily
class torch.distributions.exp_family.ExponentialFamily(batch_shape=torch.Size([]), event_shape=torch.Size([]), validate_args=None)
指数族是指数族概率分布的抽象基类, 其概率质量/密度函数的形式定义如下
表示自然参数,
表示充分统计量,
是给定族的对数归一化函数
是carrier measure.
注意
该类是Distribution类与指数族分布之间的中介, 主要用于检验.entropy()和解析KL散度方法的正确性. 我们使用这个类来计算熵和KL散度使用AD框架和Bregman散度 (出自: Frank Nielsen and Richard Nock, Entropies and Cross-entropies of Exponential Families).
entropy()
利用对数归一化器的Bregman散度计算熵的方法.
Bernoulli
class torch.distributions.bernoulli.Bernoulli(probs=None, logits=None, validate_args=None)
创建参数化的伯努利分布, 根据 probs 或者 logits (但不是同时都有).
样本是二值的 (0 或者 1). 取值 1 伴随概率 p , 或者 0 伴随概率 1 - p.
例子:
>>> m = Bernoulli(torch.tensor([0.3]))
>>> m.sample() # 30% chance 1; 70% chance 0
tensor([ 0.])
参数:
probs (Number_,_ Tensor) – the probabilty of sampling 1
logits (Number_,_ Tensor) – the log-odds of sampling 1
arg_constraints = {'logits': Real(), 'probs': Interval(lower_bound=0.0, upper_bound=1.0)}
entropy()
enumerate_support(expand=True)
expand(batch_shape, _instance=None)
has_enumerate_support = True
log_prob(value)
logits
mean
param_shape
probs
sample(sample_shape=torch.Size([]))
support = Boolean()
variance
Beta
class torch.distributions.beta.Beta(concentration1, concentration0, validate_args=None)
例子:
>>> m = Beta(torch.tensor([0.5]), torch.tensor([0.5]))
>>> m.sample() # Beta distributed with concentration concentration1 and concentration0
tensor([ 0.1046])
参数:
concentration1 (float or Tensor) – 分布的第一个浓度参数(通常称为alpha)
concentration0 (float or Tensor) – 分布的第二个浓度参数(通常称为beta)
arg_constraints = {'concentration0': GreaterThan(lower_bound=0.0), 'concentration1': GreaterThan(lower_bound=0.0)}
concentration0
concentration1
entropy()
expand(batch_shape, _instance=None)
has_rsample = True
log_prob(value)
mean
rsample(sample_shape=())
support = Interval(lower_bound=0.0, upper_bound=1.0)
variance
Binomial
class torch.distributions.binomial.Binomial(total_count=1, probs=None, logits=None, validate_args=None)
创建一个Binomial 分布, 参数为 total_count 和 probs 或者 logits (但不是同时都有使用). total_count 必须和 [probs] 之间可广播(#torch.distributions.binomial.Binomial.probs "torch.distributions.binomial.Binomial.probs")/logits.
例子:
>>> 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.]])
参数:
total_count (int or Tensor) – 伯努利试验次数
probs (Tensor) – 事件概率
logits (Tensor) – 事件 log-odds
arg_constraints = {'logits': Real(), 'probs': Interval(lower_bound=0.0, upper_bound=1.0), 'total_count': IntegerGreaterThan(lower_bound=0)}
enumerate_support(expand=True)
expand(batch_shape, _instance=None)
has_enumerate_support = True
log_prob(value)
logits
mean
param_shape
probs
sample(sample_shape=torch.Size([]))
support
variance
Categorical
class torch.distributions.categorical.Categorical(probs=None, logits=None, validate_args=None)
创建一个 categorical 分布, 参数为 probs 或者 logits (但不是同时都有).
注意
样本是整数来自 K 是 probs.size(-1).
如果 probs 是 1D 的, 长度为K, 每个元素是在该索引处对类进行抽样的相对概率.
如果 probs 是 2D 的, 它被视为一组相对概率向量.
注意
probs 必须是非负的、有限的并且具有非零和, 并且它将被归一化为和为1.
例子:
>>> m = Categorical(torch.tensor([ 0.25, 0.25, 0.25, 0.25 ]))
>