亚马逊AWS官方博客

Text-only LLM SFT 训练数据预处理:从收集到数据打包的完整指南

摘要:本文将系统介绍 Text-only LLM SFT 训练数据预处理的完整流程,涵盖从数据收集到最终打包的每一个环节,并结合真实客户案例给出实操建议。这里需要说明的是,本文聚焦于纯文本场景,且不涉及代码生成和 SQL 相关的场景。从 2025 年的行业趋势来看,代码和 SQL 相关场景基本上都是基于开源模型权重或闭源模型来构建实现的,需要针对代码和SQL相关场景做post training 的客户相对要少很多。此外,SFT 和 RFT(Reinforcement Fine-Tuning)的训练数据预处理存在差异,本文只讨论 SFT 的部分。虽然 SFT 本身又分为全参数 SFT 和 PEFT(主要是 LoRA 及其变体),但数据集的预处理流程对两者是一致的。


一、引言

在大模型微调的实践中,训练数据的质量远比数据的数量重要。许多团队在模型架构选型和超参数调优上投入了大量精力,却往往忽视了训练数据预处理这一关键环节。事实上,数据预处理的质量直接决定了 SFT(Supervised Fine-Tuning,监督微调)的最终效果。一条标注错误的困难样本带来的负面影响,可能需要数十条正确样本才能弥补。

本文将系统介绍 Text-only LLM SFT 训练数据预处理的完整流程,涵盖从数据收集到最终打包的每一个环节,并结合真实客户案例给出实操建议。这里需要说明的是,本文聚焦于纯文本场景,且不涉及代码生成和 SQL 相关的场景。从 2025 年的行业趋势来看,代码和 SQL 相关场景基本上都是基于开源模型权重或闭源模型来构建实现的,需要针对代码和SQL相关场景做post training 的客户相对要少很多。此外,SFT 和 RFT(Reinforcement Fine-Tuning)的训练数据预处理存在差异,本文只讨论 SFT 的部分。虽然 SFT 本身又分为全参数 SFT 和 PEFT(主要是 LoRA 及其变体),但数据集的预处理流程对两者是一致的。更多的详细技术实现细节可以参考我的github

二、完整流程概览

Text-only LLM SFT 训练数据的预处理本质上是一个迭代的过程。它并非线性地从头走到尾就能完成,而是可能在某个步骤发现问题后需要回到前面的步骤进行调整。完整流程包含以下九个步骤:收集数据、统一数据格式(标准化数据结构)、基础的数据清洗和过滤、初步的数据去重、进一步的数据清洗和质量过滤、精细的数据去重、数据分布评估、混合数据策略、以及数据打包和版本管理。这九个步骤环环相扣,前一步的输出是后一步的输入,而后续步骤的评估结果又可能驱动前面步骤的迭代优化。

[图1]

三、收集数据

收集数据是整个流程的起点,也是最需要人工判断和实践经验的环节。这个步骤无法自动化完成,因为涉及到的变量和变数非常多,很多时候需要根据客户的不同上下文和环境来 case by case 做实验,因此很难用代码逻辑的方式来沉淀所谓的最佳实践。

3.1 关键决策:全参数 SFT 还是 LoRA

在收集数据之前,首先需要明确的一个核心问题是选择全参数 SFT 还是 LoRA。这个决策直接影响所需的数据量和数据收集策略。一般来说,如果训练样本充足、计算资源允许、且希望模型能力有较大幅度的提升,那么全参数 SFT 是更好的选择。如果样本有限、成本受限、或者只关注单一任务的微调,LoRA则更为合适。需要特别注意的是,对于 LoRA 任务,不建议用单个 LoRA adapter 来做多任务训练。如果确实需要用 LoRA 做多任务 SFT,建议为每个任务训练一个独立的 LoRA adapter。

决策树大致可以参考如下:

[图2]

关于样本数量多少算充足,可以大致参考下文中 “text only LLM 全参数SFT的样本数量与模型参数size的关系”的表格。简单来说,在同样的条件下,模型参数量越大,最好给它提供更多的训练样本,因为更大的模型有能力消费更多的样本知识,其天花板也更高。

3.2 Multi-task 全参数 SFT 的采样策略

对于 Multi-task 全参数 SFT 任务,不同任务的数据比例是一个核心挑战。这个比例既可以在收集数据阶段来调整,也可以在训练开始前或者训练过程中针对不同 task 的样本做采样调整。Multi-task的全参数SFT的训练策略,不一定把这些task都直接暴力一次SFT的效果就是最好(也可能多阶段SFT效果更好)。训练效果和不同task的训练样本数量,不同task样本的采样方法,不同task之间本身的差异性等都有关系。核心原则是避免数据不平衡导致的”任务遗忘”——某类数据占比过大会导致模型在其他任务上性能退化。目标是让模型在所有任务上都有足够的学习信号,而非简单地按原始数据量堆积。

常见的采样方法有以下几种。第一种是均匀采样,每个任务等概率采样,不管原始数据量大小,优点是简单且小任务不会被淹没,缺点是大数据量任务可能欠拟合、小数据量任务可能过拟合。第二种是按比例采样,按各任务原始数据量的比例采样,缺点是头部任务主导训练、尾部任务学习不充分。第三种是按温度采样,这是最常用的方法,mT5、PaLM、GLM 等模型都采用了这种方案。其采样概率按如下公式计算:p_i = (n_i^(1/T)) / Σ(n_j^(1/T)),其中 n_i 为第 i 个任务的数据量,T 为温度系数,常用 T=2~5。当 T=1 时退化为按比例采样,当 T 趋近无穷大时退化为均匀采样。第四种是基于任务难度或重要性的加权,比如对核心任务(如对话、指令跟随)给予更高采样比例,对辅助任务(如分类、摘要)适当降低采样比例。

此外,还有一些实用技巧值得参考:设置数据量上限,对数据量特别大的任务做截断,常见做法是对每个任务设 max samples(如 50k~100k);Epoch 不对齐处理,让小数据集的任务可以多 epoch 重复采样,大数据集的任务只用一部分;动态调整,在训练过程中监控各任务 loss,对 loss 下降慢的任务提高采样权重;分阶段训练,先在全部数据上均匀训练,再在核心任务上做少量 epoch 的精调。最后一点非常重要——验证集独立评估:每个任务应单独评估指标。如果train loss是任务加权的,对验证集上表现差的任务尝试提升loss权重。

3.3 语种相关考虑

SFT 训练任务可能涉及单语种、多语种、或者语种混杂的场景。如果 base model 本身就支持你所需要的多个语种(如 Llama 3、Qwen2.5、Mistral 等现代 base model 在预训练阶段已覆盖多语种),建议优先考虑用一个模型训练多语种。原因在于:多个单语模型意味着多倍的部署和维护成本,而一个模型的跨语言迁移效应反而能让低资源语种受益。

关于多语种任务中不同语种训练样本的比例,有几个实用建议:首先以目标业务的语种分布为锚点,如果业务流量 70% 中文、20% 英文、10% 日文,初始比例就参考这个分布;然后根据 base model 的语种强弱进行调整,如果base model对该语种能力强,可以适当减少该语种样本的比例,否则需要增加该语种的样本比例;用验证集效果来驱动比例的最终确定。初始比例只是起点,实践中应通过各语种的验证集指标来调整这个比例——在各语种上分别跑 benchmark,哪个语种表现弱就适当提高其比例。

3.4 数据来源与收集方法

数据的收集来源通常包括以下几个渠道:公司内部积累的数据、业务专家标注的数据、通过标注工人(如 Amazon MTurk 众包平台)进行数据集的对齐标注、直接购买对齐的数据集、下载开源的对应任务的对齐数据集(比如 QA 形式的试卷本身就是高质量的对齐数据集),以及借助 SOTA LLM 来生成对齐的样本。

在数据来源策略中,人工标注的质量最高但成本也最高。最佳实践是制定详细的标注指南,先小批量试标后 review 并修订指南,再进行大规模标注,同时设置多标注员交叉验证和质检环节(抽检率根据行业和任务决定,有的客户 10%~20% 就可以接受,有的客户抽检率达到 100%)。

强模型合成数据是性价比最高的方式,用 GPT-4 或 Claude 等强模型生成训练数据。常用方法包括:Self-Instruct(用种子任务引导模型生成新的 instruction 和 response)、Evol-Instruct(对已有 instruction 做复杂度演化,来自 WizardLM 的方案)、反向指令转换(从高质量文本内容生成对齐的 QA 对,因为互联网上高质量的文本内容随处可见,但并不一定是 QA 对的形式,回译法把这些优质文本转化为可用的 SFT 训练数据)、以及 最优采样(对同一 prompt 采样 N 次选最优回复)。需要注意的是,合成数据会继承源模型的偏差和幻觉,需要人工抽检验证质量,同时要注意 License 问题——部分模型禁止用输出训练竞品。

3.5 样本难度分布

针对涉及到的训练任务,不同难度级别的样本比例也需要认真考虑。在模型训练中,困难样本和 corner case 这样的珍贵样本对模型学习来说非常重要。然而困难样本和 corner case 并不是越多越好,太多(比如超过 40%)可能会让模型训练不收敛。同时必须保证困难样本的质量,困难样本如果标注答案本身有瑕疵,模型会学到错误模式,其危害比简单样本的错误大得多。

可以参考的一个比例(如下表):

难度 比例 作用
简单 20~30% 锚定基本输出格式和通用模式,稳定训练
中等 40~50% 主力学习区间,模型提升最大的部分
困难 20~30% 拉高能力上限,学习复杂推理和边界处理
Corner case 5~10% 修补边界行为,防止极端输入下崩溃

推荐的采样策略是:简单样本做下采样(随机丢弃部分),中等样本基本保留,困难样本保留或轻微上采样,corner case 上采样 2~5 倍或进行扩写(基于一个 corner case 用不同表述和场景构造 3~5 个变体)。

3.6 真实客户案例

案例一:垂域 Single Task 全参数 SFT。客户的需求是针对垂直领域的单一任务做全参数 SFT,只关心该任务的模型效果表现,需要模型支持中英文两种语言。样本格式比较特殊:指令是中文的,输入是英文的,输出是中英文混杂的。类似如下的格式:

{
 "instruction": "请分析以下文本的情感倾向", // 中文
 "input": "The product quality is excellent but delivery was slow", // 英文
 "output": "情感倾向为正面。该评价对product quality(产品质量)给予了高度评价(excellent),但对delivery speed(配送速度)表示不满(slow)。总体来说positive sentiment占主导。" // 中英混杂
}

客户选择了一个中文开源 Dense LLM 作为基座,考虑成本和时间因素不想做 continue pretrain,想先全参数 SFT 看看效果。最终的数据策略是:客户自己的 single task 样本由 100 条左右的专家样本加上通过 OpenAI GPT 生成的约 4 万条样本组成(经过规则过滤和 10% 专家抽样检查),然后将 single task 样本与收集的开源中文指令语料按 1:1 比例混合。最终SFT后的效果客户表示可以接受。

案例二:垂域 Single Task + 其他任务防遗忘。客户的需求是垂直领域单一任务全参数 SFT,训练完的模型除了要求当前任务效果提升,还需要其他任务效果不降低,即尽量避免灾难性遗忘,只需支持中文。客户拥有高质量对齐的 QA 数据样本 20 万条以上,最终将 single task 样本与开源对齐样本按 1:1 比例混合。结果是 SFT 后的模型在关注的 QA 任务上效果好于当时的闭源模型,其他任务效果基本没有降低。

案例三:开放域 Single Task(英文,100万+ 数据)。客户在当前 single task 上有 100 万条以上的高质量数据集,来自线上流量收集的真实用户数据。由于该任务本质上是开放域的,且 base model 也是用开放域数据预训练的,因此没有额外混合开源数据集。训练策略选择了渐进式消费数据,每次使用 20~30 万条数据做全参数 SFT,然后基于前次 SFT 后的模型继续喂入新的 20~30 万条训练样本。客户表示这种策略效果不错,比较满意。

3.7 最核心的原则:数据质量大于数据数量

LIMA 论文 (https://arxiv.org/pdf/2305.11206)的结论表明,仅 1000 条高质量数据就能训出优秀的 SFT 模型(当然这个结论尤其适用于简单训练任务,仅供参考)。SFT 的 Scaling 规律不同于预训练:预训练靠量取胜,SFT 靠质取胜。低质量数据堆量反而引入噪声,导致模型退化。实践建议是:宁可花时间精标 5000 条,也不要粗标 50000 条。同时,数据样本尽量保持多样性,包括指令多样性(同一任务类型用不同措辞表达)、长度多样性(短回复和长回复都需要覆盖)、难度多样性(简单、中等、复杂问题按比例分配)、以及语言和领域多样性。

四、统一数据格式(标准化数据结构)

统一格式是为了让后续的清洗、去重等步骤更加一致和便利。用一套代码逻辑就可以处理所有数据,如果格式不统一,则需要为每种格式写不同的处理逻辑。

# 假设对所有的数据样本都统一为格式 {"instruction": ..., "response": ...} 
  def clean_instruction_data(sample):
      if len(sample["instruction"]) < 10:
          return None
      if has_toxic_content(sample["response"]):
          return None
      return sample

在实际项目中,不同数据来源的样本格式(包括存储格式和数据结构)可能都不同,转换为统一数据结构的工作比较繁琐且维护成本高。推荐的解决方案是使用 Claude Code 配合 Bedrock Claude Opus,通过 vibe coding 的方式来生成格式转换脚本,实测效果很不错。

例子:想利用AWS Nova Forge 全参数SFT来训练,当前数据集的格式(使用arrow格式保存,数据结构是自定义的字段,且数据样本是多轮对话)并不是Nova Forge要求的格式。Nova Forge SFT要求的数据格式要求类似如下:

{"schemaVersion": "bedrock-conversation-2024", 
 "system": [{"text": "You are a helpful conversational assistant. Engage in natural, friendly dialogue."}], 
 "messages": [
 {"role": "user", "content": [{"text": "Good morning , can I have your ticket , please ?"}]}, 
 {"role": "assistant", "content": [{"text": "Here you are .\nAn aisle seat , please ."}]}
 ]
}

使用Claude code + Bedrock Claude Opus 4.6来生成的python脚本得到了符合Nova Forge SFT要求格式的数据集,并使用Nova Forge来训练成功进行了验证(经验证,Nova Forge支持多轮对话的数据格式)。

这里有一个关键原则:数据中只存储语义内容,把模板以及特殊 token 的注入交给模型自己的 tokenizer 的 chat_template。这样做的好处是同一份数据可以无修改地用于不同底座模型的微调。举个例子,存储的多轮对话数据只包含 role 和 content 字段,类似于 {“conversations”: [{“role”: “system”, “content”: “You are a helpful assistant.”}, {“role”: “user”, “content”: “法国的首都是哪里?”}, {“role”: “assistant”, “content”: “法国的首都是巴黎。”}]} 这样的纯语义格式。应用模板后才会渲染成带有 <|im_start|> 和 <|im_end|> 等特殊 token 的格式,而这个渲染结果才是最后真正需要的训练样本。

五、基础的数据清洗和过滤

基础数据清洗分为两个部分:文本规范化(可选)和基于规则的过滤(必须)。执行顺序上,应当先做文本规范化,然后再做基于规则的过滤。

针对中文和英文训练数据,文本规范化的关键操作包括以下几个方面。全角半角统一方面,英文字符与数字应始终从全角转为半角,全角形式的英文和数字在中文语境中无语义价值,只会增加 tokenizer 的词表负担。标点符号规范化方面,纯中文文本保留中文标点(全角),纯英文文本保留英文标点(半角),对于中英混排文本,更实际的做法是不强行统一,保留原始标点,因为中英混排场景下用户的真实输入本身就是混合的,模型需要学习这种分布。空白字符规范化方面,连续空格应合并为单个空格(代码块除外),换行符统一为 Unix 格式,制表符转换为普通空格。此外还有中文繁简统一(除非需要同时支持两种语境)和英文大写转小写。

基于规则的过滤是必须执行的步骤,主要包含四类规则。Language-based 规则用于剔除非目标任务语言的样本,可以借助语言识别模型来实现。Statistic-based 规则针对文本计算标点符号占比、句子长度等统计特征,利用这些特征过滤低质量数据。Keyword-based 规则根据特定关键词删除嘈杂或无用的元素(例如超链接),或者如果命中”关注”、”转发”、”点赞”这种明显的广告关键词则丢弃整个句子。Policy-based 规则(借鉴自 Falcon 模型的数据清洗实践)则针对一些特定模式进行过滤,比如句子主要由大写字符组成、句子由纯数字组成、或者短句命中特定模板(如以”登录”或”注册”开头的短句)的情况,都应当丢弃。

六、初步的数据去重

对于 SFT 的数据来说,去重有两个层面。第一个层面是将 input 和 output 文本拼接后得到的完整样本,基于样本相似性进行去重,这个层面在本步骤中处理。第二个层面是针对相似的同一个 input 文本只保留质量最好的 output,这个层面比较复杂,放到后续的”精细的数据去重”步骤中处理。

去重方法主要有三种。精确去重(Exact Dedup)是对 input + output 拼接后的样本计算 hash 值,hash 值相等则认为重复。基于 Overlap ratio 的去重是定义一种文本间”共享内容”的度量方式(token、n-gram、子串或子序列),计算共享比例,超过阈值则归为重复。基于 LSH(局部敏感哈希)的去重是最常用的海量数据去重方法,其中 MinHash LSH 和 SimHash LSH 是两种主要实现。SimHash 能将一篇文章映射成 64bit,通过比较两篇文章的 64bit 的海明距离就能判断相似程度,如果海明距离小于等于 3 就可以认为是重复文章。

在确定了哪些样本是重复的之后,如何选择保留哪一条也很重要。一般做法是给这些重复样本打分,保留得分最高的那条。打分维度取决于业务场景,最后将多个维度的打分加权合并。常见维度包括对话完整性(尤其针对多轮对话场景,优先保留轮次更多、内容更完整的对话)、回复质量和信息量(优先保留回复更详细、信息密度更高的)、时间新鲜度(如果数据带时间戳,优先保留更新的)、以及来源可信度(不同来源赋予不同权重)。打分可以利用 SOTA 模型从多个维度打分并人工抽查,也可以使用业务专家进行打分。

几个需要注意的点:数据去重一般不考虑训练数据和混合数据之间的样本相似度;如果数据样本中有 system 字段,在去重步骤时应忽略它,避免仅因 system 不同而保留重复内容;SFT 训练数据可能涵盖多种任务类型,不同任务的”好样本”标准不同,可以考虑通用维度 + 任务特定维度结合打分;对于多轮对话数据,可以考虑把每个轮次去掉 role 后的 content 完全拼接在一起,然后再做去重。

七、进一步的数据清洗和质量过滤

这一步是在基础清洗之上的深度质量把控,主要依靠模型能力来实现更精细的过滤。

借助模型给样本打质量分数是一个可选但强烈推荐的做法。如果不存在数据敏感问题或成本问题(SFT 的数据量一般不会太大,因此成本一般不是很大的问题),可以直接借助当前性能最好的闭源 LLM 进行打分。评估维度建议包括 Instruction Following(response 是否准确回答了 instruction)、Helpfulness(信息是否有用且完整)、Correctness(事实是否准确,尤其是知识类问题)和 Harmlessness(是否包含有害或偏见内容)。如果数据敏感,可以训练一个分类器来过滤低分样本。如果需要控制成本,可以先采样 1~2k 条用强模型标注,然后训练一个小的质量分类器,再批量打分。

借助文本审核模型去掉不合规的文本是必须执行的操作,包括涉黄、涉恐、涉暴、涉政、辱骂、性别歧视、人种和种族歧视、语言暴力等内容。同时,借助模型识别并去除训练样本中的个人敏感信息(PII)也是必须的。

多轮对话任务有其特殊性,核心难点在于轮次间的依赖关系——不能只看单条 turn 的质量,还要看整体对话的连贯性和逻辑性。在 Turn 级别,需要逐轮检查:空轮或极短轮过滤(response 只有”好的”、”嗯”、”OK”等无信息量回复的应当去除)、重复轮检测(assistant 在不同 turn 给出几乎相同回答的情况)、角色错乱(role 标签是否严格交替)、以及截断检测(最后一轮 response 是否被截断导致不完整)。

在对话级别的过滤是多轮数据特有且最关键的部分。需要评估上下文连贯性、对话推进性(过滤”原地踏步”的对话,比如用户反复问同一个问题说明 assistant 没有真正解决问题的情况)、以及轮次合理性(超过 10~15 轮的对话需要重点审查,而 user 每轮只说”继续”或”然后呢”的对话通常质量较低)。用强模型对完整对话做多维度评估(连贯性、准确性、有用性、自然度、完整性)是最有效的方法。

此外,有些数据不需要直接丢弃,而是可以修复后保留,如下表所示。

问题 修复方式
末轮截断 才见到最后一个完整的assistant turn
中间有空轮 删除该空论及之后的所有轮次,保留前半段
前N轮高质量,后面变差 只保留前N轮作为较短的多轮样本
System prompt缺失 根据对话内容补充合理的system prompt

一轮差的回答会”污染”整条对话的训练信号,如果一个 10 轮对话中有 1 轮 assistant 回答明显错误,模型可能会学到这个错误模式。宁可裁剪为高质量的前 5 轮,也不要保留带缺陷的完整 10 轮。

八、精细的数据去重

精细去重分为两个阶段。首先是针对 input + output 拼接后的完整样本做语义或 embedding 相似度去重,只保留质量最好的那条。然后是针对同一个问题(或高度相似的问题)可能有多条不同质量的回答,只保留最好的那条。

第二个阶段涉及两个关键子问题:如何聚类相似 input 和如何评估 output 质量。在聚类相似 input 方面,LSH 方法适用于百万级数据,速度快成本低;基于 Embedding 聚类适用于十万级数据,去重效果更好但成本中等(可以使用开源的支持多语言的 embedding 模型,也可以使用基于 Bedrock 的 Cohere Embedding 模型)。在评估 output 质量方面,可以参考下表:

信号 描述 成本
样本长度 样本太短通常质量差;但也不是样本越长越好。过滤掉很短的。
模型打分 用开源的SOTA模型直接对单个(input,output)打分
LLM as judge 用第一档闭源的模型比如GPT/Claude对同一个group的多个output做对比打分 高,适合小规模
基于规则 拒绝回答,重复句子,含有乱码的这些Output可以直接淘汰

几个重要注意事项:对于中英混合数据使用 embedding 聚类时,最好使用支持多语言的 embedding 模型;input 相似度阈值不能设太高,0.7 左右即可,太高会漏掉大量改写式重复;对于多轮对话数据,一个起点就是只把 user 的所有轮次拼接起来作为 input 进行聚类,而 output 质量评估则保持 assistant 每轮回复列表逐轮评分,最后对多轮回复评分做加权。

九、数据分布评估

数据分布评估的核心目标是发现短板维度,决策是否需要补充数据。需要从多个维度来评估样本数量的分布情况,包括语种、任务类型、样本长度、任务难度等。如果后续策略是在训练开始前或训练中通过采样来解决分布问题,则可以不进行再次收集数据的迭代。

在语言维度,需要统计每种语言的样本数量和 token 总量,计算各语言占比并与目标分布对比。如果目标语言样本量低于总量的 1% 且绝对数量不足 5000 条,就需要补充。

在任务维度,应确保没有单一任务类型占比超过 40%,也没有重要任务类型低于 3%。多轮对话与单轮的比例建议至少保持 20%~30% 为多轮。如果某关键任务类型样本不足 2000 条或单一任务占比超过 50%,就需要采取行动。

在样本长度维度,需要统计 input 和 output 的 token 长度分布,分别绘制直方图并关注各分位数(P10、P25、P50、P75、P90、P99)。推荐的分布形态是近似对数正态分布,覆盖从短(50 tokens)到长(2000+ tokens)的连续区间。

在难度维度,建议的比例是简单、中等、困难约为 3:5:2,过多简单样本会浪费训练资源,过多困难样本可能导致训练不稳定。

综合评估流程如下图:

[图3]

几个实用建议:第一,写一个自动化脚本对清洗后的数据集自动生成分布报告,每次 pipeline 跑完自动触发。第二,提前设定硬门槛,每个维度的最低样本量和最大占比超出即触发告警。第三,不仅看单维度分布,还要做交叉维度分析——例如中文的数学推理数据可能极度匮乏,单看”中文总量”和”数学总量”都达标,但交叉后不达标。第四,如果某维度缺口不大,上采样优先于重新收集数据。第五,评估分布时同时按相同比例抽出验证集,确保验证集分布与训练集一致。

如果给定的数据集没有上述维度的 metadata,可以借助 AWS Bedrock Claude 针对每个样本给出这些维度的值,包括具体语种(中文、英文、中英文混杂)、任务难度(低、中、高)、任务类型(QA、多轮对话闲聊、情感分类等)。样本长度则可以按 token 长度或字符长度进行统计。

十、混合数据策略

混合数据策略首先需要回答一个问题:需要混合监督数据还是非监督数据?从理论和文献角度来看,混合预训练数据(无监督)更经典、更有据可依。从实际工程角度来看,很多客户基于 Chat 或 Instruct 模型微调,混合对齐监督数据更方便也更常见,因为格式一致、工程简单,且能在一定程度上缓解知识遗忘。如果对通用知识保持的要求很高,可以两者都混入。

需要特别指出的是,LoRA 场景下一般不需要混合数据。冻结的 base model 权重会保留通用能力,把 adapter 的有限容量集中在目标任务上效果通常更好。只有在明确观察到通用能力退化且超参调优无效时,才考虑混合数据。

关于混合比例,推荐从 20% 开始,跑一组实验看通用能力退化情况再决定加还是减。大多数 SFT 场景下 15%~25% 就够了。一般规律是 SFT 数据量越大,需要的混合数据比例越高。如果混合的是非闭源的数据,需要从统一数据格式到精细去重(步骤 2 到步骤 6)完整执行一遍,执行完后重新计算混合比例是否达到预期。

对于非监督数据的选取策略:如果担心知识遗忘,混入百科和教科书类文本;如果担心代码能力退化,混入高质量代码语料;如果担心多语言退化,混入对应语言的文本。领域分布也要匹配,假设 SFT 数据偏向医疗领域,那么选取的非监督数据应包含通用文本(防止通用能力退化,占 60%~70%)和医疗相关文本(增强领域知识,占 30%~40%)。

十一、数据打包和版本管理

数据打包和版本管理是预处理流程的最后一个环节,虽然看似是收尾工作,但对于训练效率和可复现性至关重要。

首先是应用模型的 chat 模板:根据具体的模型来 apply chat template 得到该模型训练需要的样本格式。然后是样本 packing,即把多个短样本合并为一个长样本(短样本之间用 special token 分隔),目的是提升训练效率。接着是数据样本的 tokenization。关于同一个 packed 样本中不同子样本的 attention mask 是否需要设定的问题,不同框架的支持情况不同:Megatron-LM 支持给每个样本设定自定义的 attention mask 矩阵,HF 缺省的 Trainer API 则没有这个能力。不过有实验表明是否设定这样的 attention mask 对模型效果的影响可以忽略。对于大规模训练(超过 10 万样本),建议做离线 tokenization 避免每次训练重复计算;小规模训练实验可以在线处理以获得更大的灵活性。最后生成的最终训练数据格式通常是 Arrow 或 Parquet,可以进一步进行压缩。

版本管理方面,最低限度要做到以下几点:每份数据集的原始文件有 SHA256 校验;处理脚本与数据集版本绑定(同一份脚本加同一份原始数据等于可复现的输出);不要原地修改已产出的数据集,新版本用新目录。

训练前还应当生成一份数据报告,用于自检和团队沟通。报告应包含基本统计信息(总样本数和 token 数、各数据源的样本数与占比、token 长度分布的各分位数、轮次分布)、质量指标(重复率即去重前后的样本数变化、语言分布、空回复或异常样本数量)、Packing 统计(packed 序列总数、平均每个序列包含的子样本数、padding 比例、有效 token 利用率)、以及完整的处理链路记录(每一步的过滤和丢弃数量、使用的 tokenizer 和 chat template 版本)。可视化方面建议包含 token 长度直方图、数据源占比饼图、以及 loss token 与 non-loss token 的比例图。

十二、总结

SFT 训练数据预处理是一项系统性的工程,每个环节都有其不可替代的价值。回顾整个流程,最核心的理念可以概括为:质量优先——宁精勿滥,1000 条高质量数据可能胜过 50000 条粗标数据;格式统一——数据中只存语义内容,模板和特殊 token 交给 chat_template 处理;多层去重——从精确 hash 到语义 embedding,层层过滤确保数据集的纯净度;质量把控——结合规则过滤和模型打分,多轮对话需要额外关注轮次间的依赖关系;分布均衡——多维度评估并做交叉分析,发现短板及时补充;可复现——版本管理、数据报告、处理链路的完整记录确保实验的可复现性。

需要再次强调的是,整个流程是迭代的。数据分布评估后可能需要回到数据收集步骤补充数据,混合数据策略也可能触发新一轮的清洗和去重。实践中应保持灵活,以最终模型效果为导向来调整每个环节的策略。数据预处理的工作看似繁琐,但它奠定了模型微调成功的基础。在资源有限的情况下,把时间和精力投入到数据质量的提升上,往往比调整模型架构或超参数能带来更显著的收益。

➡️ 下一步行动:

相关产品:

  • Amazon Nova — 提供前沿智能和最高性价比的基础模型
  • Amazon Bedrock — 用于构建生成式人工智能应用程序和代理的端到端平台

相关文章:

*前述特定亚马逊云科技生成式人工智能相关的服务目前在亚马逊云科技海外区域可用。亚马逊云科技中国区域相关云服务由西云数据和光环新网运营,具体信息以中国区域官网为准。

本篇作者

梁宇辉

亚马逊云科技机器学习产品技术专家,负责基于亚马逊云科技的机器学习方案的咨询与设计,
专注于机器学习的推广与应用,深度参与了很多真实客户的机器学习项目的构建以及优化。对于深度学习模型分布式训练,推荐系统和计算广告等领域具有丰富经验。


AWS 架构师中心:云端创新的引领者

探索 AWS 架构师中心,获取经实战验证的最佳实践与架构指南,助您高效构建安全、可靠的云上应用