☰
大模型训练数据配比与清洗去重:从白皮书到工程实践
2026/10/13 10:31:20 网站建设 项目流程

简介:阿里研究院发布的《2024大模型训练数据白皮书》是一份面向AI技术团队、数据治理人员及企业决策者的专业报告,系统梳理了大模型训练数据的来源、类型、质量评估、合成数据与合规治理等关键议题,尤其适合希望深入理解训练数据全貌的从业者。压缩包仅含1个PDF文件,体积约15.12MB,由于内容按专题章节编排,适合按需查阅。报告不仅解读了大语言模型与多模态模型所需数据的特点,还逐一辨析了“大模型训练依赖用户个人信息”“中文语料短缺制约我国大模型发展”等常见误解,并从数据准确性、完整性和一致性角度分析高质量标准,阐述合成数据作为解决训练数据供给不足新方案的具体路径。结尾结合美国、中国现状,对大模型训练数据安全与隐私保护的治理之智给出了参考。目前已有1502人学习下载,可帮助读者建立从数据获取、质量评估到合规使用的完整分析框架。

1. 大模型训练数据白皮书在讲什么:数据配比才是效果上限的胜负手

同一个模型结构、同一套算力,不同团队训出来的效果却可能差出一大截,问题往往不在代码而在训练数据。某头部云厂商研究院发布的《2024大模型训练数据白皮书》PDF,核心就在讨论这件事:当模型规模和算力不再稀缺,训练数据的规模、来源、质量、配比,哪个变量才真正决定效果上限。白皮书把重点放在配比与质量上,这符合一线训练侧的普遍感受——大多数团队能凑够数据,但凑不齐“恰当配比的干净数据”。这篇笔记会把它拆成可直接落地的配比计算、清洗规则、去重阈值和排查清单,适合正在做预训练、继续预训练或垂直模型数据建设的人。

2. 数据配比怎么落到训练集:Token预算与采样权重设计

2.1 配比为什么比总量更关键:四个数据维度的取舍

白皮书里被引用最多的一句话是:模型效果的上限由数据决定。这句话在训练侧已经快成共识,但落地时大多数人只盯着数据总量,也就是常说的 Total Token 数,配比基本靠拍脑袋。我见过不少团队把公开语料下载下来,按文件大小取个比例就往训练管道里灌,结果模型总在某个领域明显偏科,回头排查才发现是权重给小了。

数据工作拆到最细其实就是四件事:规模、来源、质量、配比。规模决定训练步数和算力成本;来源决定知识覆盖面,代码、论文、论坛各有分工;质量决定噪音水平,低质语料除了浪费 token,还会把生成风格带偏;配比则决定模型把这批学力花在哪些能力上。四者优先级要看团队现状,但配比是杠杆最高的一个,因为改配比不需要重新洗数据,只需要重新采样,成本最低。

数据域典型来源常见权重区间
通用文本网页、书籍、百科、新闻50% ~ 65%
代码代码托管平台快照、技术文档20% ~ 30%
数学与推理题库、论文、推导语料3% ~ 6%
多语种其他语言的网页与书籍5% ~ 10%
其他对话数据、指令数据、杂项1% ~ 3%

为什么代码权重被抬到这么高?因为代码语料不只教模型写代码,还会强化模型在长文本里的逻辑一致性,对推理类下游任务有明显迁移。数学语料贵精不贵多,5% 以内通常就够,给多了模型容易陷入“背题模式”。表格里的区间是常见开源模型配方的反推值,和具体团队的数据体量会有出入,但作为起点足够可靠。注意这是“权重区间”而不是“期望占比”,两者关系需要靠采样脚本算清楚。

配比还和模型规模相关。1B~3B 的小模型,通用文本权重应该更高一些,代码和数学给太高会让它过早记住训练集,泛化变差;70B 级别的大模型容量大,可以承受更高的代码和数学权重,因为它能从中学到结构规律而不是逐句背下来。这也解释了为什么同一份数据,不同规模模型的最优配比点并不一样。

2.2 从目标配比到采样权重:一个最小可运行的计算脚本

配比从想法变成可执行文件,一般走这几步:先定总 Token 预算,比如 1T 还是 2T;再盘点各域数据总量,单位用 token 或 GB 都行,关键是相对量要准;接着写目标占比,按 2.1 的区间给一组初值;然后计算每个域的采样权重;最后由权重生成 manifest 文件,让训练框架按它取数。

import math # 各数据域总量(单位:GB 或 token 均可,主要用相对量) data_size = { "general_text": 8000, # 通用文本 "code": 1200, # 代码 "math": 200, # 数学/推理 "multilingual": 900, # 多语种 "other": 150, # 其他 } # 目标占比(要保证加起来约等于 1.0) target_ratio = { "general_text": 0.60, "code": 0.25, "math": 0.06, "multilingual": 0.07, "other": 0.02, } # 按 “目标占比 / sqrt(数据量) ” 计算初始权重,再归一化 weights = {} for key in data_size: weights[key] = target_ratio[key] / math.sqrt(data_size[key]) total_w = sum(weights.values()) for key in weights: weights[key] = weights[key] / total_w for key in weights: expected_ratio = weights[key] * data_size[key] / sum( weights[k] * data_size[k] for k in data_size) print(f"{key}: weight={weights[key]:.4f}, expected_token_ratio={expected_ratio:.3f}")

逻辑说明:数据域存在严重的长尾,通用文本体量最大,代码和数学体量很小。如果直接用目标占比做采样权重,小数据域会被反复抽到接近枯竭,模型反复看到同样的数学题,等于变相过拟合。脚本里先对数据量开根号再做归一化,是为了压低大类权重、抬高小类权重,让最终每个 batch 里的 token 占比更接近目标配比。

参数说明:开根号是一种常见做法,不是唯一做法。当两个域数据量差一个数量级以上时,开方压缩是安全的;如果数据量接近,直接按占比加权也没问题。真正生产环境里还要给每个文件设置重复采样上限,比如单个文件最多被抽中 20 次,防止高频文件被反复读到。脚本输出的 expected_token_ratio 才是你真正想要的配比,如果它和目标占比差太多,说明某个域的总量估算有问题,需要回去修正 data_size。

提示:把采样权重、目标占比、各域总量三个数字一起写进 manifest 文件头部,排查训练问题时先核对这三个数,能省掉大半时间。

3. 清洗与去重的执行路径:质量规则、MinHash与去重阈值

3.1 质量过滤别用一套规则打天下:分层规则与误杀控制

白皮书强调数据质量,但“质量”落到工程上必须可计算。我习惯把清洗管道拆成三层:第一层是文本形状,处理长度、乱码、控制符这类基础问题;第二层是统计量,看标点密度、字母占比、n-gram 重复率;第三层是模型打分,用语言模型的困惑度或分类器给样本打分。这样分层的理由是每层代价差别很大,字符串规则跑几十亿条数据也花不了多少时间,模型打分则要消耗大量算力,所以先用便宜规则把明显垃圾清掉,再让模型打分跑在更少的数据上。

规则层规则名建议阈值容易误杀的对象
第一层文本长度200 字符以下丢弃代码注释、数学公式片段
第一层乱码与控制符含替换符或转义控制符丢弃生僻 Unicode 文本
第二层字母/汉字占比低于 0.4 丢弃代码、符号密集文本
第二层标点密度0.02 ~ 0.20代码、SQL、日志
第二层n-gram 重复率高于 0.30 丢弃合同、法条、模板化文档
第三层语言模型困惑度按域单独设阈值代码与数学语料

表格里的“容易误杀”是我踩过坑之后补上去的。最典型的案例是代码域:一个合法的函数,标点密度经常超过 0.2,如果拿通用文本的标点规则直接套,一段段有效代码会被标记成 bad_punct 丢掉,模型代码能力自然下滑。所以规则必须按域分管道,文本、代码、数学各自独立配置,不能一套规则打天下。

import re MIN_LEN = 200 # 最短文本长度 ALPHA_RATIO = 0.4 # 字母/汉字占比下限 PUNCT_MIN = 0.02 # 标点密度下限 PUNCT_MAX = 0.20 # 标点密度上限 REP_RATIO = 0.30 # n-gram重复率上限 def text_filter(record: dict) -> dict: text = record.get("text", "") if len(text) < MIN_LEN: return {**record, "drop": True, "reason": "too_short"} alpha = sum(1 for ch in text if ch.isalpha() or "\u4e00" <= ch <= "\u9fff") if alpha / max(len(text), 1) < ALPHA_RATIO: return {**record, "drop": True, "reason": "low_alpha"} punct = sum(1 for ch in text if re.match(r"[,。!?;:、,.!?;:]", ch)) punct_ratio = punct / max(len(text), 1) if not (PUNCT_MIN <= punct_ratio <= PUNCT_MAX): return {**record, "drop": True, "reason": "bad_punct"} # 4-gram重复率:抽前2000字符估算 sample = text[:2000] grams = [sample[i:i+4] for i in range(len(sample) - 3)] if len(grams) >= 100: rep = 1 - len(set(grams)) / len(grams) if rep > REP_RATIO: return {**record, "drop": True, "reason": "high_rep"} return {**record, "drop": False, "reason": "ok"}

逻辑说明:这个过滤函数返回原始的 record 并追加 drop 和 reason 两个字段,目的是保留审计信息。每条样本被丢弃时,都会记下是哪条规则命中了它,方便事后统计各规则的命中率。判断中文时用汉字范围 \u4e00-\u9fff 比单独用 isalpha 更直观,因为中文文本的“字母占比”本身很低,用英文标准会误杀大量中文语料。标点正则里同时包含了中英文标点,符合中文网页的实际书写习惯。

参数说明:MIN_LEN、ALPHA_RATIO、PUNCT_MIN 这些值只适合作为起点。不同语料分布差异很大,建议先随机抽 10 万条样本跑一遍,看每个 reason 的命中率分布。如果某个规则的命中率超过 5%,它很可能过严了,需要放宽阈值或者拆成更细的规则。reason 字段一定要保留,排查数据问题时没有它就只能靠猜。

3.2 去重三件套:精确去重、近似去重、评估集去重

清洗完成后还有一道必做工序:去重。顺序是精确去重、近似去重、评估集去重。精确去重最简单,对全文做哈希,只去掉完全一致的文档;近似去重针对转载改写的变体,同一篇新闻换个标题、加两句话,全文哈希对不上,但语义上就是同一篇;评估集去重最容易漏,危害也最大,训练集一旦混入评估题的变体,评测分数会虚高,上线后才发现真实效果远没那么好。

步骤方法建议参数主要收效
1sha1 全文哈希无参去掉完全相同的文档
2MinHash 近似去重n-gram=5、签名数=128、阈值 0.7~0.8去掉转载变体
3与评估集比对MinHash、阈值 0.6防止训练集污染评估集

参数说明:n-gram=5 适合自然语言,代码域建议换成词级别的 token 或者直接做 AST 结构去重,否则换行缩进一变,字符五元组就全对不上,库里的近似重复会漏掉大半。Jaccard 阈值 0.8 偏保守,只去长得非常像的样本;0.6 更激进,但会误杀同主题不同来源的文章。我一般从 0.7 起步,跑完抽样看误杀情况再微调。

去重一定要全局做,不能按分片做完再把结果拼起来。不同分片之间的重复率照样很高。我之前在模拟项目 X 里图省事按分片去重,结果抽样一测重复率还有 3% 以上,等于白做一遍。如果机器跑不动全量 MinHash,可以先排序再滑动窗口只和相邻块做比对,能省不少资源,但最终还是要拿一个全局抽样桶再验一次重复率。

去重也不是越狠越好。某些文本自带模板结构,比如法条、合同、API 文档,它们的近似重复率天然高,完全去掉会让模型缺少结构先验。我常用的口径是:指定域内因模板导致的重复可以容忍,网页转载带来的重复必须清掉。这两种重复对训练的影响是完全不同的。

4. 数据评估与配比调优:别让loss骗了你

4.1 评估集怎么搭:先建一套固定基准再谈调参

配比调参最忌讳只盯总 loss。总 loss 是所有域的平均数,一个域掉了、另一个域涨了,平均之后曲线平滑得像没事发生。白皮书强调的数据评估,放到工程里就是一套固定的多能力评估集。它和训练时的验证集是两个概念:验证集从训练数据里切,反映的是拟合情况;评估集独立构建,反映的是真实能力。

能力维度建议规模关注指标
通用语言能力2000 ~ 5000 条语言接受度、困惑度
知识问答1000 ~ 3000 条准确率
代码生成/补全500 ~ 1000 条编译通过率、功能测试
数学推理1000 条以内答案正确率
多语言能力每语言 500 条准确率或困惑度
指令跟随与对话1000 条人工抽样评分

样本量不必大,但版本必须锁死。同一套评估集、同一套提示词模板、同一个打分脚本,每次数据更新都跑一遍,才能对比哪个配比版本更好。最忌讳今天用 A 套题、明天换 B 套题来证明进步,这种操作除了自我安慰没有价值。我的一般做法是评估集单独建仓,和训练数据分开管理,每次发布训练数据时同时打上评估集版本号,让训练日志和评估结果互相引用得上。

评估集和训练数据必须严格去重。如果训练数据里混入评估题的近似变体,知识问答类指标会虚高好几个点,后面所有配比决策都会被带偏。所以评估集建立之后还要跑一次 MinHash 比对,确认训练集里没有评估集的近重复样本。这一步做一次不难,难的是每次新增语料后都重复检查一遍。

4.2 配比调优的最小迭代闭环:小模型试跑与坐标搜索

配比调优的成本很高,大模型一次训练动辄上千卡时,拿它直接搜索配比不现实。常见做法是小模型代理实验:拿一个 1B~3B 的小模型,在训练数据的抽样子集上跑固定步数,我一般取 5000 到 20000 步,只改配比,其他超参全部固定,观察分域 loss 的变化。

  1. 生成多个配比版本的 manifest,并记录 weights 与 seed。
  2. 用同一份代码、同一组超参跑小模型基线。
  3. 对比各域 loss 曲线,找出“压不下去的域”。
  4. 只调整一个域的权重,继续复跑。
  5. 收敛后在大模型上做最终验证。
import random, json # 每个文件格式:{"path": "...", "domain": "code", "size": 12345} files = json.load(open("files.json")) weights = { "general_text": 0.60, "code": 0.25, "math": 0.06, "multilingual": 0.07, "other": 0.02, } def build_manifest(files, weights, num_files=100000, seed=42): rng = random.Random(seed) # 先按域分组,再对各组做内部洗牌 groups = {} for f in files: groups.setdefault(f["domain"], []).append(f) for g in groups: rng.shuffle(groups[g]) # 按权重从每个域抽出目标数量的文件 pooled = [] for dom, flist in groups.items(): n = int(num_files * weights[dom]) repeated = (flist * (n // len(flist) + 1))[:n] pooled.extend(repeated) # 最后把各域的文件混在一起再洗一次 rng.shuffle(pooled) return [f["path"] for f in pooled] manifest = build_manifest(files, weights) print("manifest size:", len(manifest))

逻辑说明:这个脚本生成的 manifest 会被训练框架按顺序消费。先把每个域的文件分别洗牌,再按权重截断,最后把各域的池子混在一起做一次全局洗牌,这样能保证 batch 内各域比例稳定,不会出现连续几十个 batch 全是代码的情况。seed 固定之后,不同配比版本之间唯一的变量就是 weights。

参数说明:num_files 控制生成清单的文件总数,一般按训练步数和 batch size 反推;weights 是每次实验要改的核心参数。调优时一次只改一个域,比如把 code 从 0.25 调到 0.30,其他全部不动,否则某个曲线的变化说不清是谁引起的。小模型代理实验多跑几轮后,可以用一种类似坐标下降的策略:先调最大的域,再调代码,最后调数学。不要做全因子网格搜索,数据域之间相关性很强,网格十几组下来边际收益很低,还容易被随机种子骗到。

配比调得多了会有点玄学,但只要坚持一次只改一个变量,翻车了也定位得到。每一轮实验都记下 weights、跑了多少步、分域 loss 排名、评估集得分,四行字的事,坚持记下来后面复盘会非常省力。调了 2~3 轮还没改善,问题大概率不在配比,而在清洗或数据来源,这时候回头检查过滤规则更有效。

注意:小模型代理实验只能用来筛配比方向,不能用来替代大模型的最终验证。小模型对数据分布的敏感度和大模型并不完全一致,代理实验效果好的配比,大模型上通常不差,但仍要跑一次最终验证才算数。

5. 训练数据翻车现场:5个高频坑与排查记录

以下五类事故,一半是我自己的血泪经验,一半是帮别人排查数据问题时遇到的。每条按现象、原因、解决的顺序写,排查时可以直接当清单用。这些坑之间还有关联,比如清洗误杀会直接表现为代码能力退化,配比失衡又会和去重不彻底叠加,所以遇到问题先定位再动手,不要一次改多个变量。

5.1 现象:训练loss降了,下游任务反而掉点

训练 loss 稳定下降,模型看起来在正常收敛,但下游任务成绩反而掉了。原因最常见的是数据重复:同一篇文章在训练集里出现多遍,模型学会的是照背而不是迁移,训练 loss 被压低了,但泛化能力变差。另一个原因是评估集污染,也就是训练数据里混入了评估题的变体。

解决方法是先做全局去重,把精确重复率压到 1% 以下;再把评估集单独存放,新数据上线前用 MinHash 和评估集做一遍重叠检查。如果掉点集中在某个能力项,多半是新增语料里混入了和这个能力项相关的评测题,按 domain 字段筛一下新增数据的来源就能定位。

5.2 现象:生成文本里反复出现页面模板话

模型生成的文本里频繁出现“正文开始”“广告”“点击查看”之类与主题无关的片段。原因是网页抓回来的语料没有把页面框架剥离干净,清洗只做了文本层规则,没做结构层清洗。页面里的导航、页脚、广告位都被当成正文灌给了模型。

解决分三步:先做 HTML 解析,只把正文节点抽出来再落文本;再统计高频模板串,命中率超过阈值的整篇过滤;最后把此类模板词沉淀成阻塞列表,定期人工复核 100 条长尾案例补充规则。只靠关键词黑名单是堵不完的,结构层清洗才是治本。

5.3 现象:中文能力明显弱于英文

中文任务比英文任务弱一截,中文生成流畅度和准确性都差。原因通常是中英文配比失衡:英文语料体量大、质量高,中文语料体量小且来源杂,如果采样权重按体量自动归一化,中文会被英文挤掉。此外中文语料里灌水内容、机器翻译文本占比高,进一步拉低了质量。

解决方法是把中文域的 loss 单独拆出来看,再调高中文采样权重 10%~20% 跑一次小模型对比。中文语料需要单独做一套过滤规则,用汉字占比而不是字母占比,困惑度阈值也要放宽,否则高质量中文长文容易被误杀。单独跑一个中文验证集来跟踪效果,比看总曲线直观得多。

5.4 现象:清洗后代码和数学能力明显退化

清洗之后代码和数学能力不升反降,代码补全输出全是语法错误。原因是清洗规则没有按域区分,通用文本的标点密度和困惑度阈值被直接套到了代码、数学语料上,导致大量有效样本被误杀。代码域的符号密度天然比自然语言高,困惑度也天然更高,拿文本域的分布去卡,误伤率非常高。

解决方法是把清洗管道按域拆分,文本、代码、数学各自配置阈值;代码域改用语法检查做过滤,而不是靠字符统计;数学域保留公式结构特征,规则尽量宽松。排查时看 drop_reason 分布,如果 low_alpha 或 bad_punct 占比畸高,基本可以断定是对应规则过严,直接调阈值再复跑。

5.5 现象:训练中后期loss曲线锯齿状震荡

训练进行到中后期,loss 曲线出现锯齿状震荡,batch 与 batch 之间波动很大。原因是 manifest 生成时洗牌粒度太粗,某个阶段连续抽到了同一个超大文件,或某一个域的数据被集中到了同一段时间;也可能是改了配比后忘了固定随机种子,不同阶段的真实数据分布漂移了。

解决方法是检查 manifest 的 token 滑动平均,确保每 10 万步各域占比稳定;洗牌前先按域分桶再做全局洗牌;超大文件按块切分,避免单个文件主导一个 batch;把 seed 写进配置,复跑时严格一致。这类问题越早发现越好,等训到中后期再回头查 manifest,成本和返工量都很大。

6. 把配比调优变成日常:领域loss面板与自动筛查技巧

配比调优真正做得好的团队,靠的不是某次灵光一现,而是把数据版本和训练曲线绑定的习惯。我自己在实践里沉淀了三条流程。

第一条是分域 loss 面板。训练日志按域拆开,每 500 步刷新一次可视化面板。看的时候只关心两件事:哪些域在稳定下降,哪些域一直压不下去。稳定下降的域不要动它,压不下去的域才是配比调整的候选。这个面板比总 loss 曲线好用得多,因为它不会让一个域的进步掩盖另一个域的失败。

第二条是给每条数据留下 meta 信息。清洗时的 drop_reason、去重后的 dup_id、source_file 这些字段看起来占空间,排查时是救命稻草。哪天模型输出出现怪异重复,按 dup_id 一查就能定位是哪篇文档被抽了太多次;哪天评估掉点,按 domain 一筛就能知道是哪个域的问题。没有 meta 的数据集是黑匣子,出了问题只能靠猜。

字段作用
doc_id全局唯一,用于回溯
domain文本、代码、数学、多语种
lang语言标记
length字符数或 token 数
drop_reason清洗管道丢弃它的原因
ppl语言模型打分值
dup_id去重后归属的重复组 ID
source_file原始文件路径

第三条是数据版本留痕。每次配比改动、每条清洗规则调整,都存成一个带时间戳的配置快照,把 manifest、weights、seed、规则参数一起归档。这个习惯相当于给自己留后悔药,训练两周后发现某个曲线不对劲,翻配置快照就能定位是哪一次改动引入的,而不是面对一堆日志毫无头绪。我吃过一次亏,在模拟项目 X 里改过配比后忘了保存 manifest,训练到第四周才想看当时的数据分布,发现配置早被覆盖,只能带着疑问从头再来。从那以后我给自己立了一个规矩:任何一次配比改动,必须连同权重大小、预期占比、随机种子一起落盘,不改不训。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询