Transformers批次分词时动态补齐与固定长度补齐怎么选
来源:17golang原创
时间:2026-10-13 20:24:13 153浏览 收藏
输入长度差异较大、后端允许变化的序列长度时,优先考虑动态补齐:padding=True 或 padding="longest"。后端明确要求固定序列维度,或你希望只使用有限几种形状时,才选择 padding="max_length" 并明确长度。两者都需要单独决定截断规则,不能把“补到指定长度”理解成“超长一定被截掉”。
本文以 BERT 类文本编码批次为例,使用 Transformers 文档所描述的 tokenizer 与 DataCollatorWithPadding API,不讨论生成模型的左右补齐策略。官方文档地址:https://huggingface.co/docs/transformers/index;示例分词器仓库:https://huggingface.co/google-bert/bert-base-chinese。
短文本批次为什么被长上限拖住
设一个自定义示例批次含四条文本,分词后的有效长度分别为 12、20、28、36。若固定补到 128,每批容纳 512 个位置,其中有效位置只有 96;若只补到本批最长 36,则容纳 144 个位置。这个算术例子说明补齐占位的差异,不是模型实测耗时,也不能推出吞吐按同一比例提高。
attention_mask 让模型区分有效位置与补齐位置,但不意味着所有后端都会完全跳过这些位置的计算。因此,把全局较大上限应用到每个短文本批次,可能让容量规划围绕补齐部分展开。另一方面,动态补齐让不同批次产生不同长度,后端编译、缓存与部署约束也要一起考虑。
用同一批输入比较两种补齐
将 padding 看成形状策略,将 truncation 看成内容保留策略,将 max_length 看成配置上限。动态模式下 max_length=128 配合 truncation=True 约束超长输入,却不要求短批次也补到 128。固定模式则将短输入补到这个目标;只有启用截断后,超长输入才受对应截断规则限制。
from transformers import AutoTokenizer
# 仅加载分词器,不加载模型权重;首次使用需要仓库访问或本地缓存
tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-chinese")
texts = ["请确认订单。", "仓库完成复核后,请通知客户安排收货。"]
# 同一个上限下,动态补齐只对齐当前批次
dynamic = tokenizer(
texts, padding=True, truncation=True, max_length=128,
return_attention_mask=True,
)
# 固定补齐让本例每条序列占据128个位置
fixed = tokenizer(
texts, padding="max_length", truncation=True, max_length=128,
return_attention_mask=True,
)
for name, batch in [("动态", dynamic), ("固定", fixed)]:
# 观察分词后的长度,而不是字符数;本例返回普通列表
print(name, [len(ids) for ids in batch["input_ids"]])
print("有效位置", [sum(mask) for mask in batch["attention_mask"]])
示例使用普通列表,不需要为观察长度安装张量后端。若要传给 PyTorch 模型,可在环境有相应后端时设置 return_tensors="pt"。字符数不能直接代替 token 数,特殊 token 也占用长度。本例的 128 只是应用示例上限,不是所有模型通用值。

训练时把补齐留到组批阶段
如果数据集预处理把整批样本提前补到一个大长度,后续 collator 不会自动替你恢复那些已丢失的原始长度信息。更清楚的职责分配是:预处理分词并截断但不补齐,组批时由 DataCollatorWithPadding 接收当前样本并补齐。这样样本存储与模型批次可以使用不同形状。
from transformers import AutoTokenizer, DataCollatorWithPadding
# 必须沿用与模型匹配的分词器
tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-chinese")
texts = ["到货已签收。", "请核对运输单上的件数与收货记录。"]
features = [
# 每条样本先保留自己的长度,截断发生在分词阶段
tokenizer(text, truncation=True, max_length=128, padding=False)
for text in texts
]
collator = DataCollatorWithPadding(
tokenizer=tokenizer,
padding=True,
return_tensors="pt", # 本段需要可用的PyTorch后端
)
batch = collator(features)
print(batch["input_ids"].shape)
# 将同一批的attention_mask一并交给支持该字段的模型
DataCollatorWithPadding 用于补齐与组批,不是替代分词阶段的截断器。它也不是所有任务标签的通用补齐器;token 分类、序列到序列任务有各自的 collator。不要把额外文本元数据一起塞进张量字段。

固定形状值得付出哪些代价
| 实际约束 | 优先尝试 | 需要承担的代价 |
|---|---|---|
| 短长文本混合,后端允许可变长度 | 动态补齐 | 批次形状变化,需观察调度与编译行为 |
| 部署签名明确要求序列长度一致 | 固定长度 | 短输入增加补齐位置,超长输入需明确处理 |
| 希望限制形状数量,但全局固定过浪费 | 长度分桶加有限固定目标 | 调度、顺序恢复与等待策略更复杂 |
| 训练数据已按单条分词存储 | 组批阶段动态补齐 | 必须配置适合任务的collator |
固定序列长度不等于所有维度都固定,batch_size 仍可能变化。想复用某个静态形状的导出模型,应核对其所有输入维度与实际后端配置。动态模式也不是必然更快:更小的序列长度带来的好处,需要和编译、调度、传输等成本一起衡量。
如果 tokenizer 没有可用的 pad token,先确认模型设计和分词器配置;不要为了消除报错盲目把 EOS 当 PAD。本文例子只用于 BERT 编码任务,不能原样推导到所有自回归生成模型。
上线后看有效token而不是只看请求数
将有效位置数定义为 attention_mask 中有效标记的总数,将批次位置数定义为所有序列长度之和,补齐比例为 1 减去二者之比。在传统 0/1 mask 的文本编码批次里,这个指标能描述占位浪费,但不是硬件利用率。
读者在实际环境比较策略时,应保持同一模型、输入、截断上限与批次策略,同时记录吞吐、延迟分位数、显存峰值、补齐比例及输出一致性。固定模式若频繁超预算,调整上限或分桶;动态模式若出现形状相关的后端开销,则评估有限形状。本文没有上线压测记录,不给出伪造的提速数字。
继续压缩补齐浪费
将长度相近的文本放在同一批次,可以减少动态模式被单条长文本拉高的概率,但在线分桶会影响等待时间。重新排序时保留原始索引,输出后恢复请求次序;不能只为了更短的批次破坏业务对应关系。
pad_to_multiple_of=8 这类对齐选项可以作为设备相关实验项,但会额外补齐,不能保证更快。对齐后的长度也要处于模型允许范围;固定目标、截断上限与对齐倍数应一起考虑,而不是独立堆参数。
padding=True配合max_length会补到那个值吗?
不会据此变成固定补齐。启用截断时,上限约束内容;动态补齐仍以当前批次长度为依据。
只传一条文本,动态补齐为什么没有变化?
这条文本已经是该批次的最长序列,没有其他样本需要对齐;若明确要求目标长度,应使用固定策略。
补齐可以替代截断吗?
不可以。补齐处理短输入的占位,截断处理长输入的内容;是否允许信息被截掉还需要业务决定。
动态补齐是减少无用位置的起点,固定长度是满足形状约束的工具。先建立明确的截断上限,再按后端形状要求选择补齐,比只比较一个 padding 开关更可靠。参数依据见 官方补齐与截断说明;组批接口见 DataCollatorWithPadding 文档。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
492 收藏
-
338 收藏
-
326 收藏
-
118 收藏
-
386 收藏
-
科技周边 · 人工智能 | 58分钟前 | 人工智能 · Hugging Face Datasets streaming IterableDataset Dataset.shuffle shuffle buffer130 收藏
-
174 收藏
-
421 收藏
-
301 收藏
-
111 收藏
-
461 收藏
-
330 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习