23

我正在尝试在 PyTorch 中编写一个用于二进制分类的神经网络,但我对损失函数感到困惑。

我看到 BCELoss 是一个专门针对二进制分类的常用函数。我还看到 N 个可能类别的 N 个输出的输出层是一般分类的标准。但是,对于二元分类,它似乎可以是 1 个或 2 个输出。

那么,我应该有 2 个输出(每个标签 1 个),然后将我的 0/1 训练标签转换为 [1,0] 和 [0,1] 数组,还是使用类似 sigmoid 的东西作为单变量输出?

以下是相关的代码片段,您可以看到:

self.outputs = nn.Linear(NETWORK_WIDTH, 2) # 1 or 2 dimensions?


def forward(self, x):
  # other layers omitted
  x = self.outputs(x)           
  return F.log_softmax(x)  # <<< softmax over multiple vars, sigmoid over one, or other?

criterion = nn.BCELoss() # <<< Is this the right function?

net_out = net(data)
loss = criterion(net_out, target) # <<< Should target be an integer label or 1-hot vector?

提前致谢。

4

2 回答 2

52

对于二进制输出,您可以使用1 个输出单元,因此:

self.outputs = nn.Linear(NETWORK_WIDTH, 1)

然后您使用sigmoid激活将输出单元的值映射到01 之间的范围(当然您也需要以这种方式排列训练数据)

def forward(self, x):
    # other layers omitted
    x = self.outputs(x)           
    return torch.sigmoid(x)  

最后你可以使用torch.nn.BCELoss

criterion = nn.BCELoss()

net_out = net(data)
loss = criterion(net_out, target)

这应该适合你。

你也可以使用torch.nn.BCEWithLogitsLoss,这个损失函数已经包含了这个sigmoid函数,所以你可以把它放在你的前锋中。

如果您想使用2 个输出单元,这也是可能的。但是你需要使用torch.nn.CrossEntropyLoss而不是BCELoss. Softmax激活已包含在此损失函数中。


编辑:我只想强调这样做有真正的区别。与使用 1 个输出单元相比,使用2个输出单元的权重是使用1 个输出单元的两倍。所以这两种选择并不等价。

于 2018-12-05T09:14:50.087 回答
-1

一些理论加起来:

对于二元分类(例如 0 类和 1 类),网络应该只有 1 个输出单元。它的输出将为 1(对于 1 类存在或 0 类不存在)和 0(对于 1 类不存在或 0 类存在)。

对于损失计算,您应该首先将其通过 sigmoid,然后通过 BinaryCrossEntropy (BCE)。Sigmoid 将网络的输出转换为概率(介于 0 和 1 之间),然后 BCE 最大化所需输出的可能性。

于 2020-04-24T16:49:24.260 回答