You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TensorFlow多正分类损失计算:标签编码与损失函数选择

多标签分类的One-Hot编码与损失函数选择

一、创建对应的One-Hot编码

首先要明确:你给出的[0, 1, 0, 0, 1, 0]其实已经是多标签场景下的标准One-Hot编码了——它的长度等于总类别数(这里是6个类别,索引0到5),每个位置的1表示样本属于该类别,0表示不属于。

如果你的原始标签是类别集合(比如[1, 4],对应你例子里的类别),要转换成这种向量,在TensorFlow里可以这样实现:

import tensorflow as tf

# 总类别数
num_classes = 6
# 原始类别列表(和你例子对应,类别编号是1-based)
original_labels = [1, 4]

# 初始化全0向量
one_hot_label = tf.zeros(num_classes, dtype=tf.float32)
# 更新对应类别位置为1
one_hot_label = tf.tensor_scatter_nd_update(
    one_hot_label,
    indices=[[idx] for idx in original_labels],
    updates=[1.0]*len(original_labels)
)

print(one_hot_label.numpy())  # 输出: [0. 1. 0. 0. 1. 0.]

如果是批量处理多个样本,也可以用更简洁的方式:

# 批量原始标签(每个样本对应一组类别)
batch_original_labels = [[1,4], [0,5], [2,3]]
# 生成批量多标签One-Hot向量
batch_one_hot = tf.reduce_max(tf.one_hot(batch_original_labels, num_classes), axis=1)

二、损失函数的选择

这种样本可同时属于多个类别的多标签场景,最适合的损失函数是Sigmoid Cross Entropy,原因和另外两种的对比如下:

  • Sigmoid Cross Entropy:对每个类别输出节点独立做二分类(判断“属于/不属于”该类别),用Sigmoid激活将每个节点输出映射到0-1区间,损失是所有类别节点交叉熵的总和。完美适配多标签的非互斥特性,在TensorFlow中可以用tf.keras.losses.BinaryCrossentropy()(多标签本质是多个二分类任务,两者等价),或者底层的tf.nn.sigmoid_cross_entropy_with_logits()。

  • Softmax Cross Entropy:会强制所有类别输出的和为1,隐含“样本只能属于一个类别”的互斥假设。用它的话,模型会被迫压制类别1和4的概率,完全不符合你的多标签需求。

  • Sparse Softmax Cross Entropy:只是Softmax Cross Entropy的简化版,针对整数形式的单类别标签(比如用1代替[0,1,0,0,0,0]),同样是互斥分类场景,不适用。

举个实际使用的代码示例:

# 模型输出的logits(未经过激活的原始输出),shape为(批量大小, 类别数)
logits = tf.random.normal((3, 6))
# 批量多标签One-Hot标签,shape为(批量大小, 类别数)
labels = tf.constant([[0,1,0,0,1,0], [1,0,0,0,0,1], [0,0,1,1,0,0]], dtype=tf.float32)

# 使用Sigmoid交叉熵损失(from_logits=True表示输入是未激活的logits)
loss_fn = tf.keras.losses.BinaryCrossentropy(from_logits=True)
loss = loss_fn(labels, logits)
print(loss.numpy())

内容的提问来源于stack exchange,提问作者rodrigo-silveira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:38:14