多标签时间序列任务中CrossEntropyLoss使用问题咨询
多标签时间序列CrossEntropyLoss使用问题解答
你的实现存在3处核心错误,是导致损失值异常、模型无法收敛的直接原因:
- 损失函数选型错误:PyTorch原生
CrossEntropyLoss仅适用于单标签多分类场景,要求每个样本(此处单个时间步为一个计算样本)只能归属一个类别;你的需求是多标签分类(每个时间步可同时归属多个类别),该场景下每个类别是独立二分类任务,应使用BCEWithLogitsLoss计算损失。 - 标签维度匹配逻辑错误:针对3维时序输入,
F.cross_entropy要求输入形状为[batch_size, num_classes, time_steps]时,对应标签形状必须为[batch_size, time_steps](每个位置存储对应时间步的类别索引,单标签场景),不存在单独的类别维度。你使用view强制把形状为[batch_size, time_steps, classes]的标签转为[batch_size, classes, time_steps],仅会按内存顺序重排数据,不会调整维度对应关系,直接导致时间步、类别与标签的映射完全错位,计算出的损失没有实际意义。如果需要调整维度顺序,必须使用permute(0,2,1)做维度转置,而非view。 - 标签值不合法:示例中你用
torch.randn生成标签,输出为符合正态分布的连续值,包含负数,既不符合单标签场景下类别索引为非负整数的要求,也不符合软标签场景下值在[0,1]区间、类别和为1的概率分布要求,本身就是非法的输入值。
正确实现参考
多标签分类场景(匹配你的需求:每个时间步可同时输出多个类别置信度)
多标签场景下使用BCEWithLogitsLoss,该算子内置sigmoid操作,数值稳定性优于手动计算sigmoid后接BCELoss:
import torch import torch.nn.functional as F batch_size = 256 time_steps = 224 classes = 16 # 模型输出形状符合要求:[batch_size, 类别数, 时间步] y_est = torch.randn((batch_size, classes, time_steps)) # 多标签标签为0/1值,形状与模型输出完全对齐,每个位置代表该时间步是否属于对应类别 y_true = torch.randint(0, 2, size=(batch_size, classes, time_steps)).float() loss = F.binary_cross_entropy_with_logits(y_est, y_true)
单标签多分类场景(每个时间步仅归属1个类别)
如果实际是单标签任务,才使用CrossEntropyLoss,注意标签不需要保留类别维度,直接存储类别索引即可:
# 单标签标签形状:[batch_size, 时间步],每个值为0~classes-1的类别整数索引 y_true_single_label = torch.randint(0, classes, size=(batch_size, time_steps)) loss_ce = F.cross_entropy(y_est, y_true_single_label)
内容的提问来源于stack exchange,提问作者papillon
相关产品推荐
相关产品推荐

