登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  人工智能

Tokenizer 左填充和右填充应该怎么选

来源:17golang原创

时间:2026-09-28 07:32:01 399浏览 收藏

Tokenizer 左填充还是右填充,不能只看模型名字:decoder-only 模型做批量文本生成时通常选左填充;因果语言模型训练、encoder-only 和多数 encoder-decoder 数据整理流程通常使用右填充,并优先遵循模型默认值、模型卡和 DataCollator 的约定。单条输入没有发生 padding 时,方向不会产生实际差异。

官方文档:https://huggingface.co/docs/transformers/main_classes/tokenizer

快速选择
  • decoder-only 批量 generate():优先 padding_side="left"。
  • decoder-only 训练:多数数据管线使用右填充,并把 PAD 对应标签设为 -100。
  • encoder-only 分类、抽取任务:通常保持 tokenizer 默认右填充,并正确传入 attention_mask。
  • encoder-decoder:源序列和目标标签交给模型配套 tokenizer/DataCollator 管理,通常不要自行改方向。

padding_side 控制的到底是什么

批次里的文本长度不同,无法直接组成矩形张量。padding=True 会把较短序列补到批次最长长度,padding="max_length" 则补到指定或模型允许的最大长度;padding_side 决定 PAD 放在有效 token 左边还是右边。官方 Tokenizer API 只允许 "left" 或 "right",未显式设置时采用对应 tokenizer 类的默认值。

方向本身并不能让模型忽略 PAD。真正告诉模型哪些位置无效的是 attention_mask。如果还在训练,损失函数还需要通过标签中的 -100 忽略 PAD 位置;只改 padding_side 而漏掉这两个掩码,结果仍可能异常。

为什么 decoder-only 批量生成优先左填充

自回归生成要从每条提示词的最后一个有效 token 继续预测。右填充时,短提示词的批次末端是 PAD;许多生成流程从张量最后一个位置取得下一 token 的 logits,即使 attention_mask 屏蔽了注意力,末端位置仍不是短提示词真正的结尾。Hugging Face 的 LLM 生成教程因此明确建议 decoder-only 批量生成使用左填充。

不同长度提示词左填充后末端有效 token 对齐与 attention mask 关系图
图1:左填充把不同长度提示词的最后一个有效 token 对齐到批次末端,attention_mask 负责屏蔽左侧 PAD。

许多 decoder-only LLM 没有独立 pad_token。推理时常见做法是临时把 EOS 作为 PAD,并始终传入 attention_mask。这样不是说 PAD 变成了“真正的句尾”,而是利用掩码让补齐位置不参与有效上下文。

from transformers import AutoModelForCausalLM, AutoTokenizer

model_id = "your-decoder-only-model"

# 批量生成让有效提示词末端位于同一列,避免从右侧 PAD 位置续写。
tokenizer = AutoTokenizer.from_pretrained(model_id, padding_side="left")
model = AutoModelForCausalLM.from_pretrained(model_id)

if tokenizer.pad_token_id is None:
    # 推理时可复用 EOS 作为 PAD,但必须保留 attention_mask。
    tokenizer.pad_token = tokenizer.eos_token

batch = tokenizer(
    ["用一句话解释缓存", "列出三个 HTTP 状态码并说明用途"],
    padding=True,
    return_tensors="pt",
)

# 把 input_ids 和 attention_mask 一起传入生成接口。
generated = model.generate(**batch, max_new_tokens=32)
texts = tokenizer.batch_decode(generated, skip_special_tokens=True)

按模型与任务选择填充方向

decoder-only 生成、训练、encoder-only 与 encoder-decoder 填充方向关系图
图2:填充方向由模型架构与当前任务共同决定,模型默认和官方文档优先级高于通用经验。
模型与任务常见选择主要理由
decoder-only 批量生成左填充让批次末端对应每条提示词的最后一个有效 token
decoder-only 因果 LM 训练右填充常见数据整理器和标签移位流程按右填充组织
encoder-only 分类/抽取通常右填充双向注意力配合 attention_mask,遵循预训练与 tokenizer 默认
encoder-decoder通常右填充源序列、目标标签和 DataCollator 有各自约定
单条且不补齐无实际差异输入中没有 PAD 位置

“通常”不是绝对规则。某些模型会自行构造 position_ids,某些模型卡会明确要求方向,远程推理服务也可能在内部重新组批。可靠做法是先保持 tokenizer 默认,再只为明确的生成或训练问题调整,并把配置写进推理或训练入口,避免同一个 tokenizer 在不同阶段被隐式修改。

训练时不要误伤真实 EOS

因果语言模型训练通常右填充,让每条样本从索引 0 开始放置有效 token。创建 labels 后,应根据 attention_mask 把 PAD 位置设为 -100。如果 pad_token 与 eos_token 共用同一个 ID,不要按“token ID 等于 EOS”批量屏蔽,否则可能连样本中真实的 EOS 也从损失中去掉。

batch = tokenizer(
    texts,
    padding=True,
    truncation=True,
    return_tensors="pt",
)

# labels 从 input_ids 复制,不能直接修改模型输入张量。
labels = batch["input_ids"].clone()

# 按 attention_mask 屏蔽补齐位置,保留正文里的真实 EOS 标签。
labels[batch["attention_mask"] == 0] = -100
batch["labels"] = labels

若使用 Transformers 提供的 DataCollator,应先查看它对 pad_token、label_pad_token_id 和左右填充的处理,不要在外层再重复改 labels。对于 token classification,还要同步对齐 word_ids 与标签;对 seq2seq,目标端的 label padding 由专用 collator 处理更稳妥。

快速检查配置是否真的生效

不要只打印 tokenizer.padding_side。取两条长度明显不同的文本组成批次,同时检查 input_ids 与 attention_mask:左填充时,短序列开头应出现 PAD 且 mask 为 0;右填充时,PAD 和 0 应出现在末尾。

sample = tokenizer(
    ["短句", "这是一条明显更长的输入文本"],
    padding=True,
    return_tensors="pt",
)

# 同时观察 token 与掩码,确认 PAD 一侧和无效位置一致。
print("padding_side:", tokenizer.padding_side)
print("input_ids:\n", sample["input_ids"])
print("attention_mask:\n", sample["attention_mask"])

decoder-only 生成还应做一组 A/B:同样的两条提示词分别左填充和右填充,固定解码参数,比较短提示词的输出是否异常;训练则比较有效 token 数、被屏蔽标签数和 loss 是否包含 PAD。这样得到的是任务级证据,而不是对 padding_side 的泛化猜测。

常见误区

  • 把左填充当成 LLM 的全局配置:生成和训练可能需要不同方向,应分开创建或显式设置 tokenizer。
  • 只传 input_ids:批量补齐后必须传 attention_mask,否则模型可能把 PAD 当成上下文。
  • 把 pad_token_id 和 eos_token_id 相同理解为完全等价:它们的数值可以复用,但语义要由 attention_mask 和 labels 区分。
  • 忽略 position_ids:自定义模型或手写 forward 时,左填充可能改变位置编号;优先调用模型官方生成接口。
  • 混淆 padding_side 与 truncation_side:前者决定补齐位置,后者决定超长序列从哪端截断,两者要分别设置。

相关问题

单条推理也必须左填充吗?

如果单条输入没有补齐,左右方向不会改变张量。只有单条也使用 padding="max_length" 时,方向才会实际出现。

attention_mask 正确,右填充生成就一定没问题吗?

不一定。decoder-only 批量生成通常还会从批次最后一个位置取得下一 token logits,右填充会让短序列末端落在 PAD 上,因此官方 LLM 教程仍建议左填充。

可以永久修改 tokenizer.padding_side 吗?

可以,但更推荐在训练和生成入口显式设置并记录,因为同一模型的两个阶段可能采用不同方向。保存 tokenizer 时也要确认配置是否随制品一起交付。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>