Keras - 带权重的多标签分类



我正在尝试对一些每个样本有多个标签的 CXR 图像进行分类。据我所知,我必须放置一个具有sigmoid激活的致密层,并使用二进制交叉熵作为我的损失函数。问题是存在很大的阶级不平衡(正常比异常多得多(。我很好奇这是我到目前为止的模型:

from keras_applications.resnet_v2 import ResNet50V2
from keras.layers import GlobalAveragePooling2D, Dense
from keras import Sequential
ResNet = Sequential()
ResNet.add(ResNet50V2(input_shape=shape, include_top=False, weights=None,backend=keras.backend,
layers=keras.layers,
models=keras.models,
utils=keras.utils))
ResNet.add(GlobalAveragePooling2D(name='avg_pool'))
ResNet.add(Dense(len(label_counts), activation='sigmoid', name='Final_output'))

正如我们所看到的,我正在使用 sigmoid 来获取输出,但我对如何实现权重有点困惑。我想我需要使用使用 BCE(use_logits = true( 的自定义损失函数。像这样:

xent = tf.losses.BinaryCrossEntropy(
from_logits=True,
reduction=tf.keras.losses.Reduction.NONE)
loss = tf.reduce_mean(xent(targets, pred) * weights))

所以它将输出视为 logits,但我不确定的是最终输出的激活。我是通过激活 sigmoid 来保留它,还是使用线性激活(未激活(?我假设我们保留 sigmoid,只是将其视为 logit,但我不确定 pytorches"torch.nn.BCEWithLogitsLoss"包含一个 sigmoid 层

编辑:发现这个:https://www.reddit.com/r/tensorflow/comments/dflsgv/binary_cross_entropy_with_from_logits_true/

根据:pgaleone

from_logits=True 表示损失函数期望线性张量 (网络的输出层没有任何激活功能,但 标识(,因此您必须删除 sigmoid,因为它将是 损失函数本身将 softmax 应用于您的网络输出,以及 然后计算交叉熵

您实际上不希望在多标签分类中使用from_logits

来自文档 [1]:

logits:每个标签的激活,通常是线性输出。这些活化能被解释为非归一化对数概率。

所以你说得对,当激活函数设置为 True 时,你不想使用激活函数。

但是,文档还说

警告:此操作需要未缩放的 logit,因为它在内部对 logit 执行 softmax 以提高效率。不要使用 softmax 的输出调用此操作,因为它会产生不正确的结果

Softmax根据定义优化一个类。这就是softmax的设计方式。由于您正在执行多标签分类,因此您应该使用 sigmoid,正如您自己提到的。

这意味着如果你想使用sigmoid,你不能使用from_logits因为它会在sigmoid之后应用softmax,这通常不是你想要的。

解决方案是删除此行:

from_logits=True,

[1] https://www.tensorflow.org/api_docs/python/tf/nn/softmax_cross_entropy_with_logits?version=stable

最新更新