2.1 预训练数据:来源、爬取与清洗

2.1 预训练数据:来源、爬取与清洗(10T Tokens 级别的工程方法论)

预训练阶段的核心在于数据能不能规模化地获得、稳定地处理、持续地提纯 。当总体训练量级来到 10T tokens 甚至更高时,数据质量和数据分布的细微偏差,都会被训练过程不断放大,最终体现在模型的通用能力、对齐倾向和长尾鲁棒性上。

在实践中:

  • **通用预训练(Base)**常见规模约为 10T tokens
  • **继续预训练(Continued Pretraining)**通常也至少在 100B tokens (101110^{11}1011 tokens)量级,且往往需要更精细的数据配比与更强的质量控制。

2.1.1 数据来源:通用语料 + 专用语料

预训练语料通常可分为两大类:

1)通用文本数据(General Text)

覆盖范围广、规模大,目标是提升语言建模与世界知识覆盖:

  • 网页(Common Crawl 等)
  • 书籍 / 长文本(Books、Z-Library 类)
  • 论坛 / 社区对话(Reddit 等)
  • Wikipedia / 百科类

通用数据的特点是"量大、噪声也大",因此清洗与去重往往比爬取更关键。

2)专用文本数据(Specialized Text)

为了补足高级能力或特定场景能力,常见包含:

  • 多语言数据(尤其中英文与目标小语种)
  • 科学数据(论文、arXiv、教材)
  • 数学数据(题目、解题过程、数学百科)
  • 代码数据(GitHub、文档、Markdown)
  • 逻辑推理/竞赛题/高质量问答

专用数据通常"质量更高、密度更强",但也更难获取与结构化。


常见数据来源清单与特点

  • Common Crawl:开放网页数据平台,覆盖广、更新快,但噪声极高,必须强清洗。
  • GitHub:代码数据主来源,既有高质量工程代码,也有大量镜像、自动生成与重复仓库。
  • 垂类网页文本:例如数学网站、代码论坛、库文档站等,适合补强特定能力。
  • 电子书 / 教育材料 / 论文资料:知识密度高,特别适合提升"可解释推理"和"学术写作风格"。
  • 内部数据:公司业务语料或垂域语料,往往与目标任务分布更接近,但风险在于分布偏与合规成本。

开源语料的现实定位:能启动,但不保证长期上限

FineWeb、The Pile、SkyPile、RedPajama 等开源语料可以作为"启动资金",但通常会遇到:

  • 质量参差(尤其中文网页语料)
  • 重复严重(跨数据集、跨版本、跨预处理 pipeline)
  • 格式和结构差(段落混乱、广告污染、模板化文本多)
  • 领域偏差(过度依赖某类站点或平台)

因此,开源语料的合理用法往往是:先用来打底,再通过清洗、重采样、增补高质量专用数据逐步拉高上限


一个继续预训练配比的示例(100B tokens)

一个典型的继续预训练配置可能是:通用 70B tokens,总计 100B tokens。并且在总语料里常按比例控制,例如:

  • 英文 : 中文 : 代码 = 70 : 20 : 10

这种配比的直觉:

  • 英文语料仍是全球公开知识与高密度技术内容的主要载体;
  • 中文语料决定中文能力上限,但质量与分布更难控制;
  • 代码语料对结构化推理、工具化表达、格式稳定性有明显增益。

2.1.2 数据爬取:从"能抓到"到"抓得对、抓得全、抓得稳"

预训练数据的获取往往不是单一爬虫能解决,而是一个组合系统:定向抓取 + 搜索驱动抓取 + 关键词驱动抓取,并且要配合解析与结构化。

爬取方式的三种常见路线

1)定向网站爬取(Site-centric)

针对固定站点列表(白名单或重点站点),做全站或特定栏目抓取。

适用场景:

  • 领域站点明确(如 arXiv、维基百科镜像、代码文档站)
  • 质量相对可控
  • 站点结构稳定,可持续更新

典型风险:

  • 站点结构变更导致解析失败
  • 反爬策略(频率限制、验证码、JS 渲染)
2)关键词驱动爬取(Keyword-centric)

在指定站点或站群中,以关键词检索入口抓取页面,再做扩展抓取。

适用场景:

  • 目标领域(数学/代码/医学)关键词可描述
  • 希望"按主题"扩大覆盖

关键点在于:关键词集合必须持续迭代,否则会出现覆盖不足分布偏置

实例:为了补强数学推理能力,关键词可能覆盖:

  • 数学概念:eigenvalue, determinant, convex, lemma, proof
  • 题型:geometry, combinatorics, inequality
  • 表达:Let x∈Rx \in \mathbb{R}x∈R, we have, therefore, hence

如果关键词只覆盖竞赛题类,很容易导致模型输出风格"题解化",而对教材/论文的表达风格适配不足。

3)基于搜索引擎爬取(Search-centric)

先通过搜索引擎(或自建索引)获取候选 URL,再进行抓取与解析。

适用场景:

  • 站点分散、长尾强
  • 需要覆盖更多非结构化高质量内容

风险:

  • 搜索引擎结果自身带偏(SEO、热点驱动)
  • 重复链接与镜像页极多

PDF 数据:高质量但高成本的"硬骨头"

很多高密度数据(论文、书籍、教材)以 PDF 形式存在。PDF 的难点不是"下载",而是"高质量解析成结构化文本"。

为什么 PDF 难解析?
  • 公式与符号不是线性文本(∑,∫,ab\sum, \int, \frac{a}{b}∑,∫,ba 等在 PDF 内是排版对象)
  • 表格是视觉结构,不是文本流
  • 两栏排版导致阅读顺序错乱
  • 图片/图注/脚注混排
一个典型失败案例(解析错序)

两栏论文中,正确顺序是"左栏上 → 左栏下 → 右栏上 → 右栏下",但很多解析会输出:

  • 左栏上半段 → 右栏上半段 → 左栏下半段 → 右栏下半段
    导致语义断裂,甚至把公式解释拆碎。
实践策略
  • 使用专门的 PDF 解析服务通常比通用 Python 库稳定;
  • 用大模型解析 PDF 当然可行,但在海量数据场景下成本会非常高;
  • 自训 OCR/结构化解析模型是可选项,但前提是有足够的高质量对齐数据(PDF → text)。

2.1.3 数据清洗:决定上限的关键环节

如果说爬取解决"有没有",清洗解决的就是"好不好、像不像、能不能学"。

数据清洗通常包含:

  1. URL 过滤与站点策略
  2. 内容抽取(去噪、去模板)
  3. 语言识别与语种控制
  4. 低质过滤(篇章级 + 句子级)
  5. 模型打分(Quality Scoring)
  6. 数据去重(Deduplication)
  7. 测试集过滤(Test-set Filtering)

下面逐块展开。


A. URL 过滤:先在入口处"砍掉一大半垃圾"

网页语料噪声常常来自站点层面:成人、博彩、下载站、采集站、SEO 农场、内容聚合页等。URL 过滤通常包括:

  • 黑名单:直接过滤明显低质/违规域名或路径模式
  • 白名单/保留策略:对高质量来源(如教材站、官方文档站)保留更高采样率
  • URL 评分:用启发式规则或训练模型对 URL 质量做预判

一个关键实践点是:为了区分"人工精心构建的数据"与"网页噪声语料",有时会对某些高质量站点做独立处理链路,而不是简单混入网页流里。例如 arXiv、Wikipedia 这类来源,通常会单独清洗与去重,以避免被网页流的规则误伤或被当作"模板页"过滤掉。


B. 内容抽取:从 HTML 里拿到"真正的正文"

抓到 URL 只是开始,HTML 页面里充满:

  • 导航栏、目录、相关推荐
  • 广告、版权声明、弹窗文本
  • 评论区、脚注、脚本内容

内容抽取目标是得到"正文文本流",同时尽量保留段落结构。

实例:同一篇博客页面的正文可能只有 30%,剩下 70% 是侧边栏、推荐、评论与广告。

如果抽取失败,会造成模型学习到大量"关注/点赞/转发/下载/相关阅读"的垃圾模式。


C. 语言识别:保证语种分布与目标一致

当语料规模到 10T tokens 级别,语言分布如果不受控,模型会出现:

  • 目标语种能力被稀释
  • 混语输出增加
  • 特定语种的 tokenization/拼写习惯变差

语言识别通常分两步:

  1. 语言检测:识别文本语种,并给出置信度分数
  2. 阈值过滤:置信度低于阈值(如 0.65)直接丢弃或进入"低优先级池"

如果要精确控制中英文比例,可以进一步在采样阶段使用配比公式进行重采样。例如对第 iii 类语料给权重:

pi=niα∑jnjα p_i = \frac{n_i^{\alpha}}{\sum_j n_j^{\alpha}} pi=∑jnjαniα

其中:

  • nin_ini 是该类别的可用 token 数(或文档数)
  • α\alphaα 控制"均衡程度"
    • α=1\alpha = 1α=1 接近按规模采样(大类更大)
    • α<1\alpha < 1α<1 会抬升小类比例(更均衡)
    • α→0\alpha \to 0α→0 接近均匀采样

这个公式的意义是:即便某类语料很大,也不会无限吞噬训练步数;同时小类(如数学、代码)能被"抬起来",保证技能学习密度。


D. 低质过滤:篇章级 + 句子级的组合

1)篇章级别过滤(Document-level)

目标是直接丢弃"整体不正规"的文档,例如:

  • 全文重复同一段(爬取失败、模板页)
  • 极端标点比例(乱码、清洗失败)
  • 文本长度异常(过短或过长但有效信息密度极低)
  • 超多 URL、超多联系方式、超多广告关键词

可以用一些简单的比率特征辅助判断,例如"标点占比":

rpunc=NpuncNchar r_{\text{punc}} = \frac{N_{\text{punc}}}{N_{\text{char}}} rpunc=NcharNpunc

当 rpuncr_{\text{punc}}rpunc 过高时,往往意味着乱码/格式化残留;过低时可能意味着没有自然语言结构(如列表堆砌)。

另一个常用特征是"重复度",例如对文档内重复 nnn-gram 的比例:

rdup=∣DupNGrams(D)∣∣AllNGrams(D)∣ r_{\text{dup}} = \frac{\left|\text{DupNGrams}(D)\right|}{\left|\text{AllNGrams}(D)\right|} rdup=∣AllNGrams(D)∣∣DupNGrams(D)∣

  • DDD 为文档
  • DupNGrams(D)\text{DupNGrams}(D)DupNGrams(D) 为重复出现的 nnn-gram 集合
  • 比例高通常意味着模板、刷屏内容或低质聚合
2)句子级别过滤(Sentence-level)

目标是去掉文档里"无意义但高频的垃圾句式"。常见策略:

  • 全大写句子(英语场景常见)
  • 纯数字/乱码句子
  • 命中广告/引流关键词(关注、转发、点赞、扫码等)
  • 过短且命中特定模板(如"登录/注册""展开更多")

实例:

大量网页会在每段中插入"点击展开全文""登录查看更多",如果不清理,模型会学到在任何长回答中插入这些句式,形成明显的输出污染。


E. 规则清洗的边界:不要把分布"清洗歪了"

规则越多,不代表越好。最大的工程风险之一是:

  • 清洗规则过强 → 语料分布偏移 → 模型输出偏置
    例如,过滤"疫情/新冠"相关词可能把大量医学科普、公共卫生教材一起误伤;过滤某些政治敏感词会把新闻报道、历史资料一起误伤,最终导致模型在相关话题上"知识空洞"。

合理策略是:

  • 把"必删项"(色情、博彩、恶意内容)与"可疑项"(热点词、社会事件词)分开;
  • 对可疑项更多采用降权、抽样率降低,而不是直接删除;
  • 通过抽检与指标监控(困惑度分布、文体分布、主题分布)判断是否清洗过度。

F. 困惑度(Perplexity)辅助:检测"不像人话"的文本

困惑度常用于筛除"表达不自然、乱码、机器拼接"的文本。定义上,对序列 w1:Nw_{1:N}w1:N,语言模型给出的平均负对数似然为:

L=−1N∑t=1Nlog⁡p(wt∣w<t) \mathcal{L} = -\frac{1}{N}\sum_{t=1}^{N}\log p(w_t \mid w_{<t}) L=−N1t=1∑Nlogp(wt∣w<t)

对应的困惑度为:

PPL=exp⁡(L) \text{PPL} = \exp(\mathcal{L}) PPL=exp(L)

直觉解释:

  • 如果模型觉得文本很"自然",L\mathcal{L}L 小,PPL 低;
  • 如果文本像乱码、拼接、极端模板,L\mathcal{L}L 大,PPL 高。

实践中通常不是用单一阈值硬切,而是:

  • 按数据源/语种分桶统计 PPL 分布;
  • 去掉极端高 PPL 的尾部样本;
  • 避免误删"高难度但高价值"的内容(如数学证明、代码、符号密集文本)。

G. 模型打分:让模型帮你"挑数据"

当规则清洗做到一定程度后,仍会残留大量"看起来像正文但信息密度低"的样本。这时常见做法是训练/使用一个质量打分器,对样本进行质量估计,并用于:

  • 过滤(删除低分)
  • 降权(低分样本采样率降低)
  • 分层采样(高分池更多训练步数)

为什么打分器常用 BERT 类?

  • 在相同参数规模下,BERT(双向编码)对文本表征与分类通常更强;
  • Decoder-only 更擅长生成,但作为判别器未必是性价比最优。

一个常见的现实策略是:

不要追求打分器 100% 准确,打分器的价值是"让整体更好",而不是"单条样本绝对正确"。训练成本过高反而会拖累迭代效率。


2.1.4 数据去重:规模越大,去重越决定性价比

数据重复会造成:

  • 训练计算被浪费(同样内容反复学)
  • 模型记忆增强但泛化变差
  • 基准评测污染(train-test overlap)

重复大体分三类:

1)训练数据内部与跨数据集重复

  • 单文档内部重复(lines/paragraphs/n-grams)
  • 文档之间重复(镜像站、转载、聚合)
  • 数据集之间重复(同源数据不同预处理版本)

典型例子:同一来源的 Common Crawl 既被处理成某个网页数据集,又被另一条 pipeline 处理成 C4 类数据,两者混用必然重复。

2)训练迭代设置带来的"人为重复"

如果对高质量数据设置更多 epoch,本质上也是重复利用,但这是"可控的重复",目的在于:

  • 用更高训练步数强化高质量数据影响力

3)训练集与测试集重复(Test-set Filtering)

必须避免预训练语料与评测 benchmark(或内部验证集)高度相似,否则评测失真。


去重的四步法(从单位定义到测试集过滤)

第一步:确定去重单位(Unit)

不同来源应选择不同粒度:

  • 网页:可能是 line-level 或 document-level
  • 书籍:book-level(覆盖度超过阈值才算重复)
  • 代码:file-level(完全匹配或结构化特征)

选择 Unit 的核心原则:
Unit 太小会误删(把合理的引用、通用表述当重复),Unit 太大会漏删(重复段落藏在大文档里)

第二步:Unit 自身去重(内部重复)

如果一个 Unit 内部重复比例过高,往往意味着它整体是低质模板或爬取失败页,此时应直接丢弃该 Unit。

可以用前面提到的 rdupr_{\text{dup}}rdup(重复 nnn-gram 比例)或重复段落比例作为判据。

第三步:Unit 之间去重(跨文档重复)

常见方法包括:

  • 完全匹配(hash)
  • 模糊匹配(SimHash、MinHash)

模糊匹配本质上是在比较集合相似度,例如用 Jaccard 相似度描述两份文本的 shingle 集合 A,BA,BA,B:

J(A,B)=∣A∩B∣∣A∪B∣ J(A,B) = \frac{|A \cap B|}{|A \cup B|} J(A,B)=∣A∪B∣∣A∩B∣

当 J(A,B)J(A,B)J(A,B) 超过阈值(例如 0.8),可以判为"高度重复",保留其中一个。

第四步:测试集过滤(Test-set Filtering)

在确定需要的训练规模后(例如目标 10T tokens),对训练语料做去重时还要额外:

  • 与测试集/评测集做相似度匹配
  • 删除与测试集相似的训练文档

这一步的目标是确保评测公平,避免模型在预训练阶段"见过题"。

相关推荐
九.九8 小时前
ops-transformer:AI 处理器上的高性能 Transformer 算子库
人工智能·深度学习·transformer
春日见8 小时前
拉取与合并:如何让个人分支既包含你昨天的修改,也包含 develop 最新更新
大数据·人工智能·深度学习·elasticsearch·搜索引擎
恋猫de小郭8 小时前
AI 在提高你工作效率的同时,也一直在增加你的疲惫和焦虑
前端·人工智能·ai编程
寻寻觅觅☆8 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
deephub8 小时前
Agent Lightning:微软开源的框架无关 Agent 训练方案,LangChain/AutoGen 都能用
人工智能·microsoft·langchain·大语言模型·agent·强化学习
偷吃的耗子9 小时前
【CNN算法理解】:三、AlexNet 训练模块(附代码)
深度学习·算法·cnn
大模型RAG和Agent技术实践9 小时前
从零构建本地AI合同审查系统:架构设计与流式交互实战(完整源代码)
人工智能·交互·智能合同审核
老邋遢9 小时前
第三章-AI知识扫盲看这一篇就够了
人工智能
互联网江湖9 小时前
Seedance2.0炸场:长短视频们“修坝”十年,不如AI放水一天?
人工智能
PythonPioneer9 小时前
在AI技术迅猛发展的今天,传统职业该如何“踏浪前行”?
人工智能