数据多样性探索
数据多样性(Data Diversity)贯穿大模型建设的全流程:预训练、继续预训练(Continue Pretraining)、SFT(Supervised Fine-Tuning)、以及后续的偏好优化或强化学习阶段。多样性并不是一个单一概念,它至少包含以下多个维度:
- 任务多样性:问答、摘要、对话、代码、数学推理、工具调用、结构化输出等。
- 语义多样性:同任务内部主题覆盖面(实体、概念、场景、论证方式)与表达差异。
- 语种多样性:中文/英文/多语,尤其影响跨语泛化与术语覆盖。
- 数据来源多样性:书籍、百科、论文、网页、论坛、代码仓库、文档、合成数据等。
- 结构与格式多样性:Markdown、LaTeX、表格、日志、API 文档、对话体裁等。
一个常见误区是:只追求"更多数据"。实践中,高质量 + 高覆盖的少量数据 在对齐/指令微调阶段往往更有效。典型代表是 "Less is More" 思路(如 LIMA),以及"只需要极少比例数据即可达到接近效果"的观察(例如"maybe only 0.5% data is needed"这类结论)。它们共同指向:SFT 数据应该更像"高信息密度的课程",而不是"无差别的堆量"。
1. 为什么 SFT 阶段更需要"高质量 + 多样性"
1.1 预训练与 SFT 的目标不同
- 预训练更偏向"知识注入 + 语言建模能力":同义表达、相似语义的重复句子并非完全无价值,它们仍然贡献语言统计规律与知识的"冗余强化"。
- SFT 更偏向"行为对齐 + 能力显化":你希望模型学会遵循指令、稳定输出、掌握任务格式,并能覆盖多类需求场景。此时大量语义重复的样本会造成:
- 学到的行为模式过窄(模式坍缩到少数风格/模板)
- 对长尾任务/小众意图覆盖不足
- 有效梯度被重复样本稀释
因此,SFT 的数据构建往往更强调:少而精、覆盖广、质量高。
2. 聚类筛选 SFT 样本:通用三步法
一个非常常见、且在工业界易落地的"多样性采样"框架是:
- 向量化(Embedding):把每条样本映射为语义向量(例如用 SimBERT / Sentence-BERT)。
- 聚类(Clustering):在向量空间中把相似样本归为一簇。
- 核心样本采样(Core Sampling):从每个簇中抽取代表性样本,形成"覆盖尽可能广"的子集。
其直觉是:聚类后每个簇代表一个"语义区域",从每个语义区域取样就能提升覆盖率。
为了进一步将"质量"纳入考虑,可以为每条样本设定一个质量评分 qiq_iqi(来自单独的质量模型或人工规则),并在采样中融入。
3. 三种多样性采样方案:思路、优缺点与改进动机
下面三种方案从"只考虑多样性"逐步升级到"多样性 + 质量 + 更合理的局部结构度量"。
3.1 方案 1:基于 K-Means 的聚类多样性采样
做法 :
用 K-Means 得到 KKK 个簇。最简单的多样性采样方式是:每个簇等概率采样,或者按簇大小的某种函数采样。
如果簇 ccc 的样本数为 ncn_cnc,一个常用的"簇采样概率"形式是:
p(c)=ncα∑c′nc′α p(c)=\frac{n_c^{\alpha}}{\sum_{c'} n_{c'}^{\alpha}} p(c)=∑c′nc′αncα
- 当 α=1\alpha=1α=1:按簇大小比例采样(大簇更容易被抽到)
- 当 α=0\alpha=0α=0:每个簇等概率采样(更强调覆盖)
- 当 α<0\alpha<0α<0:更倾向小簇(更强调长尾覆盖)
缺点 :
这种方案只保证簇级覆盖,不保证簇内样本质量。现实中常见情况是:某些簇可能聚集了大量低质量内容(噪声、重复、格式错误、低信息密度),如果簇被等概率采样,反而会提高低质量样本的进入概率。
直观例子 :
假设有一个簇几乎全是"短、空、敷衍回答"的对话模板,它们彼此很相似所以被聚在一起。如果按簇等概率采样,这个簇会占到一个固定配额,导致低质量样本"被多样性机制保护"。
3.2 方案 2:聚类多样性权重 + 质量权重的加权采样
为了解决"低质量簇被过采样",引入每条样本的质量权重 qiq_iqi,并把"多样性权重"和"质量权重"结合。
一种通用形式是给每条样本一个最终权重 wiw_iwi:
wi=λ⋅di+(1−λ)⋅qi w_i = \lambda \cdot d_i + (1-\lambda)\cdot q_i wi=λ⋅di+(1−λ)⋅qi
其中:
- did_idi:多样性相关权重(例如来自簇的稀有度、簇的代表性等)
- qiq_iqi:质量评分(越高越好)
- λ∈[0,1]\lambda \in [0,1]λ∈[0,1]:平衡系数
或者使用乘法形式(强调"质量与多样性必须同时好"):
wi=di⋅qi w_i = d_i \cdot q_i wi=di⋅qi
一个常见选择 :把多样性权重定义为簇级权重 di=f(nc(i))d_i = f(n_{c(i)})di=f(nc(i)),例如:
di=1nc(i) d_i = \frac{1}{n_{c(i)}} di=nc(i)1
表示:来自小簇的样本更"稀有",更应被采样。
缺点(结构性问题) :
聚类(尤其 K-Means)强依赖"全局分割",但真实语义空间并不总是"簇内比簇间更相似"。会出现你提到的现象:
有些簇间样本对之间的相似度比簇内样本对之间的相似度还要高
这意味着簇边界并不能稳定表示"语义邻域"。一旦簇划分失真,簇级多样性权重就会引入偏差:你以为抽到了新的语义区域,但实际上只是从另一个簇里抽到了一个非常相似的样本。
3.3 方案 3:KNN 局部密度(类聚程度)作为多样性权重 + 质量权重
为了避免"全局簇划分的硬边界问题",转向 局部结构:用 KNN 来度量每个样本在局部邻域中的"密度"或"冗余度"。
设第 iii 个样本的 embedding 为 eie_iei,其 kkk 个最近邻集合为 Nk(i)\mathcal{N}_k(i)Nk(i)。定义它与邻域的平均相似度:
si=1k∑j∈Nk(i)sim(ei,ej) s_i=\frac{1}{k}\sum_{j\in \mathcal{N}_k(i)} \mathrm{sim}(e_i,e_j) si=k1j∈Nk(i)∑sim(ei,ej)
其中 sim(⋅,⋅)\mathrm{sim}(\cdot,\cdot)sim(⋅,⋅) 可以是余弦相似度。
直觉:
- 若 sis_isi 很高:说明 iii 周围很多样本都和它很像,它处于"高密度重复区域",多样性贡献小
- 若 sis_isi 很低:说明它在局部更稀有,更可能代表新语义
因此可以把多样性权重定义为"反密度":
di=1−si d_i = 1 - s_i di=1−si
再与质量权重结合得到最终采样权重:
wi=di⋅qi w_i = d_i \cdot q_i wi=di⋅qi
或用加权和:
wi=λdi+(1−λ)qi w_i = \lambda d_i + (1-\lambda)q_i wi=λdi+(1−λ)qi
用"阈值相似度计数"替代平均相似度(更可控)
你提到的另一个实用版本是:统计"在相似度阈值以内的邻居数量"。设阈值为 ttt(例如 t=0.8t=0.8t=0.8),定义:
mi=∑j∈Nk(i)I(sim(ei,ej)≥t) m_i=\sum_{j\in \mathcal{N}_k(i)} \mathbb{I}\left(\mathrm{sim}(e_i,e_j) \ge t\right) mi=j∈Nk(i)∑I(sim(ei,ej)≥t)
- mim_imi 越大:说明周围有很多"高度相似"的邻居,越重复
- mim_imi 越小:说明更稀有
把它转成多样性权重(反向):
di=1−mik d_i = 1-\frac{m_i}{k} di=1−kmi
你观察到"这种权重分布更接近正态"是符合直觉的:
平均相似度容易被极端值拉动,而阈值计数更像"局部重复率",在真实语料中更稳定、更可解释。
4. 预训练的多样性:去重与"保留知识冗余"的平衡
在预训练阶段,多样性同样重要,但目标不同:预训练强调知识覆盖和语言能力,过度去重可能损害知识强化与稳健性。一个典型的相关方向是 文档去重与多样化(Document De-Duplication and Diversification),例如 D4 这类工作强调:
- 去除"近重复文档"能显著提高训练效率
- 但完全消除相似语义会损失知识冗余带来的稳定性
- 更合理的做法是:在去重的同时,保留多样性与必要的冗余
实践策略往往是:
- 对"网页模板重复、转载、镜像站"做强去重
- 对"语义相似但信息互补"的内容保留一定比例
- 对高价值领域(如数学、代码、科研)保留更高密度
5. 实际垂域经验:从种子数据到 0.5B 领域语料的可扩展流程
下面是一套非常典型、且在垂域继续预训练中被反复验证有效的流程。核心思想是:
先用少量高质量"种子数据"定义领域边界,再用召回与分类器把边界扩到大规模语料。
5.1 Step 1:尽可能多地爬取数据,形成初始语料库
这一步不追求纯净,追求覆盖与规模,用来保证"领域相关内容一定存在于库中"。
5.2 Step 2:基于聚类/相似度召回,从中文语料库筛出垂域文档并扩充种子
一个典型 pipeline:
- 关键词初筛通用数据
- 召回与种子相似度 Top-K 的文档
- 人工筛选,得到扩充种子
2.1 关键词初筛通用数据
(1)细化处理种子文本:保留段落/标题结构,把一个长文档切成多个"知识片段"(以标题+段落为单位)。
(2)关键词挖掘:对种子片段做分词/统计,得到候选关键词集合,再人工筛选形成关键词表。
(3)通用数据初筛 :从通用语料中筛出命中关键词表至少 NNN 个关键词的文档。这个 NNN 是一个可调阈值,用于控制召回率/精确率。
2.2 召回与种子相似度 Top-K 文档
对每个候选通用文档(例如取前 512 tokens 作为表示)计算与种子片段的相似度,取 Top-10 或 Top-K。
这一步的作用是从"关键词粗筛"进一步变为"语义召回"。
2.3 人工筛选
人工标注召回文档是否属于垂域,输出两类:
- 正例:垂域相关(加入扩充种子)
- 负例:非垂域(后续可用作分类器负样本)
5.3 Step 3:训练一个中文领域数据分类器,批量筛出大规模垂域语料
训练数据构建
- 正例:垂域种子文档 + Step2 扩充种子(每个文档取前 1k tokens)
- 负例:Step2 人工标注为非垂域的文档(同样取前 1k tokens)
模型选择与目标
一般用中文 BERT 家族(长度 1024 左右),目标是二分类。这里不追求极致召回,而追求高精度,确保最终筛出的语料纯净度足够高。
规模化筛选
用训练好的分类器对大库文档做预测,通过阈值筛选,最终得到例如 0.5B 量级的垂直语料。
6. 数据配比与训练顺序:把数据当作"课程"
6.1 指导思想:尽可能细的任务分桶 + 粗分类器足够好
实践上,常见建议是按任务类型精细到 3 级类别,例如:
- 一级:中文 / 英文 / code
- 二级:百科、论坛、新闻、论文、书籍、工具文档、教程、对话......
- 三级:更细的主题或任务形式(例如"数学证明""几何题""算法题""SQL 查询""API 调用")
用一个轻量分类器给每个 document 打标签即可,不要求完美。训练一个 2 万条级别的数据分类器往往就足够支撑分桶与配比实验。
6.2 常见配比经验:中 / 英 / code = 4 : 4 : 2
在很多开源大模型技术报告里,训练数据可粗分为三大类:
- 知识(中英为主)
- 代码
- 逻辑(可理解为 math + CoT 风格推理数据)
对于中文大模型,一种常见经验配比是:
- 中文尽量占一半以上(增强中文能力与本地知识覆盖)
- 英文质量通常更高,也不能太少(提升抽象推理与通用知识质量)
- math 与 code 往往显著影响推理能力上限(比例尽可能多,但要小心分布偏移)
6.3 领域继续预训练:领域数据比例要严格控制
在继续预训练(continue pretraining)中,领域数据比例过高会导致通用能力下降(遗忘 summarization、open-domain QA 等)。大量工业经验的共识是:
- 领域数据比例通常控制在 10%--15% 以下
- 超过这个范围,通用能力下降会更明显
- 不同基座模型对该阈值敏感度不同:有些模型需要更低的领域比例
这类阈值高度依赖:模型规模、原始预训练分布、领域数据与通用数据的差异度等,因此需要通过小模型实验逐步校正。
6.4 SFT 阶段领域与通用的混合比例可更高
SFT 数据规模往往比预训练小很多,且目标是行为对齐与能力激活,因此领域数据比例可以显著提高。例如:
- 领域 : 通用 = 1 : 1 是常见的起点
- 若 SFT 数据量很小,是否混合通用数据可能差异不大
- 若 SFT 数据量变大,混合通用数据能显著缓解过拟合与风格坍缩
7. 课程学习:先学什么,再学什么
课程学习(Curriculum Learning)的核心不只是"按难度排序",更是考虑 能力形成路径与遗忘:先让模型在通用分布稳定收敛,再逐步注入专项能力,同时用一定比例通用数据做"正则化"。
下面用三个典型能力课程说明"数据顺序"的作用。
7.1 代码能力课程:从通用到代码密集
一个经典范式是:
- 先大量通用 token 训练出稳健语言能力
- 再用代码密集数据强化代码生成与结构化推理
例如一种课程结构:
- 通用 token →\rightarrow→ 代码密集 token
进一步地,对某个语言(如 Python)可采用"二级专项":
- 通用 →\rightarrow→ 代码相关 →\rightarrow→ Python 代码专项
直觉:
如果一开始就大量喂代码,模型可能更早形成"代码优先"的生成偏置,影响自然语言对话质量;而先通用再专项更稳。
7.2 数学能力课程:代码基座 + 数学增量 + 少量通用正则
数学训练往往与代码强相关:符号、结构、长程依赖、严格格式、可执行性思维等。
一种常见课程结构:
- 通用 →\rightarrow→ 代码相关 →\rightarrow→ 数学相关
同时加入少量通用数据作为正则,避免模型在纯数学分布中遗忘通用能力。例如通用占比 5% 这类设计,本质上是"保持基座能力的锚点"。
7.3 长文本能力课程:先短上下文稳定,再扩窗
长上下文训练往往涉及 RoPE 等位置编码策略的调整。课程上常见做法是:
- 先在较短上下文长度上训练大规模 token(稳定收敛)
- 再切换到更长上下文长度训练较小规模 token(适配长程建模)
例如:
- 4K 上下文训练大量 token →\rightarrow→ 16K 上下文训练少量 token
直觉:
直接上长上下文训练成本很高,且容易不稳定;先短后长能显著提升训练效率与稳定性。
8. 把"多样性采样"落到一个统一视角
从上述方案与经验可以得到一个统一的理解:
- 多样性不是目的,是"覆盖更多有效语义区域"的手段
- 质量是前置约束:多样性机制不能保护低质量
- 全局聚类适合做粗覆盖,但局部密度更适合做精细去冗余
- 不同阶段(预训练 / SFT / 继续预训练)对多样性与冗余的容忍度不同
- 配比与课程是"数据多样性"在时间维度上的表达:不仅要"有什么",还要"什么时候学"
在 SFT 数据选择里,最稳健的一条路线通常是:
- 用 embedding 表示语义空间
- 用 KNN 或局部密度度量冗余
- 用质量模型过滤或加权
- 用分桶与配比保证任务覆盖
- 用课程顺序降低遗忘与偏置
这套思路的价值在于:它不依赖某一种特定算法,而是一种可组合、可迭代的"数据治理框架"。