我正在尝试对一些每个样本有多个标签的 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