ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

TRL SFT 的 packing 策略怎么选?bfd、bfd_split 与 wrapped 的区别

TRL SFT 的 packing 策略怎么选?bfd、bfd_split 与 wrapped 的区别 TRL SFT 的 packing 策略怎么选bfd、bfd_split 与 wrapped 的区别【免费下载链接】trlTrain transformer language models with reinforcement learning.项目地址: https://gitcode.com/GitHub_Trending/tr/trl在 TRLTrain transformer language models with reinforcement learning里用SFTTrainer做监督微调时序列长短不一会让批处理大量 padding浪费显存和算力。开启packingTrue后多个短序列会被打包进同一行、填满到max_length从而减少 padding。但超过max_length的超长序列该怎么处理取决于packing_strategy参数——bfd、bfd_split、wrapped三种策略在“丢 token、保 token、破坏序列连续性”之间的取舍各不相同选错会直接损失训练数据或影响效果。这篇文章基于 Packing 文档 和 SFT 训练器文档讲清三种策略的差异、选择依据和验证方式。前提packing 只在特定条件下可用Packing 有两道硬门槛来自 Reducing Memory Usage 的 Packing 一节仅支持SFT 训练其他训练器没有 packing 选项模型必须使用FlashAttention 或其变体。第二条在源码中体现得很具体。sft_trainer.py 中定义了已知能可靠支持 packing / padding-free 的注意力实现集合FLASH_ATTENTION_VARIANTS { flash_attention_2, flash_attention_3, kernels-community/flash-attn2, kernels-community/flash-attn3, kernels-community/vllm-flash-attn3, }如果attn_implementation不在这个集合里训练器会打印警告packing 把多个样本聚进同一条序列非 FlashAttention 实现可能导致样本间交叉污染cross-contamination并建议关闭 packing 或把模型配置里的attn_implementation换成上述选项之一。另外注意一个源码层面的行为使用bfd或bfd_split时SFTTrainer 会自动开启 padding-free 模式padding_free args.padding_free or (args.packing and args.packing_strategy in {bfd, bfd_split})因为带 padding 的 attention mask 会让 FlashAttention 错误地重算 position_ids。你不需要显式设置padding_freeTrue但这意味着使用 BFD 策略时不能再传自定义 data collator会直接抛ValueError。三种策略的区别三种策略都基于Best-Fit Decreasing (BFD)分箱打包的思路区别在于序列超出max_length时的处理方式见 reducing_memory_usage.md策略超长序列的处理token 是否保留对序列连续性的影响bfd默认溢出部分丢弃会丢 token保留单条序列边界bfd_split先切成 ≤max_length的块再打包全部保留长序列被切开块可能进入不同的打包行wrapped所有 token 拼成一条流按固定长度切块全部保留忽略序列边界可能把不相关的样本混在同一个块里各策略的文档依据bfd默认Best-Fit Decreasing packing序列超过max_length时溢出 token 被丢弃。源码 pack_dataset 的 docstring 进一步说明它“保留序列边界适合需要维持对话结构的 SFT 和 conversational 数据集”。bfd_split超长序列先被切分成不超过max_length的块再参与打包不丢 token做法来自论文Fewer Truncations Improve Language Modelingpaper_index 中的对应条目 也把它列为bfd_split策略的来源。代价是在 SFT 数据上可能破坏对话结构它更适合预训练或长文档场景。wrapped所有 token 拼成一条流后切成固定长度块padding 最少但可能把不相关的样本混在一起。文档明确指出这属于concatenate-then-split预处理会打断数据集中相当大比例样本的序列连续性并引用 Qwen3-Coder-Next Technical Report 的结论这会损害性能。一个重要的等价性说明文档原文 NOTE当所有序列都短于max_length时bfd和bfd_split行为完全一致因为不需要截断也不需要切分。按数据特点选策略选择依据可以直接对应到文档给出的适用条件SFT / conversational 数据集对话结构重要→ 用默认的bfd。docstring 明确说它是为保持对话结构设计的。代价是超长样本的尾部 token 会丢如果数据集里长序列很少这个损失可以忽略。长文档、预训练语料不能容忍丢 token→ 用bfd_split。它保留了全部 token但注意 docstring 的提醒这可能破坏 SFT 数据集里的对话结构。如果你是在微调指令数据而不是做通用 LM先评估数据里超长样本的占比再决定。wrapped仅在你能接受序列连续性被破坏时使用。它 padding 最少但文档给出的结论是负面居多混合不相关样本、打断连续性、引用报告称损害性能。源码里还有一条对应约束padding_freeTrue搭配wrapped会打印“不推荐”的警告见 sft_trainer.py。数据长度普遍远小于max_length→ 三个策略中bfd与bfd_split无差别直接用默认的bfd即可。配置与执行最小配置就是给SFTConfig传packing、packing_strategy和max_length三个参数示例来自 reducing_memory_usage.mdfrom trl import SFTConfig training_args SFTConfig( ..., packingTrue, packing_strategybfd, # 可选值bfd、bfd_split、wrapped max_length512, )packing_strategy默认值是bfd见 sft_config.pymax_length决定每行打包后的长度。选max_length本身也有讲究How to choose the max_length value?太小会丢弃大量 token太大会推高显存甚至 OOM且没有 packing / padding-free 时大部分 token 会是 padding。文档提供了一个可视化工具来查看数据集中的序列长度分布用来辅助定这个值。如果沿用旧配置里出现过的bfd-requeue值SFTConfig 会自动改写成bfd_split并抛出FutureWarning提示该策略已更名、将在 v2.0.0 移除——见到这个警告直接把配置改成bfd_split即可。验证策略行为文档和源码给出了一个可直接运行的最小核对方式pack_dataset的 docstringdata_utils.py展示了固定输入下两种策略的输出。下面的输入、输出均为源码中的文档示例用于确认打包行为而不是训练必须达到的数值from datasets import Dataset from trl.data_utils import pack_dataset examples { input_ids: [[1, 2, 3, 4, 5], [6, 7], [8, 9, 10], [11]], attention_mask: [[1, 1, 1, 0, 0], [1, 0], [1, 1, 0], [1]], } dataset Dataset.from_dict(examples) # 默认 bfd5-token 的序列 [1,2,3,4,5] 被截断token 5 丢弃 packed pack_dataset(dataset, seq_length4, strategybfd) print(packed[:]) # 文档示例输出: # {input_ids: [[1, 2, 3, 4], [8, 9, 10, 11], [6, 7]], # attention_mask: [[1, 1, 1, 0], [1, 1, 0, 1], [1, 0]], # seq_lengths: [[4], [3, 1], [2]]} # bfd_splittoken 5 被切出来补进第二个块 packed pack_dataset(dataset, seq_length4, strategybfd_split) print(packed[:]) # 文档示例输出: # {input_ids: [[1, 2, 3, 4], [8, 9, 10, 5], [6, 7, 11]], # attention_mask: [[1, 1, 1, 0], [1, 1, 0, 0], [1, 0, 1]], # seq_lengths: [[4], [3, 1], [2, 1]]}对照示例可以看清楚两种策略的分野bfd的输出里 token5消失了bfd_split里它被保留并拼到了第二个块的末尾seq_lengths列记录了每行里各段原始序列的长度供 document-aware 的 FlashAttention 使用。训练启动后还有两个日志信号值得盯出现“attention implementation is not set to a supported Flash Attention variant”警告 → 说明当前实现不在支持集合里样本间可能交叉污染需要换注意力实现或关闭 packing出现“padding_freeTruewith the wrapped packing strategy, which is not recommended”警告 → 说明你显式开了padding_free又选了wrapped文档与源码都标为不推荐组合。限制与因果 SDPA 长上下文方案互斥long_context_training.md 说明packing 依赖 block-diagonal mask 防止文档互相读取而 causal-SDPA 方案要求全注意力且拒绝 sliding-window / chunked attention 的模型两者同时开启时 TRL 会直接报错raises。做长上下文 SFT 时不要期望叠加 packing。bfd/bfd_split自动进入 padding-free 模式因此不支持自定义 data collatorpadding_freeTrue且未开 packing 时又设置了max_length非视觉数据集SFTTrainer也会抛ValueError提示要么开 packing、要么预先截断输入、要么把max_lengthNone。wrapped的连续性破坏问题没有参数可调只能靠接受或不接受来取舍对 SFT 数据而言bfd或bfd_split通常更符合文档给出的适用条件。按数据形态落一次判断对话型 SFT 数据用默认bfd长文档且不能丢 token 用bfd_split只有明确接受样本混合、以最小化 padding 为第一目标时才考虑wrapped。配置改完后用上面的pack_dataset示例和启动日志里的警告就能确认策略真的按预期生效。【免费下载链接】trlTrain transformer language models with reinforcement learning.项目地址: https://gitcode.com/GitHub_Trending/tr/trl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表