大模型数据准备全流程:清洗、配比、去重与防泄漏 做模型训练的朋友都听过一句话垃圾进垃圾出。我头几次接触大模型训练时总觉得只要把能找到的文本全塞给模型参数量够大就一定能出效果。结果跑出来的东西要么重复要么满嘴胡话评测分数惨不忍睹。后来我才明白数据准备才是整个训练过程里最不该省事的一环很多人模型效果上不去问题往往不在网络结构而在数据。这篇分享想结合我自己准备训练数据的经验把大模型数据从哪里来、怎么洗、怎么切、怎么配比、怎么防泄漏这些事一次讲清楚。适合正在搭训练流程的工程师也适合刚入门想了解数据工程的同学。我不会堆术语重点讲清楚每个步骤背后的为什么以及踩过的坑。1. 先说结论数据准备的核心流程我每次接到一个新模型训练任务第一件事绝对不是调参而是先把数据管线画出来。大模型训练的数据准备本质上是一条标准流水线原始语料采集、基础清洗、质量过滤、去重、分词与格式转换、数据配比、打包样本最后单独抽出评测集。每一步都对应一类问题跳过任何一步后面一定会在某个地方爆发。1.1 一条清晰的数据流水线先给你看我常用的流水线结构阶段主要任务如果跳过会怎样原始语料采集确定数据来源、规模、许可数据质量和合规性没底基础清洗去HTML标签、统一字符、过滤乱码模型学到大量噪音质量过滤去掉低质量、重复、无意义文本训练容易崩或生成胡话去重精确去重 近似去重过拟合评测虚高分词/格式化训练分词器、切分序列、拼接打包训练效率低信息丢失数据配比控制各领域数据比例、epoch模型能力偏向严重评测集构建按时间或内容划分防泄漏指标不可信上线后悔你可以把这条流水线想象成做菜。食材不是买回来洗一洗就能下锅的要挑拣、切配、搭配大模型的数据处理比这还要细得多。前期花的时间越足后面训练和调优就越顺。1.2 为什么质量比数量更重要总有人觉得大模型嘛数据越多越好几十TB砸进去肯定比几GB强。这句话在“质量同等”的前提下成立但现实是低质量数据的破坏性远超想象。我见过一个团队用了大量从网页上抓的正文没有做过滤结果训练出来的模型特别喜欢在一句话里插入广告链接甚至会把解析错误的乱码当成正常语言。这就是典型的清洗不干净。另一个团队的数据配比里代码占了六成最后模型写文档时动不动冒出if __name__ __main__:。数据里有什么模型就会学成什么样。高质量数据至少要满足三点来源可靠、格式统一、内容多样。来源可靠指的是许可清晰不夹带隐私信息格式统一指编码、分隔符、换行都一致减少模型学无意义模式内容多样指覆盖不同场景避免某一类文本淹没了其他领域。数量当然重要但没有质量数量就是灾难。2. 数据从哪来语料来源与取舍训练大模型的数据一般有几个主流来源公开数据集、爬虫数据、合成数据。每个来源都有优势也都有各自的雷区。我通常在确定来源前先列出需要的能力清单再倒推需要什么数据。比如要提升代码能力就必须补充代码语料和对应的天然语言注释要提升问答能力就要保证有指令-回答结构的数据。2.1 公开数据集、爬虫与合成数据先说说公开数据集。这类数据最大的优点是省事别人已经做过一轮清洗但要注意两点一是许可是否允许用于模型训练二是很多人直接拿公开数据集的原始划分去训练里面可能包含测试集导致后面评估根本不可信。爬虫数据是大规模训练的主力尤其是想自研模型的时候。爬数据本身不难难在清洗和合规。我的建议是先确认目标网站的robots约定尽量只抓允许公开访问的内容并记录抓取时间和来源。抓到的数据噪音极大需要更强的过滤规则但这部分工作可以做出自己的数据壁垒。合成数据是近几年很热门的方向。所谓合成就是用大模型去生成训练样本。它不是造一个虚假世界而是针对性地补充一些真实数据里稀缺的格式。比如我想让模型学会按固定JSON结构输出那就可以准备一批模板交给一个像样的模型生成变体再人工抽检。合成数据的好处是可控、便宜坏处是多样性不足容易让模型形成模板腔。三种来源不是三选一我推荐的组合是以爬虫和公开数据做底子用合成数据补足特定能力短板。这样既保证规模又保证针对性。2.2 版权、隐私与许可必须绕开的坑这块我不想讲太多法律条文但有几个原则必须守。数据的来源许可一定要记录下来哪怕是内部模型也应该有个清单说明每批数据是谁、在哪、以什么方式拿到的。千万别把个人隐私数据塞进训练集尤其是邮箱、手机号、聊天记录这类。这类内容会让模型在生成时“记住”真实用户信息既危险又不可控。我见过一个朋友图省事直接下载了一堆不明来源的“清洗好”的语料包训练到一半发现生成结果里出现了大量个人地址吓得连夜把数据换掉。这种事一旦上线就不是技术问题了。建议每条数据管线都保留一个“合规检查”节点用规则或模型识别敏感信息宁可损失数据量也不能留雷。3. 清洗与过滤把垃圾挡在门外数据清洗是整个流程里最朴素但最耗时的环节。很多人以为清洗就是去一下HTML标签实际上真正要处理的问题远不止这些。3.1 清洗流水线每一步在干什么我自己的清洗管线大概是下面这个顺序去除HTML标签、脚本、样式和不可见字符。统一字符编码处理乱码和控制字符。归一化空格、换行和标点。语言识别把非目标语言的文本单独分流。过滤短句、重复句、无意义文本。过滤个人敏感信息。做一次全量去重。每一步都有对应的代码实现。先看一个最基础的清洗函数import re import unicodedata def clean_text(raw: str) - str: # 去掉HTML标签 text re.sub(r[^], , raw) # 去掉脚本和样式块 text re.sub(r(?is)(script|style).*?.*?/\1, , text) # 统一空白字符 text re.sub(r\s, , text) # 去除控制字符 text .join( ch for ch in text if unicodedata.category(ch) ! Cc ) return text.strip()这个函数只是打底真正的难点在于定义“什么算干净”。我的经验是每清洗完一批数据抽一两百条人工过一眼看看还有哪些垃圾没清掉。不要只信统计指标你亲手看过数据才知道过滤规则的阈值该怎么定。3.2 质量过滤规则与“为什么这么写”质量过滤是清洗之后的关键一步核心目标是去掉那些语法正确但毫无信息量的文本。我也给一些常用规则和原因最短长度过滤比如句子少于50个字符很多是导航文字、验证码、乱码。最长长度过滤比如超过5000字符可能是拼接错误的页面也可能是PDF解析错位。乱码比例统计非目标语言字符占比超过一定阈值直接丢弃。重复片段比例如果一句话里“哈哈哈”或“。”重复太多说明质量低。困惑度过滤用一个现成的小语言模型算一下文本困惑度高困惑度通常意味着不可读。这些规则的阈值不是拍脑袋定的最好用一小批标注过的样本画分布选一个能兼顾召回和精度的点。比如我做过一次实验把句子长度低于30字符的数据全部丢掉虽然少了10%的量但训练时loss曲线明显更稳。这就是质量提升的证明。4. Tokenization与格式模型眼中的数据清洗完的数据还是“人眼文本”但模型看到的是一串token id。这个环节处理得好不好直接决定训练效率和最终能力。4.1 分词器如何影响训练效果主流大模型大多用BPE这类子词分词方法原理不复杂从字符出发不断合并出现频率最高的相邻片段最后形成一份词表。词表的大小对训练影响很大。词表太小很多词被切得稀碎模型要费更多步去拼出语义词表太大embedding层和输出层的参数暴涨训练开销变大。我的建议是根据模型规模选择词表大小几亿参数的小模型可以用2万到4万词表几十亿参数的大模型用4万到8万比较常见。中文场景还要注意分词器最好用真实训练语料从头训练不要直接拿一个现成的英文词表硬套否则中文会被切得很别扭。另一个细节是分词器应该在清洗和去重之后训练不要在原始噪声文本上训练。原因很简单噪声文本包含大量乱码和URL分词器会把它们当成常见片段合并进词表白白占掉词表名额。4.2 Packing、拼接与注意力掩码大模型训练一般把输入变成固定长度比如2048或4096。但真实文档长短不一直接截断会丢失长文档后面一半的内容直接padding又会浪费算力。所以行业里常用packing把多个短文档按顺序拼接成一个固定长度序列中间用分隔符token隔开。拼接后还要保证注意力不会跨文档乱看。也就是说在计算注意力时需要给每个文档的token加上segment掩码让第2个文档的token看不到第1个文档的内容。否则模型可能会学会“上一篇文章末尾和下一篇文章开头有诡异关联”生成时突然串台。我见过不少新手在这个坑里栽跟头。他们只做了padding的attention mask没做文档间的mask训练出来的模型在长文本生成时经常文风突变。解决方法是把文档边界信息显式传进训练脚本在构造batch的时候生成对应的attention mask。5. 数据配比与混合比例不是拍脑袋当你有多种来源的数据下一步就是决定每种数据用多少。这个比例对模型能力的影响往往比网络结构还大。5.1 多源数据的配比策略不同任务对数据的需求不一样。我的常用做法是先列一个“能力维度表”比如通用知识、代码能力、数学推理、多轮对话、文本格式化等然后给每个维度对应的数据源定一个初始占比。初始比例一般参考几个原则通用语料占大头专业语料占补充任务定制语料占少量但高质量。举个例子一个偏代码生成的模型初始配比可能让代码相关语料占30%到40%而一个偏问答的模型指令数据可能要安排到10%以上。这个配比不是在训练前一次定死而是要结合验证集效果反复调。先小规模跑几百步看不同领域loss下降速度如果某个领域loss下不去就要检查该领域数据量是否太少或质量太低。配比调整时有个技巧不要单独增加某一类数据的绝对数量因为你做的是“配比”而不是“叠加”。当你增加一类数据的比例其他类比例会下降所以要整体考虑。我习惯把配比写成一个配置字典放在训练脚本之外方便多次实验对比。5.2 Epoch、重复数据与去重数据配比之外训练轮数epoch和重复暴露次数也很关键。很多人的误区是把所有数据都训练好几个epoch觉得多看几遍学得更牢。但重复训练会放大高频模式的缺陷尤其是重复的低质量数据会导致模型生成时不断重复同一句话。所以数据去重不是只在清洗阶段做一次还要在配比后做一次“全局去重”。全局去重是指把所有来源的数据放到一起去重而不是各自去重。因为同一个优质文本可能同时出现在公开数据集和爬虫数据里如果每个来源各自去重合并后还是有大量重复。去重可以用精确hash也可以用MinHash做近似去重。MinHash适合处理大规模数据能把文本转成多个局部hash然后比较相似度阈值一般设在0.7到0.8之间。去重后训练数据的epoch建议控制在1到3之间数据量充足的话尽量让模型见一次就好这样泛化更好。6. 验证集与防泄漏别让基线“虚高”训练大模型最后都要看评测但如果评测集建得不干净分数高得再漂亮也是自欺欺人。这是我特别想强调的一个环节。6.1 常见的泄漏路径数据泄漏最常见的路径是训练集和评测集来自同一个时间段的同一个数据源模型其实已经“背过”答案。比如你拿某百科语料抓取数据做训练又用同样百科语料里另一批页面做评测而这两个批次是从同一份导出里随意划分的那很可能有相似或重复的文本。还有一种泄漏是文档级去重做完了但句子级没有。模型训练时看到过某篇文章的前半部分评测时却要求生成后半部分于是它直接“回忆”出答案。这种泄漏非常隐蔽。6.2 如何构建靠谱的评测集我一般遵循三个原则构建评测集时间切分用某时间点之前的数据训练之后的数据评测模拟“模型没见过未来数据”的真实状态。相似去重构建评测集前把评测集中的每一篇文档和训练集做n-gram重叠检查去掉重叠度过高的样本。独立来源尽量使用与训练集不同来源的评测数据比如训练主要是爬虫网页评测就使用人工编写的题目或开源评测集。这三个原则不能只取其中一个要同时满足。特别是在做公开benchmark对比时数据泄漏会让你的排名毫无参考价值。我在实际项目里就踩过训练集里包含了一份测试题的近义改写文本结果模型在该测试集上效果惊人换一个外部测试集却立刻崩掉。从那以后防泄漏检查成了评测前必须过的关卡。7. 实操中的问题速查最后整理一些我在数据准备过程中遇到过的高频问题方便你排查自己的管线。7.1 高频故障与排查思路问题现象可能原因排查与解决训练loss不降数据质量差噪声过多抽样看原始数据提高过滤阈值生成内容重复训练数据重复度过高做全局近似去重降低epoch模型胡言乱语乱码和特殊字符未被清除检查清洗函数过滤控制字符评测分数不合常理地高评测集与训练集重叠做n-gram重叠检查换独立评测中文生成不流畅分词器词表不匹配用训练语料重新训练分词器长文本生成串台packing时未处理文档间注意力添加segment mask这些是表象背后往往是一链子问题比如清洗不彻底导致分词器学到噪声分词器又反过来影响生成质量。所以排查时不要只看单点最好把整条数据管线重新过一遍。7.2 我的几条独家经验最后分享几条我自己的实战心得算不上标准答案但都是踩过坑换来的。第一清洗完数据一定要人工抽样检查。我要求团队每轮清洗后至少抽300条文本自己看一遍再决定是否继续。统计指标能帮你筛选可疑项但只有肉眼阅读才能建议“垃圾”的真正样子。第二分词器要先拿干净语料训练再切分全量数据。很多人顺序搞反了直接切完才想到训练分词器结果分词器被噪声带偏后期很难纠正。第三用小规模实验验证数据配比。与其直接烧资源跑一个大模型不如先用小参数量模型跑少量数据快速验证某个配比是否合理。我一般先用一个几亿参数的小模型跑两天看各领域loss趋势再决定最终配比。数据准备是一份细活没有太多玄学。你愿意花时间把源头理清后面的训练和评测都会省心很多。希望这篇分享能帮你少走点弯路。