python PyTorch的BCEWithLogitsLoss类是如何实现的?

h6my8fg2  于 2022-11-21  发布在  Python
关注(0)|答案(3)|浏览(416)

根据the PyTorch documentation,类BCEWithLogitsLoss()的优点是可以使用
数值稳定性对数和指数技巧
如果我们使用类BCEWithLogitsLoss(),并将参数reduction设置为None,则它们有一个公式:

我现在简化的条件,并获得一些行计算后:

我很好奇,看看这是否是源代码如何做到这一点的方式,但我找不到它..他们唯一的代码是这样的:
Code for BCEWithLogitsLoss

wpx232ag

wpx232ag1#

nn.BCEWithLogitsLoss实际上只是S形函数内部的交叉熵损失。如果模型的输出层未使用S形函数 Package ,则可以使用它。通常用于单个输出层神经元的原始输出。
简单地说,你的模型输出pred将是一个原始值。为了得到概率,你将不得不使用torch.sigmoid(pred)。(为了得到实际的类标签,你需要torch.round(torch.sigmoid(pred))。)然而,当你使用nn.BCEWithLogitsLoss时,你不需要做任何类似的事情(例如,取sigmoid)。这里你只需要做以下事情-

criterion = nn.BCEWithLogitsLoss()
loss = criterion(pred, target) # pred is just raw nn output

因此,对于实现部分,criterion接受两个 Torch Tensor-一个是原始nn输出,另一个是真实的类标签,然后使用S形对第一个进行 Package -对于Tensor中的每个元素,然后计算每对的交叉熵损失(-(target*log(sigmoid(pred))),并将其减少到平均值。

fcipmucu

fcipmucu2#

所有的pytorch函数代码都是用C++实现的。实现的源代码在这里。
pytorch实现将BCEWithLogitsLoss计算为

其中t_n就是-relu(x)。这里使用t_n基本上是一种避免取正值指数的聪明方法(从而避免溢出)。通过将t_n代入l_n,可以使这一点变得更清楚,这将产生以下等效表达式

hyrbngr7

hyrbngr73#

根据C++的实现他们在最后使用了这个函数:

static inline at::Tensor apply_loss_reduction(const at::Tensor& unreduced, int64_t reduction) {
    if (reduction == at::Reduction::Mean) {
      return unreduced.mean();
    } else if (reduction == at::Reduction::Sum) {
      return unreduced.sum();
    }
    return unreduced;
  }

正如您在documentation中所看到的,默认情况下,它们使用均值缩减。

相关问题