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

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 只是应用示例上限,不是所有模型通用值。

批次最长长度固定目标与截断上限的静态配置关系
图1:原创静态配置说明图。动态与固定分组分别关联本批最长长度和指定目标;截断上限独立影响内容长度,图示不表示执行顺序或实测性能。

训练时把补齐留到组批阶段

如果数据集预处理把整批样本提前补到一个大长度,后续 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与批次张量字段的结构
图2:原创静态模块说明图。样本列表属于预处理产物,collator 依赖同一分词器;input_ids 与 attention_mask 属于同一个批次,不是两次独立组批。

固定形状值得付出哪些代价

实际约束优先尝试需要承担的代价
短长文本混合,后端允许可变长度动态补齐批次形状变化,需观察调度与编译行为
部署签名明确要求序列长度一致固定长度短输入增加补齐位置,超长输入需明确处理
希望限制形状数量,但全局固定过浪费长度分桶加有限固定目标调度、顺序恢复与等待策略更复杂
训练数据已按单条分词存储组批阶段动态补齐必须配置适合任务的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 文档。

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