PyTorch下Unlikelihood Training损失实现正确性技术问询
你的Unlikelihood Training损失实现不正确
你当前的代码完全不符合原论文的损失设计逻辑,核心问题如下:
- 输入语义混淆:原生NLLLoss接收的是
log_softmax输出的对数概率,取值范围是(-∞, 0],你代码里直接用1 - logs[i][c[i]]作为权重系数,计算出来的权重会大于1甚至出现异常值,完全不符合加权逻辑。 - 损失结构错误:原论文的非似然损失是标准NLL损失 + 独立非似然惩罚项的加权和,不是给目标token的NLL项乘一个系数。非似然项的作用是单独压低指定负样本token的生成概率,和目标token的似然计算是独立的两个部分。
- 负样本参数语义错误:你代码里的
c是单个token的形式,但原论文里每个位置需要惩罚的是一整个负样本token集合,非似然项需要对集合内所有token计算惩罚值再聚合,不是取单个token算权重。
原论文中token级非似然损失的核心逻辑为:总损失由两部分组成,第一部分是常规的负对数似然损失,第二部分是非似然惩罚项,对所有需要被规避的负样本token c计算$-log(1-p(c))$的均值,目标是让这些负样本的生成概率p(c)趋近于0,两部分通过权重系数α加权求和。
正确实现参考
import torch import torch.nn.functional as F def unlikelihood_loss(logits, targets, neg_token_mask, alpha=0.1): """ Args: logits: 模型原始输出logit,形状为 [batch_size, seq_len, vocab_size] targets: 真实标签token ID,形状为 [batch_size, seq_len] neg_token_mask: 负样本掩码,形状和logits一致,对应位置为1表示该位置的该token需要被惩罚 alpha: 非似然惩罚项的权重 """ log_probs = F.log_softmax(logits, dim=-1) probs = torch.exp(log_probs) # 计算标准NLL损失 nll_loss = F.nll_loss( log_probs.reshape(-1, log_probs.size(-1)), targets.reshape(-1), reduction="mean" ) # 计算非似然惩罚项,加1e-8避免log(0)的数值不稳定问题 ul_per_token = -torch.log(1 - probs + 1e-8) ul_loss = (ul_per_token * neg_token_mask).sum() / (neg_token_mask.sum() + 1e-8) return nll_loss + alpha * ul_loss
如果要实现论文中用于解决重复生成问题的序列级非似然损失,只需要在构造
neg_token_mask时,把每个位置之前已经出现过的token标记为负样本即可,损失计算逻辑不需要改动。
内容的提问来源于stack exchange,提问作者Minions
相关产品推荐
相关产品推荐

