Python Keras多类多标签图像分类:处理独立标签和从属标签的混合;非二进制输出

Python Keras多类多标签图像分类:处理独立标签和从属标签的混合;非二进制输出,python,keras,conv-neural-network,multilabel-classification,multiclass-classification,Python,Keras,Conv Neural Network,Multilabel Classification,Multiclass Classification,我正在尝试从Keras培训一个经过预培训的VGG16模型,用于多类多标签分类任务。这些图像来自NIH的胸部X光8数据集。该数据集有14个标签(14种疾病)和一个“无发现”标签 我知道对于独立的标签,比如14种疾病,我应该使用sigmoid激活+二进制交叉熵损失函数;对于依赖标签,我应该使用softmax+分类交叉熵 然而,在我总共15个标签中,有14个是独立的,但一个“未发现”与其余14个在技术上是相关的-->没有发现和患有疾病的概率加起来应该是1,但患有何种疾病的概率应该独立给出。那么我应该使

我正在尝试从Keras培训一个经过预培训的VGG16模型,用于多类多标签分类任务。这些图像来自NIH的胸部X光8数据集。该数据集有14个标签(14种疾病)和一个“无发现”标签

我知道对于独立的标签,比如14种疾病,我应该使用sigmoid激活+二进制交叉熵损失函数;对于依赖标签,我应该使用softmax+分类交叉熵

然而,在我总共15个标签中,有14个是独立的,但一个“未发现”与其余14个在技术上是相关的-->没有发现和患有疾病的概率加起来应该是1,但患有何种疾病的概率应该独立给出。那么我应该使用什么样的损失呢

此外,我的输出是一个浮点(概率)列表,每列都是一个标签

y_true:
[[0. 0. 0. ... 0. 0. 1.]
 [0. 0. 0. ... 0. 0. 1.]
 [0. 0. 1. ... 0. 0. 0.]
 ...
 [0. 0. 0. ... 0. 0. 1.]
 [0. 0. 0. ... 0. 0. 0.]
 [0. 0. 0. ... 0. 0. 1.]]

y_predict:
[[0.1749 0.0673 0.1046 ... 0.     0.     0.112 ]
 [0.     0.1067 0.2804 ... 0.     0.     0.722 ]
 [0.     0.     0.0686 ... 0.     0.     0.5373]
 ...
 [0.0571 0.0679 0.0815 ... 0.     0.     0.532 ]
 [0.0723 0.0555 0.2373 ... 0.     0.     0.4263]
 [0.0506 0.1305 0.4399 ... 0.     0.     0.2792]]
这样的结果使得使用
classification\u report()
函数无法评估我的模型。我正在考虑设置一个阈值,将其转换为二进制,但这将是更多的人为修改,而不是CNN预测,因为我必须选择一个阈值。所以我不确定我是否应该做一些硬代码的东西,或者是否有其他已经存在的方法来处理这种情况

我对CNN和分类很陌生,所以如果有人能指导我或给我任何提示,我将非常感激。谢谢大家!

主体代码如下:

vgg16_model = VGG16()
last_layer = vgg16_model.get_layer('fc2').output

#I am treating them all as independent labels
out = Dense(15, activation='sigmoid', name='output_layer')(last_layer)
custom_vgg16_model = Model(inputs=vgg16_model.input, outputs=out)

for layer in custom_vgg16_model.layers[:-1]:
layer.trainable = False

custom_vgg16_model.compile(Adam(learning_rate=0.00001), 
                           loss = "binary_crossentropy", 
                           metrics = ['accuracy'])   # metrics=accuracy gives me very good result, 
                                                     # but I suppose it is due to the large amount 
                                                     # of 0 label(not-this-disease prediction),
                                                     # therefore I am thinking to change it to 
                                                     # recall and precision as metrics. If you have
                                                     # any suggestion on this I'd also like to hear!

关于我的项目的一些更新,实际上我已经解决了这个问题中提到的大部分问题

首先,由于这是一个多类别多标签分类问题,我决定使用ROC-AUC分数,而不是精度或召回率作为评估指标。它的优点是不涉及阈值——AUC有点像阈值范围内性能的平均值。而且它只关注积极预测,因此它减少了数据集中大多数0的影响。在我的例子中,这可以更准确地预测模型的性能

对于输出类,我决定使用14个类而不是15个类——如果所有标签都是0,则表示“找不到”。然后我可以在我的输出层中愉快地使用sigmoid激活。尽管如此,由于我的数据集高度不平衡,我还是使用了焦点损失而不是二进制交叉熵


我仍然面临这个问题,因为我的ROC不好(非常接近y=x,有时低于y=x)。但我希望我的进步能给任何人一些启发。

我的项目的一些更新,我实际上已经解决了这个问题中提到的大部分问题

首先,由于这是一个多类别多标签分类问题,我决定使用ROC-AUC分数,而不是精度或召回率作为评估指标。它的优点是不涉及阈值——AUC有点像阈值范围内性能的平均值。而且它只关注积极预测,因此它减少了数据集中大多数0的影响。在我的例子中,这可以更准确地预测模型的性能

对于输出类,我决定使用14个类而不是15个类——如果所有标签都是0,则表示“找不到”。然后我可以在我的输出层中愉快地使用sigmoid激活。尽管如此,由于我的数据集高度不平衡,我还是使用了焦点损失而不是二进制交叉熵

我仍然面临这个问题,因为我的ROC不好(非常接近y=x,有时低于y=x)。但我希望我的进步能给任何发现这一点的人一些启发