理解pytorch中正态分布的log_prob

Sam*_*ant 6 reinforcement-learning probability-distribution pytorch

我目前正在尝试从具有连续动作空间的 openAi 健身房环境中解决 Pendulum-v0。因此,我需要使用正态分布来对我的行为进行采样。我不明白的是 log_prob 使用时的维度:

import torch
from torch.distributions import Normal 

means = torch.tensor([[0.0538],
        [0.0651]])
stds = torch.tensor([[0.7865],
        [0.7792]])

dist = Normal(means, stds)
a = torch.tensor([1.2,3.4])
d = dist.log_prob(a)
print(d.size())
Run Code Online (Sandbox Code Playgroud)

我期待一个大小为 2 的张量(每个动作一个 log_prob),但它输出一个大小为(2,2)的张量。

但是,当对离散环境使用分类分布时,log_prob 具有预期大小:

logits = torch.tensor([[-0.0657, -0.0949],
        [-0.0586, -0.1007]])

dist = Categorical(logits = logits)
a = torch.tensor([1, 1])
print(dist.log_prob(a).size())
Run Code Online (Sandbox Code Playgroud)

给我一个大小为(2)的张量。

为什么正态分布的 log_prob 大小不同?

小智 7

如果查看torch.distributions.Normal源代码并找到 log_prob(value) 函数的定义,可以看到计算的主要部分是:

return -((value - self.loc) ** 2) / (2 * var) - some other part
Run Code Online (Sandbox Code Playgroud)

其中value是一个变量,其中包含要计算其对数概率的值(在您的情况下为a),self.loc是分布的平均值(在您的情况下为means),var是方差,即标准差的平方(在您的情况下,stds **2)。可以看到,这确实是正态分布的概率密度函数的对数,减去上面我没有写的一些常数和标准差的对数。

在第一个示例中,您将meansstds定义为列向量,而将值定义为行向量

means = torch.tensor([[0.0538],
    [0.0651]])
stds = torch.tensor([[0.7865],
    [0.7792]])
a = torch.tensor([1.2,3.4])
Run Code Online (Sandbox Code Playgroud)

但是,从列向量中减去行向量,代码在 Python 中的value - self.loc中执行的操作会给出一个矩阵(尝试!),因此您获得的结果是两个定义的分布中的每一个以及每个分布的 log_prob 值a中的变量。

如果您想获得没有交叉项的 log_prob,则一致地定义变量,即

means = torch.tensor([[0.0538],
    [0.0651]])
stds = torch.tensor([[0.7865],
    [0.7792]])
a = torch.tensor([[1.2],[3.4]])
Run Code Online (Sandbox Code Playgroud)

或者

means = torch.tensor([0.0538,
    0.0651])
stds = torch.tensor([0.7865,
    0.7792])
a = torch.tensor([1.2,3.4])
Run Code Online (Sandbox Code Playgroud)

这就是您在第二个示例中的做法,这就是您获得预期结果的原因。