多标签图像分类需用二值向量标签、binary_crossentropy损失、sigmoid输出及多标签专用评估指标。标签为shape=(batch_size, num_classes)的0/1张量,损失函数须为binary_crossentropy且输出层用sigmoid,评估宜用Hamming loss、subset accuracy和macro-F1。

多标签图像分类和单标签不同,一张图可能同时属于多个类别(比如“猫”“室内”“白天”),模型输出不再是单一概率分布,而是每个标签独立的置信度。关键不在换模型,而在数据准备、损失函数、评估方式和预测逻辑这四点上。
标签格式必须是二值向量,不是整数索引
单标签用 [0, 0, 1, 0] 表示第3类;多标签则用 [1, 0, 1, 1] 表示同时属于第0、第2、第3类。输入模型前,标签要转成 shape=(batch_size, num_classes) 的 float32 张量,值只能是 0 或 1。
- 用 sklearn.preprocessing.MultiLabelBinarizer 处理原始标签列表(如 [[‘cat’,’indoor’], [‘dog’,’outdoor’]])最稳妥
- 别用 to_categorical —— 它只适合单标签,会把多标签错误展开成稀疏独热码
- 验证时打印几个样本的 label.sum(axis=1),确保结果可以大于 1(说明允许多个 1)
损失函数要用 binary_crossentropy,不是 categorical_crossentropy
因为每个标签是独立的二分类任务,不是互斥的多选一。keras 中直接指定 loss=’binary_crossentropy’ 即可,但要注意:
- 最后一层激活必须是 sigmoid(输出 0~1 概率),不能用 softmax
- 如果手动写 loss,确保用 tf.keras.losses.BinaryCrossentropy(from_logits=False)
- 别在标签里做归一化或除以总和——那会破坏二值语义
预测后需设定统一阈值,再按需调整
模型输出是每个类的概率值(如 [0.82, 0.15, 0.93, 0.67]),需转成 0/1 才能算准确率。常用做法是:
立即学习“Python免费学习笔记(深入)”;
- 初始统一用 threshold=0.5:大于即判定存在
- 若某类样本极少(如“金毛犬”只占 0.3%),可单独调低该类阈值(用 per-class threshold)
- 更稳的方式是用 validation set 跑 grid search,在 F1-score 或 hamming loss 上找最优全局阈值
评估指标不能只看 accuracy,得用多标签专用指标
accuracy 在多标签中意义不大(全错一个也算整体错),推荐组合使用:
- Hamming loss:错误标签占总标签数的比例,越低越好(sklearn.metrics.hamming_loss)
- Exact match ratio (subset accuracy):整张图所有标签全对才算对,非常严格(sklearn.metrics.accuracy_score,需加 normalize=True)
- Per-class F1:分别算每个类的 precision/recall/F1,再 macro 平均,能看出长尾类表现
基本上就这些。不复杂但容易忽略——尤其标签格式和损失函数配错,模型会训得“看起来收敛”实则学不会多标签逻辑。