
Make `argmax` in `post_process_semantic_segmentation` optional
快速结论:当用户需要获取语义分割模型的类别概率(shape [N, C, H, W])而非硬分割图(shape [N, H, W])时触发,例如计算 ROC AUC 指标或使用自定义分割损失函数。优先排查:在调用 post_process_semantic_segmentation 前,手动处理模型原始输出以避免被强制 argmax。
问题场景
用户在使用 Hugging Face Transformers 的语义分割模型(如 DETR、MaskFormer、Mask2Former、OneFormer 等)时,通过 post_process_semantic_segmentation 函数获取分割结果。当前该函数会强制对 logits/scores 执行 argmax,返回硬分割图(shape [N, H, W])。但在某些应用场景(如计算 ROC AUC 指标、实现 SMP 库中的自定义分割损失、使用 RankSEG 等后处理方法)中,用户需要获取类别概率(shape [N, C, H, W])而非最终分割图。
报错原文
# 没有直接的报错信息,核心问题是功能缺失
# 用户期望:从 post_process_semantic_segmentation 返回 [N, C, H, W] 的类别概率
# 当前行为:强制 argmax 后返回 [N, H, W] 的硬分割图
原因分析
可能原因:Transformers 的 post_process_semantic_segmentation 函数设计为一次性完成从模型原始输出到最终分割图的转换,内部包含对所有模型的通用后处理逻辑(包括对 DETR 的 class_queries_logits 和 masks_queries_logits 的组装、MaskFormer 的 mask 处理等),最后强制执行 argmax。对于需要中间类别概率表示的下游任务,这一设计过于刚性。
- 用户手动复制各模型(DETR、ConditionalDETR、MaskFormer、Mask2Former、OneFormer 等)的后处理代码进行改造,代码极度冗余。
- 不同模型的输出结构不同:有些模型输出
logits(可直接 softmax),而 DETR/MaskFormer 等输出class_queries_logits和mask_queries_logits,需要先通过 Einsum 组装为分类得分。 - 社区提交了 PR #37904 尝试添加
class_proba参数,但尚未合并。
环境排查
- Transformers 版本:低于 v4.49.0(2026年7月8日关闭 Issue 时的当前版本)。
- 模型类型:DETR(DetrForSegmentation)、ConditionalDETR(ConditionalDetrForSegmentation)、MaskFormer(MaskFormerForInstanceSegmentation)、Mask2Former(Mask2FormerForUniversalSegmentation)、OneFormer(OneFormerForUniversalSegmentation)、SegFormer(SegformerForSemanticSegmentation)等。
- Python 环境:需要 PyTorch 和 torchvision(对于模型推理)。
解决步骤
- 获取模型原始输出:直接调用模型的 forward,如
outputs = model(pixel_values),不通过 pipeline。 - 手动处理模型输出:根据模型类型编写自定义后处理函数,获取类别概率。参考 Issue 中提供的代码模式:
- 对于输出
logits的模型(如 SegFormer):probs = outputs.logits.softmax(dim=1) - 对于 DETR/ConditionalDETR:提取
class_queries_logits和masks_queries_logits,执行masks_classes = class_queries_logits.softmax(dim=-1)[..., :-1](注意处理 null class),masks_probs = masks_queries_logits.sigmoid(),然后用torch.einsum组装得分。 - 对于 MaskFormer/Mask2Former/OneFormer:提取
class_queries_logits和masks_queries_logits,类似 DETR 处理,但需注意模型特有的输出键(如masks_queries_logits在 Mask2Former 中为mask_embeddings)。
- 对于输出
- 可优先尝试:参考试验分支 leev1s/semantic-rankseg 中的实现(通过
_get_semantic_segmentation_probs方法获取概率)。probs = self._get_semantic_segmentation_probs(model_outputs)[0] - 等待官方功能:关注 PR #37904 或后续版本是否添加
class_proba参数。
验证方法
确认输出张量的形状为 [N, C, H, W],且每个像素的类别概率和为 1(softmax 后)。可以通过 probs.sum(dim=1).allclose(torch.ones_like(probs[:, 0, :, :])) 进行验证。



