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),对训练语料做去重时还要额外:

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

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

相关推荐
阿杰学AI3 小时前
AI核心知识129—大语言模型之 向量数据库(简洁且通俗易懂版)
数据库·人工智能·ai·语言模型·自然语言处理·向量数据库·vector database
PILIPALAPENG3 小时前
第3周 Day 2:Function Calling —— 让 Agent 听懂人话,自己干活
前端·人工智能·python
阿里云大数据AI技术3 小时前
PAI Physical AI Notebook详解8:Isaac Lab Arena 全身机器人机动+操控工作流
人工智能
高木木的博客4 小时前
数字架构智能化测试平台(1)--总纲
人工智能·python·nginx·架构
wanghowie4 小时前
11. AI 客服系统架构设计:不是调 API,而是系统工程
人工智能·系统架构
袋鼠云数栈UED团队4 小时前
基于 OpenSpec 实现规范驱动开发
前端·人工智能
Raink老师4 小时前
【AI面试临阵磨枪】什么是 Tokenization?子词分词(Subword)的优缺点?
人工智能·ai 面试
迷你可可小生4 小时前
面经(三)
人工智能·rnn·lstm
逻辑驱动的ken4 小时前
Java高频面试考点场景题09
java·开发语言·数据库·算法·oracle·哈希算法·散列表
云烟成雨TD4 小时前
Spring AI Alibaba 1.x 系列【28】Nacos Skill 管理中心功能说明
java·人工智能·spring