在 PyTorch 中使用 KL 散度的哪种方法是正确的?如果分布为零怎么办?

问题描述 投票:0回答:1

我正在尝试将分布

p
拟合到具有
KL 散度
的分布 q

import torch

p = torch.Tensor([0.1, 0.2, 0.7])
q = torch.Tensor([0.333, 0.334, 0.333])

所以我自己计算kl散度:

def kl_div(P, Q):
    return (P * (P / Q).log()).sum()

kl_div(p, q)

结果是

tensor(0.2972)

然后我发现PyTorch已经实现了

torch.nn.functional.kl_div
功能。

我认为

input
应该是网络的输出,
target
是一个常数。
所以我将
p
视为
input
,将
q
视为
target

但是

的结果
torch.nn.functional.kl_div(p.log(), q, reduction='sum')  # tensor(0.3245)

和我不一样。

这个得到的结果和我一样。

torch.nn.functional.kl_div(q.log(), p, reduction='sum')   # tensor(0.2972)

所以我真的很想知道出了什么问题?
我对kl散度的理解有问题吗?
或者我填错了

torch.nn.functional.kl_div

的参数

还有一个问题:

如果我的分布为零怎么办?

比如

p = torch.Tensor([0., 0.3, 0.7])
q = torch.Tensor([0.333, 0.334, 0.333])

这种情况我还是需要计算kl散度。

deep-learning pytorch
1个回答
0
投票

KL 散度不对称。

KL(P, Q) != KL(Q, P)

逐点 KL 散度定义为

y_{true} * log(y_{true}/y_{pred})

接下来,你的功能:

def kl_div(P, Q):
    return (P * (P / Q).log()).sum()

P
视为真实分布。从你的问题来看,听起来你将
P
视为预测分布,将
Q
视为真实分布,因此你的功能相对于你的函数发生了翻转。

您可能会感到困惑,因为数学符号

KL(P||Q)
P
定义为观测分布,将
Q
定义为“模型”分布,而 ML 上下文使用
P
表示您正在训练的模型的输出和
Q
表示数据集中的真实观测结果。

对于第二个问题,当其中一个值为零时,KL 散度未定义。这是该指标的定义。如果 P(i) = 0 且 Q(i) > 0,这意味着

P
表示事件
i
是不可能的,而
Q
表示它是可能的 - 对于这种差异没有任何衡量标准。

您可以通过在您的值中添加一个小 eps 来捏造它,即

torch.nn.functional.kl_div((p+1e-8).log(), q, reduction='sum')
。但是,如果您的用例经常出现 0 值,您应该考虑不同的指标。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.