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

PyTorch实现论文「并发」Softmax函数遇输出恒值异常问题

并发Softmax实现异常的原因与修正方案

异常根因

你的代码逻辑和对函数的理解存在两处偏差,共同导致了第一个输出恒为0.5的结果:

  • 计算循环错误纳入了无需计算的负样本类
  • 求和项重复计入了当前类的自身指数值

详细问题拆解

  1. 固定0.5输出的形成逻辑
    以你给出的样例y=[0,1,1]为例,数组中仅类0为负样本,其余两类为正样本。你写的sum_over_j的计算规则是累加所有满足1-y[j]=1的指数化logit值,因此无论i循环到哪个类,sum_over_j的计算结果始终等于exp(vec[0])。
    当循环到i=0时,当前类的zi=exp(vec[0]),代入计算公式得到out = exp(vec[0])/(exp(vec[0]) + exp(vec[0])) = 0.5。这就是无论修改vec的第一个元素为任何值,输出都固定为0.5的直接原因。
  2. 函数设计的认知偏差
    你简化后的并发Softmax,核心作用是为每个正样本标签计算独立的归一化得分,不需要对负样本类计算输出。按照你省略rij项后的简化定义,每个正样本类i的输出计算规则为:当前类的指数化logit,除以「当前类的指数化logit + 所有负样本类的指数化logit之和」。负样本类本身不属于需要输出得分的对象,纳入循环计算本身就不符合函数的设计逻辑。

修正后的循环实现

import torch

y = [0, 1, 1]
vec = torch.tensor([0.2, 0.9, 0.7])

def concurrent_softmax(vec, y):
    # 提前累加所有负样本类的指数化logit,避免循环内重复计算
    neg_logit_sum = sum(torch.exp(vec[j]) for j in range(len(y)) if y[j] == 0)
    # 仅遍历正样本类计算输出
    for i in range(len(vec)):
        if y[i] == 0:
            continue
        current_exp = torch.exp(vec[i])
        yield current_exp / (neg_logit_sum + current_exp)

for result in concurrent_softmax(vec, y):
    print(result)

修正后的代码输出会随vec的取值动态变化,不再出现固定值异常,符合函数的预期效果。

内容的提问来源于stack exchange,提问作者Steve Ahlswede

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.29 05:15:03