有没有办法优化许多多元样本的伯努利对数似然计算?

Is there a way to optimize the calculation of Bernoulli Log-Likelihoods for many multivariate samples?

我目前有两个 Torch 张量,px,它们的形状都是 (batch_size, input_size)

我想计算给定数据的伯努利对数似然,return 大小为 (batch_size)

的张量

这是我想做的一个例子: 我有伯努利随机变量的对数似然公式:

\sum_i^d x_{i} ln(p_i) + (1-x_i) ln (1-p_i)

假设我有 p 张量: [[0.6 0.4 0], [0.33 0.34 0.33]] 并说我有基于这些概率的二进制输入的 x 张量:

[[1 1 0], [0 1 1]]

我想计算每个样本的对数似然,这将导致:

[[ln(0.6)+ln(0.4)], [ln(0.67)+ln(0.34)+ln(0.33)]]

是否可以在不使用 for 循环的情况下进行此计算? 我知道我可以使用 torch.sum(axis=1) 在日志之间进行最终求和,但是是否可以在不使用 for 循环的情况下进行伯努利对数似然计算?或者最多使用 1 个 for 循环?我正在尝试尽可能地矢量化此操作。我发誓我们以前可以使用 LaTeX 来做方程式,是不是有什么变化或者是另一个网站?

虽然不是一个好的做法,但您可以直接在张量上使用公式,如下所示(有效,因为这些是元素明智的操作):

import torch
p = torch.tensor([
    [0.6, 0.4, 0],
    [0.33, 0.34, 0.33]
])

x = torch.tensor([
    [1., 1, 0],
    [0, 1, 1]
])

eps = 1e-8
bll1 = (x * torch.log(p+eps) + (1-x) * torch.log(1-p+eps)).sum(axis=1)
print(bll1)
#tensor([-1.4271162748, -2.5879497528])

注意为了避免log(0)错误,我在里面引入了一个非常小的常量eps

更好的方法是在 pytorch.

中的 nn 模块中使用 BCELoss
import torch.nn as nn
bce = nn.BCELoss(reduction='none')
bll2 = -bce(p, x).sum(axis=1)
print(bll2)
#tensor([-1.4271162748, -2.5879497528])

由于 pytorch 将 BCE 计算为 损失 ,它会在您的公式前加上一个负号。属性 reduction='none' 表示我不希望以任何方式减少整个批次的计算损失 (averaged/summed)。这是明智的使用,因为我们不需要手动处理数值稳定性和错误处理(例如在上面添加 eps。)

您确实可以验证这两个解决方案实际上 return 相同的张量(达到公差):

torch.allclose(bll1, bll2)
# True

或张量(不对每一行求和):

torch.allclose((x * torch.log(p+eps) + (1-x) * torch.log(1-p+eps)), -bce(p, x))
# True

随时要求进一步说明。