理解 Transformers 中的交叉熵损失与 Masked Label 问题

心靈之曲
发布: 2025-09-30 19:58:01
原创
904人浏览过

理解 transformers 中的交叉熵损失与 masked label 问题

本文旨在深入解析 Hugging Face Transformers 库中,针对 Decoder-Only 模型(如 GPT-2)计算交叉熵损失时,如何正确使用 labels 参数进行 Masked Label 的设置。通过具体示例和代码,详细解释了 target_ids 的构造方式,以及如何避免常见的错误,并提供了自定义计算损失的方案。

在使用 Hugging Face Transformers 库训练或评估 Decoder-Only 模型(例如 GPT-2)时,交叉熵损失是一个核心概念。labels 参数在计算损失中扮演着关键角色,尤其是在需要对部分 token 进行 Masking 的场景下。本文将深入探讨 labels 参数的使用,以及如何避免常见的错误配置。

Decoder-Only 模型中的输入与目标

在 Hugging Face 中,Decoder-Only 模型通常需要 input_ids 和 labels 作为输入。attention_mask 虽然重要,但在此处不重点讨论。核心思想是,对于 Decoder-Only 模型,输入和目标需要具有相同的形状。

例如,假设输入是 "The answer is:",我们希望模型学习到 "42" 作为答案。那么,完整的文本序列为 "The answer is: 42",其对应的 token IDs 可能为 [464, 3280, 318, 25, 5433] (其中 ":" 对应 25," 42" 对应 5433)。

为了让模型学习预测 "42",我们需要设置 labels 为 [-100, -100, -100, -100, 5433]。这里的 -100 是 torch.nn.CrossEntropyLoss 的 ignore_index,意味着这些位置的损失将被忽略。换句话说,模型不会学习 "The answer" 后面跟着 "is:" 这样的关系,而是专注于学习在给定 "The answer is:" 的前提下,应该预测 "42"。

注意: Decoder-Only 模型要求输入和输出具有相同的形状。这与 Encoder-Decoder 模型不同,后者可以有 "The answer is:" 作为输入,而 "42" 作为输出。

常见错误与正确做法

在问题中,作者尝试使用 target_ids[:, :-seq_len] = -100 来 Masking labels,但结果并未如预期。问题在于,当 seq_len 等于输入序列的长度时,这条语句实际上没有修改任何元素。

正确的做法是,根据实际需求,有选择性地将 target_ids 中的某些位置设置为 -100。例如,在迭代处理文本数据时,可能需要忽略之前已经见过的 token,而只计算当前新 token 的损失。

AI建筑知识问答
AI建筑知识问答

用人工智能ChatGPT帮你解答所有建筑问题

AI建筑知识问答 22
查看详情 AI建筑知识问答

以下是一个示例,展示了如何在迭代过程中正确地 Masking labels:

max_length = 1024
stride = 512

# 假设 tokens 是一个包含完整文本 token IDs 的列表
# 第一次迭代
end_loc = max_length
input_ids = tokens[0:end_loc]
target_ids = input_ids.clone()
# 第一次迭代时,不需要 Masking,因此 target_ids 与 input_ids 相同

# 第二次及后续迭代
begin_loc = stride
end_loc = begin_loc + max_length
input_ids = tokens[begin_loc:end_loc]
target_ids = input_ids.clone()
target_ids[:max_length - stride] = -100  # Masking 之前已经见过的 token
登录后复制

在这个例子中,每次迭代都会处理长度为 max_length 的文本片段,但只有最后 stride 个 token 的损失会被计算,之前的 token 通过 Masking 被忽略。

自定义计算损失

如果不想依赖模型内部的损失计算方式,也可以手动计算交叉熵损失。这种方法提供了更大的灵活性,可以更好地控制损失计算的细节。

以下是一个自定义计算损失的示例代码:

from transformers import GPT2LMHeadModel, GPT2TokenizerFast
import torch
from torch.nn import CrossEntropyLoss

model_id = "gpt2-large"
model = GPT2LMHeadModel.from_pretrained(model_id)
tokenizer = GPT2TokenizerFast.from_pretrained(model_id)

encodings = tokenizer("She felt his demeanor was sweet and endearing.", return_tensors="pt")
target_ids = encodings.input_ids.clone()

outputs = model(encodings.input_ids, labels=None) # 不传入 labels
logits = outputs.logits
labels = target_ids.to(logits.device)

# Shift 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())
登录后复制

在这个例子中,我们首先不将 labels 传入模型,而是获取模型的 logits 输出。然后,手动将 logits 和 labels 进行对齐(shift),并使用 CrossEntropyLoss 计算损失。reduction='mean' 表示计算所有 token 的平均损失。

注意事项:

  • shift_logits 和 shift_labels 的目的是使预测的 logits 与对应的真实 label 对齐。
  • contiguous() 方法用于确保张量在内存中是连续存储的,这对于某些操作是必需的。
  • 可以根据需要调整 CrossEntropyLoss 的 reduction 参数,例如设置为 'sum' 来计算所有 token 的损失之和。

通过理解 Decoder-Only 模型的输入和目标,以及正确使用 labels 参数进行 Masking,可以更有效地训练和评估这些模型。同时,自定义计算损失的方法提供了更大的灵活性,可以满足不同的需求。

以上就是理解 Transformers 中的交叉熵损失与 Masked Label 问题的详细内容,更多请关注php中文网其它相关文章!

相关标签:
最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号