简单而简短的问题。我有一个执行图像分割的网络(Unet)。我希望对数作为输出输入到交叉熵损失中(使用 pytorch)。目前,我的最后一层如下所示:
class Logits(nn.Sequential):
def __init__(self,
in_channels,
n_class
):
super(Logits, self).__init__()
# fully connected layer outputting the prediction layers for each of my classes
self.conv = self.add_module('conv_out',
nn.Conv2d(in_channels,
n_class,
kernel_size = 1
)
)
self.activ = self.add_module('sigmoid_out',
nn.Sigmoid()
)
在这里使用 sigmoid 激活功能是否正确?这能给我对数吗?
当人们谈论"logits"时,他们通常指的是"原始"n_class
维输出向量。对于多类分类(n_class
> 2),您希望将原始"logits"的n_class
维向量转换为n_class
-dim概率向量.
也就是说,您希望对所有n_class
条目进行prob_i >= 0
prob = f(logits)
,并且sum(prob)=1
.
以可微分的方式执行此操作的最直接方法是使用 Softmax 函数:
prob_i = softmax(logits) = exp(logits_i) / sum_j exp(logits_j)
很容易看出,softmax
的输出确实是一个n_class
暗的概率向量(我把它留给你作为一个简短的练习)。
顺便说一句,这就是为什么原始预测被称为"logits",因为它们是输出预测概率的"日志"。
现在,习惯上不会在分类网络之上显式计算softmax,而是将其计算推迟到损失函数,例如nn.CrossEntropyLoss
内部计算softmax,并需要原始对数作为输入,而不是归一化概率。这样做主要是为了数值稳定性。
因此,如果您正在使用nn.CrossEntropyLoss
训练多类分类网络,则完全不需要担心最终激活,只需从最终的卷积/线性层输出原始对数.
最重要的是,不要使用nn.Sigmoid()
激活,因为它往往具有饱和梯度并且会弄乱您的训练。
据我了解,您正在处理多标签分类任务,其中单个输入可以有多个标签,因此您使用nn.Sigmoid
(与多类分类的nn.Softmax
相比)。
有一个结合nn.Sigmoid
和nn.BCELoss
的损失函数:nn.BCEWithLogitsLoss
。因此,您将有一个对数向量作为输入,其长度是类的数量。而且,目标也将具有相同的形状:作为多热编码,活动类具有1
s。