Keras多标签分类中evaluate与手动计算准确率不一致问题
问题根源:Keras默认
accuracy与你手动计算的准确率定义完全不同 你遇到的这个差异其实非常常见,核心原因是Keras在多标签分类任务中使用的默认accuracy指标,和你用accuracy_score手动计算的准确率,根本不是同一个东西。
1. 两者的计算逻辑差异
- Keras的
accuracy(标签级准确率):当你用binary_crossentropy作为损失时,Keras的accuracy是逐标签计算的——它会统计所有样本的所有标签中,预测正确的标签占总标签数的比例。举个例子:如果一个样本有5个标签,你预测对了4个,那这个样本会给准确率贡献4/5=0.8;如果另一个样本5个标签全对,贡献1.0。最后把所有样本的这个值平均,就是Keras输出的0.94。 - 你手动计算的准确率(样本级准确率):
accuracy_score(y_final, output)统计的是完全预测正确的样本数占总样本数的比例——只有当一个样本的所有标签都和真实值完全一致时,这个样本才算“准确”。在多标签、类别不平衡的场景下,这个数值通常会低很多,就像你得到的0.35。
2. 为什么差异这么大?结合你的数据情况
你提到存在类别不平衡,部分类别出现频率更高。这意味着你的数据中,大部分标签是负样本(0)。Keras的标签级准确率会被大量正确预测的负标签拉高——比如100个标签里94个是负的,模型只要都预测成0,就能拿到94%的标签级准确率,但样本级准确率可能很低,因为很少有样本的所有标签(包括少数正标签)都能被预测正确。
而你的F1-micro=0.71,这个指标是基于所有标签的TP、FP、FN计算的,它更能反映模型在正标签上的表现,也和Keras的标签级准确率逻辑不同(F1关注的是正例的精准和召回,而标签级准确率包含了大量负例的正确预测)。
3. 解决办法:用自定义指标匹配你的计算逻辑
如果你想在Keras的evaluate中得到和accuracy_score一致的样本级准确率,可以自定义一个指标函数:
import tensorflow as tf from tensorflow.keras import backend as K def sample_level_accuracy(y_true, y_pred): # 先把预测值二值化,和你手动处理的逻辑一致 y_pred_bin = K.round(y_pred) # 判断每个样本的所有标签是否完全匹配 is_sample_correct = K.all(K.equal(y_true, y_pred_bin), axis=-1) # 转换为浮点型后计算平均值 return K.mean(K.cast(is_sample_correct, tf.float32))
然后修改模型编译的代码,用这个自定义指标替代默认的accuracy:
model.compile( optimizer=adam, loss='binary_crossentropy', metrics=[sample_level_accuracy, tf.keras.metrics.Precision(), tf.keras.metrics.Recall()] )
这样之后,model.evaluate返回的准确率就会和你手动用accuracy_score计算的结果一致了。另外,也可以直接把F1-score作为自定义指标加入,方便直接在训练过程中监控。
4. 额外提醒
在多标签分类任务中,默认的标签级准确率通常不是一个好的评估指标,因为它会被类别不平衡严重误导。更推荐使用F1-score(micro/macro/weighted)、Precision、Recall这些更能反映模型真实性能的指标。
内容的提问来源于stack exchange,提问作者Rami
相关产品推荐
相关产品推荐

