尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

预训练数据集构建全流程:从数据采集、清洗去重到领域配比与打包

发布时间:2026/9/29 23:40:36

资讯中心
01
ARTICLE

预训练数据集构建全流程:从数据采集、清洗去重到领域配比与打包

预训练数据集构建全流程:从数据采集、清洗去重到领域配比与打包
1. 预训练数据集构建的整体设计思路1.1 为什么数据决定了大模型的上限做预训练这行久了越来越认同一句话模型架构决定下限数据质量决定上限。很多人一上来就纠结用多大的模型、多少张卡、什么并行策略但真正跑过一轮完整预训练的人都知道数据才是那个最容易被低估、也最容易翻车的环节。一个 7B 的模型如果喂的是干净、多样、配比合理的语料效果往往能吊打一个 13B 但数据脏乱差的模型。预训练数据集构建这件事本质上是在解决三个问题从哪来、怎么洗、怎么配。从哪来是数据源的问题怎么洗是清洗和去重的问题怎么配是领域配比和采样权重的问题。这三个问题任何一个没处理好后面训练出来的模型都会出现各种奇怪的表现——比如中文说着说着突然蹦出英文、代码能力几乎为零、或者反复输出某些重复片段。我见过太多团队在数据上偷懒直接拿开源数据集拼一拼就开跑结果训练 loss 曲线看着挺漂亮一评测全是问题。所以这一篇我会把预训练数据集构建的完整流程拆开讲从原始语料的采集、清洗、去重、质量过滤到最终的配比和打包尽量把每一步的坑都点出来。1.2 数据集构建的完整链路拆解一条完整的预训练数据流水线大致可以拆成下面这几个阶段数据采集确定数据源包括网页文本、书籍、论文、代码仓库、百科、问答社区等格式统一把各种来源的数据转成统一的中间格式通常是 JSONL 或 Parquet文本提取从 HTML、PDF、EPUB 等原始格式中抽取纯文本质量过滤基于规则和模型打分剔除低质量内容去重处理包括精确去重和模糊去重MinHash LSH 是主流方案敏感与有害内容过滤这一步在合规场景下必不可少领域配比与采样按目标能力设定各领域权重Tokenization 与打包转成 token id 序列按固定长度打包成训练样本这条链路里质量过滤和去重是最耗算力也最影响效果的两步。很多团队在去重上省事结果模型在训练后期出现严重的记忆和重复问题那时候再回头处理数据成本就高得多了。1.3 方案选型的几个关键取舍在动手之前有几个取舍需要提前想清楚。第一自建流水线还是用现成工具。如果只是做小规模实验或者微调直接用 LLaMA-Factory 这类框架自带的数据处理能力就够了它支持 Alpaca、ShareGPT 等多种格式配置一个 YAML 就能跑。但如果是真正的预训练数据量在 TB 级别那就必须自建流水线因为现成工具在吞吐和定制化上都不够用。第二去重的粒度。是文档级去重、段落级去重还是句子级去重文档级去重能去掉整篇重复的文章但去不掉那种同一段话在不同文章里反复出现的情况。实践中通常是文档级 段落级组合段落级用 MinHash 做近似去重。第三质量过滤用规则还是用模型。规则过滤快、可解释、成本低但覆盖不了语义层面的低质量内容。模型过滤比如用一个小分类器打分效果更好但需要额外训练一个质量分类器而且推理成本不低。我的建议是规则先行、模型兜底先用规则干掉明显垃圾再用模型精筛。2. 数据源选择与原始语料处理2.1 主流数据源的类型与特点预训练数据源大致可以分成几类每一类的处理方式都不一样数据源类型典型代表特点处理难点网页文本Common Crawl、各类爬取语料量大、多样、噪声多正文提取、去广告、去导航书籍语料电子书、小说、教材语言规范、长文本版权、格式转换学术论文arXiv、PubMed专业性强、结构化LaTeX 公式、参考文献处理代码仓库GitHub 公开仓库逻辑性强、结构化许可证过滤、去测试代码百科问答各类百科、问答社区质量高、事实性强模板内容、引用标记中文语料中文新闻、论坛、博客中文能力关键编码问题、繁简混杂网页文本是预训练的主力通常占总量的一半以上。但网页文本的噪声也最大导航栏、广告、评论区、页脚这些内容如果不清理干净模型学到的就是一堆垃圾。书籍和论文质量高但量少通常作为精品数据按较低比例混入。代码数据对模型的推理能力有明显帮助即使你不想做代码模型混入 5% 到 10% 的代码数据也能提升模型的逻辑能力。2.2 网页正文提取的实操要点网页正文提取是数据流水线的第一道关。原始 HTML 里真正有用的正文可能只占 10% 到 20%剩下的都是模板、脚本、样式和广告。常用的提取方案有几种。基于规则的方法比如 trafilatura、readability速度快对新闻类页面效果好但对结构复杂的页面容易漏抽或误抽。基于模型的方法比如训练一个正文分类器效果更稳但需要标注数据。实践中我一般用 trafilatura 做第一遍然后用启发式规则做二次校验。几个实操中总结的校验规则正文长度小于 200 字符的直接丢弃大概率是提取失败正文中链接密度超过 30% 的丢弃说明提取到的是导航或列表页正文中重复行占比超过 50% 的丢弃说明提取到了模板内容正文中特殊符号如|、#、*占比过高的降权处理提示网页提取不要追求一步到位先粗提再精筛比一次性做完美提取要高效得多。因为后面还有质量过滤兜底前面漏掉一点没关系。2.3 格式统一与中间表示不管原始数据是什么格式最终都要统一成一种中间表示。我推荐用JSONL每行一个文档字段至少包含{ id: doc_000001, text: 文档正文内容..., source: common_crawl, domain: web, lang: zh, timestamp: 2024-01-01, meta: {url: ..., title: ...} }用 JSONL 的好处是流式处理方便一行一条记录读取和写入都不需要把整个文件加载到内存。如果数据量特别大可以转成 Parquet压缩率更高列式存储对后续按字段过滤也更友好。字段设计上有几个点要注意。source 和 domain 字段一定要保留后面做领域配比的时候全靠它。lang 字段用于语言过滤中英文混杂的语料如果不分开处理会严重影响 tokenizer 的效率。timestamp 字段在做数据版本管理时有用可以按时间切分训练集和验证集避免数据泄漏。3. 数据清洗与质量过滤的核心细节3.1 规则过滤第一道防线规则过滤是性价比最高的一步用简单的启发式规则就能干掉大量低质量内容。下面是我在实际项目中常用的一套规则按优先级排列长度过滤。太短的文档信息量不足太长的文档可能是拼接或爬取错误。一般保留 200 到 100000 字符之间的文档。这个阈值不是拍脑袋定的200 字符大约对应 100 个中文 token低于这个长度的文档很难提供有效的语言模式。重复率过滤。计算文档内 n-gram 的重复率如果 5-gram 重复率超过 0.3说明文档内部大量重复直接丢弃。这个规则能干掉很多机器生成的垃圾文本。特殊字符比例过滤。统计文档中非字母、非数字、非标点字符的占比超过 0.3 的丢弃。这类文档通常是编码错误或者乱码。语言置信度过滤。用 fastText 或 langdetect 做语言识别置信度低于 0.8 的丢弃。中英文混杂的文档要特别处理如果中文占比低于 70%通常归到英文语料里。敏感词与黑名单过滤。维护一个敏感词表命中超过阈值的文档丢弃。这一步在合规场景下是硬性要求。import re from collections import Counter def rule_filter(doc, min_len200, max_len100000): text doc[text] if len(text) min_len or len(text) max_len: return False # 5-gram 重复率 tokens text.split() if len(tokens) 50: ngrams [ .join(tokens[i:i5]) for i in range(len(tokens)-4)] counter Counter(ngrams) repeat_ratio 1 - len(counter) / len(ngrams) if repeat_ratio 0.3: return False # 特殊字符比例 special len(re.findall(r[^\w\s\u4e00-\u9fff.,!?;:\-], text)) if special / len(text) 0.3: return False return True这套规则跑下来通常能过滤掉 30% 到 50% 的原始数据。别心疼这些被过滤掉的内容如果留着对模型只有坏处没有好处。3.2 模型打分质量精筛规则过滤之后剩下的数据质量参差不齐这时候就需要模型来精筛。主流做法是训练一个质量分类器输入是文档输出是一个 0 到 1 的质量分。质量分类器的训练数据怎么来常见的有两种思路。一种是用高质量语料做正样本随机网页做负样本训练一个二分类器。另一种是用 GPT 类模型对一批文档打分然后用这些分数训练一个小模型。前者成本低但标注粗糙后者效果好但成本高。实践中我一般先用前者快速迭代等流水线稳定了再用后者精调。质量分的阈值设定很关键。阈值太高会过滤掉太多数据阈值太低又起不到筛选作用。我的经验是先看分数分布取一个能保留 60% 到 70% 数据的阈值然后人工抽检被过滤掉的数据看看有没有误杀。如果误杀率高就调低阈值如果漏放的低质量内容多就调高阈值。除了通用质量分还可以针对特定领域训练专门的分类器。比如代码质量分类器判断代码是否能编译、是否有注释、是否是测试代码。学术质量分类器判断论文是否有摘要、是否有公式、是否是综述。这些专用分类器能显著提升对应领域的数据质量。3.3 去重精确去重与模糊去重去重是预训练数据处理里最容易被低估的一步。重复数据会导致模型在训练后期反复记忆同样的内容表现为生成时反复输出某些片段或者对某些问题的回答过度自信。精确去重相对简单对文档做哈希比如 SHA256哈希值相同的文档只保留一份。这一步能干掉完全重复的文档但干不掉近似重复的。模糊去重才是重头戏。主流方案是MinHash LSH。MinHash 把文档表示成一个固定长度的签名向量两个文档的 Jaccard 相似度可以通过签名向量的相似度来估计。LSH 则把相似的签名分到同一个桶里避免两两比较。具体参数上我一般用128 个哈希函数n-gram 大小设为5对中文用字符级 5-gram对英文用词级 5-gram。相似度阈值设在0.8也就是 Jaccard 相似度超过 0.8 的文档认为是重复的只保留一份。from datasketch import MinHash, MinHashLSH def build_minhash(text, num_perm128, ngram5): m MinHash(num_permnum_perm) for i in range(len(text) - ngram 1): m.update(text[i:ingram].encode(utf-8)) return m lsh MinHashLSH(threshold0.8, num_perm128) for doc in docs: m build_minhash(doc[text]) if not lsh.query(m): lsh.insert(doc[id], m) keep.append(doc)去重的粒度也值得说道。文档级去重是最基本的但有些内容会以段落形式在不同文档里重复出现比如新闻通稿、法律条款、产品说明。这时候需要段落级去重把文档切成段落对段落做 MinHash重复段落只保留一次。段落级去重的计算量比文档级大很多通常只在文档级去重之后对剩余数据做。注意去重不要做得太狠。有些内容虽然相似但上下文不同语义也不同。比如今天天气很好这句话在不同文章里出现不应该被当成重复。所以相似度阈值不要设得太低0.8 是一个比较稳妥的值。4. 领域配比、Tokenization 与打包实操4.1 领域配比的设计逻辑数据清洗完之后下一步是决定各领域数据的配比。这个配比直接决定了模型的能力分布。配比设计没有标准答案取决于你的目标。如果你要做的是一个通用中文大模型一个参考配比是中文网页 40%、中文书籍 15%、中文百科问答 10%、英文网页 15%、英文书籍 5%、代码 10%、学术论文 5%。这个配比能保证中文能力为主同时兼顾英文和代码能力。如果你要做的是代码模型代码占比可以提到 50% 以上同时保留一定比例的英文技术文档和中文注释数据。配比设计有几个原则。第一高质量数据即使量少也要保证一定比例比如书籍和论文占比可以低但不要为零。第二代码数据对推理能力有帮助即使不做代码模型也建议混入 5% 到 10%。第三多语言数据要控制比例非目标语言占比过高会稀释目标语言的能力。配比确定之后采样的时候要注意不要简单按比例随机采样而是按领域分别采样再合并。因为不同领域的数据量差异很大如果直接按比例采样小领域的数据可能被大领域淹没。4.2 Tokenization 的关键参数Tokenization 是把文本转成 token id 序列的过程。这一步看似简单但有几个参数会显著影响训练效率和模型效果。词表大小。中文场景下词表大小一般在 50000 到 100000 之间。词表太小会导致很多词被拆成单字序列变长训练变慢。词表太大则 embedding 层参数变多而且低频 token 学不好。我一般用64000左右这是一个比较平衡的值。特殊 token。除了常规的 BOS、EOS、PAD、UNK预训练还需要一些特殊 token比如文档分隔符、段落分隔符。这些 token 能帮助模型理解文档结构。是否保留空格。对英文来说空格是重要的分词信号通常保留。对中文来说空格的处理要小心因为中文本身不用空格分词如果保留空格模型可能会把空格当成噪声。Tokenization 之后要统计一下 token 的分布。如果发现某些 token 占比异常高比如某个特殊符号占了 5%说明数据清洗有问题需要回头检查。4.3 序列打包与训练样本构造Tokenization 之后每个文档变成一个 token id 列表。这些列表长度不一需要打包成固定长度的训练样本。打包策略有两种。一种是拼接打包把多个短文档拼成一个长序列用文档分隔符隔开。另一种是截断打包长文档截断短文档填充。实践中我一般用拼接打包因为填充会浪费大量算力。拼接打包的具体做法是维护一个缓冲区不断往里塞文档的 token 序列塞满一个固定长度比如 4096就输出一个训练样本。如果某个文档太长超过固定长度就截断成多个样本。def pack_sequences(docs, max_len4096, sep_token_id1): buffer [] for doc in docs: tokens doc[input_ids] while len(tokens) max_len: buffer.extend(tokens[:max_len]) yield buffer buffer [] tokens tokens[max_len:] if len(buffer) len(tokens) 1 max_len: yield buffer buffer [] buffer.extend(tokens) buffer.append(sep_token_id) if buffer: yield buffer打包的时候要注意不要让一个文档跨越多个样本否则模型学到的上下文是断裂的。用分隔符隔开不同文档让模型知道这是不同的文档。4.4 用 LLaMA-Factory 做小规模验证如果你不想一上来就自建完整流水线可以用LLaMA-Factory做小规模验证。它支持多种数据格式配置一个 YAML 就能跑起来。dataset: - name: pretrain_demo file_name: data/pretrain_demo.jsonl format: pretrain columns: prompt: textLLaMA-Factory 的 pretrain 格式要求数据是 JSONL每行一个{text: ...}。它会自动做 tokenization 和打包。小规模验证的时候用几千条数据跑一遍看看 loss 曲线是否正常下降生成效果是否符合预期。验证通过之后再上大规模流水线。提示LLaMA-Factory 适合做验证和微调不适合做 TB 级预训练。它的数据处理是单机的吞吐有限。大规模预训练还是要自建分布式流水线。5. 常见问题与排查技巧实录5.1 数据流水线常见问题速查问题现象可能原因排查方法解决方案训练 loss 震荡大数据质量参差、配比失衡抽样检查各领域数据质量加强质量过滤调整配比模型输出重复片段去重不彻底统计训练数据重复率加强 MinHash 去重中文夹杂英文语言过滤不严统计语言分布提高语言置信度阈值代码能力差代码数据占比低检查代码数据比例提高代码数据占比训练速度慢序列长度不均、填充多统计序列长度分布改用拼接打包显存溢出序列过长、batch 过大检查 max_len 和 batch_size降低 max_len 或 batch_size模型学不到长程依赖文档被截断检查打包逻辑避免文档跨样本5.2 几个踩过的坑坑一去重阈值设太低。有一次我把 MinHash 阈值设成 0.6结果大量语义相似但内容不同的文档被误删模型的知识面明显变窄。后来调到 0.8效果好很多。去重是为了去掉真正的重复不是为了去掉相似。坑二质量分类器过拟合。用 GPT 打分训练质量分类器的时候如果训练数据分布和实际数据分布不一致分类器会过拟合到训练分布上。解决办法是定期用人工抽检校准分类器发现误判就补充训练数据。坑三Tokenization 后没检查。有一次 tokenization 之后直接开跑训练到一半发现 loss 异常。回头检查才发现某个特殊符号在数据里占比 8%tokenizer 把它单独编码成了一个 token导致这个 token 的 embedding 被过度训练。后来在清洗阶段加了一条规则过滤掉特殊符号占比过高的文档。坑四打包时文档跨样本。早期打包逻辑没写好一个文档被拆到两个样本里模型学到的上下文是断裂的。表现是模型在长文本生成时容易跑题。后来改成文档不跨样本用分隔符隔开问题解决。5.3 数据版本管理与可复现性预训练数据流水线一定要做版本管理。每次调整清洗规则、去重参数、配比都要记录版本号并且保存对应的数据快照。否则出了问题根本没法回溯。我的做法是给每个数据版本打一个 tag格式是>
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。