
本文旨在深入解析 Hugging Face Transformers 库中,使用 GPT-2 等 Decoder-Only 模型计算交叉熵损失时,如何正确使用 masked label,并解释了常见的困惑。通过具体示例和代码,详细阐述了 target_ids 的构建方法,以及如何结合 ignore_index 来控制损失计算的范围,从而避免不必要的计算偏差,并提供了手动计算损失的替代方案。
在使用 Hugging Face Transformers 库进行自然语言处理任务时,尤其是使用 GPT-2 等 Decoder-Only 模型时,理解交叉熵损失的计算方式和 masked label 的作用至关重要。本文将深入探讨 target_ids 的正确构建方法,以及如何利用 ignore_index 来精确控制损失计算的范围,从而避免常见的错误和困惑。
Decoder-Only 模型、输入和目标
在 Hugging Face Transformers 库中,Decoder-Only 模型(如 GPT-2)主要依赖 input_ids、label_ids 和 attention_mask 进行训练。其中,input_ids 代表输入序列的 token IDs,label_ids 代表目标序列的 token IDs,而 attention_mask 用于指示哪些 token 应该被模型关注。
假设我们有一个输入 “The answer is:”,我们希望模型学习回答 “42”。将这个句子转化为 token IDs,假设 “The answer is: 42” 对应的 IDs 是 [464, 3280, 318, 25, 5433](其中 “:” 是 25,” 42″ 是 5433)。
为了让模型学习预测 “42”,我们需要设置 label_ids 为 [-100, -100, -100, -100, 5433]。这样,模型就不会学习到 “The answer” 后面应该跟着 “is:”,因为这些位置的损失被忽略了。
注意: Decoder-Only 模型要求输入和输出具有相同的形状。这与 Encoder-Decoder 模型不同,后者可以接受 “The answer is:” 作为输入,而 “42” 作为输出。
-100 是 torch.nn.CrossEntropyLoss 的默认 ignore_index。使用 “忽略” 比 “mask” 更准确,因为 “mask” 暗示模型看不到这些输入,或者原始输入被替换为特殊的 “” token。
理解问题的根源
原始问题中,代码 target_ids[:, :-seq_len] = -100 试图将 target_ids 中除了最后 seq_len 个元素之外的所有元素设置为 -100。然而,由于 target_ids 的长度为 seq_len,所以实际上没有任何元素被修改,导致损失计算结果不变。
迭代数据集时的正确方法
在使用滑动窗口迭代数据集时,masked label 的应用需要在不同的迭代步骤中进行调整。以下是一个示例:
第一次迭代:
max_length = 1024stride = 512end_loc = 1024input_ids = tokens[0 : 1024]target_ids = input_ids.clone()target_ids[:-1024] = -100 # 实际上没有修改任何元素assert torch.equal(target_ids, input_ids)trg_len = 1024prev_end_loc = 1024
在第一次迭代中,由于 target_ids[:-1024] 实际上等于 target_ids[:0],因此 target_ids 没有被修改,损失是基于所有 1024 个 token 计算的。
第二次及后续迭代:
begin_loc = 512end_loc = 1536trg_len = 1536 - 1024 # 512input_ids = tokens[512 : 1536] # 注意:tokens 512-1024 已经被模型看到过target_ids = tokens[512 : 1536].clone()target_ids[:-512] = -100 # 将已经见过的 token 对应的 label 设置为 -100
从第二次迭代开始,target_ids 的前 512 个元素(对应于模型已经见过的 token)被设置为 -100,损失仅基于后 512 个 token 计算。
手动计算损失
如果需要更精细地控制损失计算过程,可以直接从模型获取 logits,然后手动计算交叉熵损失。
from torch.nn import CrossEntropyLossoutputs = model(encodings.input_ids, labels=None)logits = outputs.logitslabels = target_ids.to(logits.device)# 调整 logits 和 labels 的形状,使其匹配shift_logits = logits[..., :-1, :].contiguous()shift_labels = labels[..., 1:].contiguous()# 计算损失loss_fct = CrossEntropyLoss(reduction='mean')loss = loss_fct(shift_logits.view(-1, model.config.vocab_size), shift_labels.view(-1))print(loss.item())
这段代码首先从模型获取 logits,然后将 logits 和 labels 的形状进行调整,使其能够匹配。最后,使用 CrossEntropyLoss 计算损失。
总结:
理解 Decoder-Only 模型中 target_ids 的构建方式,以及如何利用 ignore_index 来控制损失计算的范围,是使用 Hugging Face Transformers 库进行自然语言处理任务的关键。通过正确设置 target_ids,可以避免不必要的计算偏差,并提高模型的训练效果。
以上就是理解 Transformers 中的交叉熵损失及 Masked Label 问题的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1374744.html
微信扫一扫
支付宝扫一扫