非独热多1标签下categorical crossentropy的替代损失函数咨询
针对多标签分类场景的损失函数选择
你遇到的问题本质是多标签分类任务(每个样本同时属于多个类别),而categorical_crossentropy是为单标签独热分类设计的——它假设每个样本只有一个类别,所有输出的概率和为1,显然不适合你的场景。下面是几个最适合的替代方案:
1. Binary Crossentropy(首选)
这是多标签分类的标准损失函数,完美匹配你的标签格式。它将每个输出神经元视为独立的二分类任务(判断该类别是否存在),计算每个标签位的交叉熵后取平均。
使用要点:
- 输出层必须使用
sigmoid激活函数(而不是softmax),这样每个输出节点的结果是0到1之间的概率值,独立于其他节点。 - Keras中直接指定损失即可:
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) - 你的标签格式(6个1,其余0的向量)完全符合这个损失的输入要求,无需修改标签。
2. Focal Loss(针对极度不平衡样本)
你的场景中正负样本比例极度悬殊(约7000:6),普通的binary crossentropy可能会让模型偏向于预测大多数的0类别。Focal Loss通过降低易分类样本(大量的负样本)的权重,让模型更关注难分类的正样本。
自定义实现示例(Keras):
import tensorflow as tf from tensorflow.keras import backend as K def focal_loss(gamma=2., alpha=0.25): def focal_loss_fixed(y_true, y_pred): pt_1 = tf.where(tf.equal(y_true, 1), y_pred, tf.ones_like(y_pred)) pt_0 = tf.where(tf.equal(y_true, 0), y_pred, tf.zeros_like(y_pred)) return -K.mean(alpha * K.pow(1. - pt_1, gamma) * K.log(pt_1)) - K.mean((1 - alpha) * K.pow(pt_0, gamma) * K.log(1. - pt_0)) return focal_loss_fixed # 使用时 model.compile(optimizer='adam', loss=focal_loss(gamma=2, alpha=0.25), metrics=['accuracy'])
3. Categorical Hinge Loss
适合需要严格区分正负类的场景,它的目标是让正类的输出显著高于负类。不过在你的样本极度不平衡场景下,效果可能不如前两者,但可以作为备选尝试:
model.compile(optimizer='adam', loss='categorical_hinge', metrics=['accuracy'])
关键提醒:
无论选择哪种损失,都不要用softmax作为输出层激活——softmax会强制所有输出的和为1,这和多标签场景中多个类别可以同时存在的逻辑矛盾。一定要用sigmoid激活每个输出节点。
内容的提问来源于stack exchange,提问作者Noltibus
相关产品推荐
相关产品推荐

