第四章 文本数据清洗:去重、分段、规范化、脏词与格式纠错(先把数据“训得动”,再谈模型“训得好”)

文章目录

你做私训模型,最常见的幻觉是:"数据只要多就行。"

结果训出来:输出更像"复读机"、口径互相打架、离线评测虚高、上线直接翻车。

这篇只解决一个工程问题:把原始文本变成"可训练资产"。并且给你两份可交付的东西:

  • 清洗管线脚本骨架(可扩展 / 可审计 / 可版本化)
  • 数据 schema(训练 / 评测通用)

00|先上"全局图":把清洗从玄学变成流水线

你不缺"更多规则",你缺的是:每一步都能解释、能复跑、能产出报告
原始数据

PDF/网页/工单/合同/FAQ
01 规范化

字符/空白/编码
02 分段结构化

标题/段落/列表/表格
03 精确去重

hash
04 近重复去重

SimHash/MinHash+LSH
05 异常过滤

超短/超长/乱码/模板壳
06 脱敏&禁词

PII/密级/合规
07 格式纠错

JSON可解析/字段统一
导出

processed.jsonl + dropped.jsonl + report.json
manifest 版本化

统计/快照/规则hash


01|去重:MinHash / SimHash 的工程思路(先消灭"重复毒药")

为什么要去重?

大规模语料天然带大量重复/近重复;不去重会导致:

  • 训练浪费算力(同一句话喂一万遍)
  • 输出更"复读机",甚至更容易"背答案"
  • train/eval 污染:评测看起来很强,其实是泄漏

Hugging Face 在大规模去重实践里把动机说得很直:重复会带来训练数据"逐字输出"、隐私风险、以及评测污染;同时去重还能提升训练效率与可协作性。(Hugging Face)

FineWeb 的数据构建也专门讨论了不同去重策略/粒度对效果的影响,说明"去重不是可选项,而是配方的一部分"。

1.1 两层去重策略(最稳)

第一层:精确去重(Exact Dedup)

  • 做法:对规范化后的文本sha1/md5
  • 目标:秒杀完全一样的样本(ROI 最高)

第二层:近重复去重(Near Dedup)

这里两把刀,各有分工:

✅ MinHash(集合相似度,适合 shingle / n-gram)
  • 逻辑:切 shingles(词/字符 n-gram)→ MinHash 近似 Jaccard → LSH 召回候选 →(可选)再算真相似度做精裁
  • 工程优势:可扩到百万/千万级,并且"可解释"(能看到重复簇)

这套流程在 Datasketch + LSH 的实践里讲得很清楚:shingling → minhash → LSH 召回候选对,再做校验。(Yury Kashnitsky)

✅ SimHash(指纹法,适合 web 文本/文档快速粗筛)
  • 逻辑:把文档映射成 64-bit 指纹,相似文档的指纹在少量 bit上不同(海明距离小)
  • 工程优势:指纹极小、比较极快,适合先粗筛

Google/Charikar 系列工作对 simhash 的描述很标准:它把高维特征压成小指纹,并利用"近重复只差少量 bit"的性质做高效检索。

⚡robin 实战建议(够用且稳)

  • 语料 < 100 万:MinHash + LSH 直接上
  • 语料更大、要更快:SimHash 粗筛 + MinHash 精筛(混合更稳)

02|分段与结构化:把"长文本"变成"可学习样本"

私有数据常见来源:PDF 解析、网页正文、会议纪要、合同条款、FAQ......最大问题是:

  • 一条样本太长(训练效率差、激活炸)
  • 结构太乱(标题/列表/表格混在一起)
  • 信息密度不均(前面是目录,后面才是干货)

你要做的是:切成"片段 + 元信息" ,保证每段语义完整 + 可定位来源

2.1 切分最小粒度(工程必做)

至少要分清:

  • title:标题/小节
  • paragraph:自然段
  • bullets:列表项(要保序)
  • table:表格(转 Markdown 或抽成结构化字段)

切分目标不是"越碎越好",而是:一段能被模型学、也能被你追责

2.2 最小够用字段(建议你直接固定)

  • title:标题/小节名
  • content:清洗后的正文片段
  • source:来源(doc_id/url/file/ticket_id)
  • loc:定位(页码/段号/行号/时间戳/字符 span)
  • tags:领域标签(可选)

03|规范化:统一口径,降低噪声(模型才不会学"脏习惯")

规范化做三件事,你就能超过 80% 的"只会堆数据"的团队:

  1. 字符规范:全角半角、空白折叠、不可见字符、异常换行
  2. 单位/格式统一:日期、金额、编号、版本号(企业文档高频雷区)
  3. 可控保留:标点/大小写/emoji 要不要保留------按任务目标定

⚡黄金句:
规范化不是"洗白一切",而是"让模型学你想让它学的部分"。


04|异常样本剔除:别把"垃圾"当数据量

异常样本不剔除,LoRA/QLoRA 很容易学出坏习惯(而且你还以为是"模型不行")。

常见异常:

  • 超短:1--2 个词(信息密度过低)
  • 超长:正文堆叠但无结构(训练慢、还污染上下文)
  • 乱码/编码错误、不可见字符爆炸
  • 高重复字符哈哈哈哈哈 / ===== / 0000000
  • 模板壳:明显同模板替换变量(会把模型训成"模板机")

建议"规则 + 统计"组合拳:

  • 规则:长度阈值、字符集比例、重复率阈值
  • 统计:语言检测、重复簇密度、(可选)困惑度异常

05|脏词与格式纠错:把"合规风险"和"结构崩坏"扼杀在训练前

5.1 脏词 / 敏感信息(最小实践就够交付)

  • PII:手机号/邮箱/证件号/精确地址 → 脱敏或替换占位符
  • 内部密级:按授权与审计策略处理(最小权限)
  • 业务禁词:你线上不能出现的表达(合规门禁)

关键点:脱敏不是"删掉就完事",要可审计(谁脱的、用的什么规则版本、命中哪些字段)。

5.2 格式纠错(结构化输出任务的生死线)

你要训练 JSON / 表格 / 固定模板输出:

清洗阶段必须保证:

  • JSON 可解析
  • 字段名统一(mapping 固定)
  • 引号/逗号/换行稳定

否则模型会学到"半截 JSON",上线必炸。


✅ 交付物 1:清洗管线脚本骨架(可直接落 repo)

下面这个骨架的目标是:可扩展、可审计、可版本化(后面接 W&B、manifest、回归集冻结都很顺)。

目录建议

text 复制代码
data-pipeline/
├── pipeline/
│   ├── 00_ingest.py
│   ├── 01_normalize.py
│   ├── 02_segment.py
│   ├── 03_dedup_exact.py
│   ├── 04_dedup_near_minhash.py
│   ├── 05_dedup_near_simhash.py
│   ├── 06_filter_anomalies.py
│   ├── 07_sanitize.py
│   ├── 08_format_fix.py
│   └── 99_export.py
├── configs/
│   └── pipeline.yaml
├── outputs/
│   ├── processed.jsonl
│   ├── dropped.jsonl
│   └── report.json
└── manifests/
    └── data_manifest_v0.1.json

核心接口(伪代码,按这个写就不会散)

python 复制代码
# pipeline/core.py
from dataclasses import dataclass
from typing import Iterable, Dict, Any, List

@dataclass
class Record:
    doc_id: str
    source: str
    loc: Dict[str, Any]
    title: str
    content: str
    meta: Dict[str, Any]

def normalize(text: str) -> str:
    # 全角半角、空白折叠、不可见字符清理、统一换行
    ...

def segment(rec: Record) -> List[Record]:
    # 标题/段落/列表切分,并继承 doc_id/source/loc
    ...

def dedup_exact(records: Iterable[Record]) -> Iterable[Record]:
    # hash(normalize(content)) 精确去重
    ...

def dedup_minhash(records: Iterable[Record]) -> Iterable[Record]:
    # MinHash + LSH 近重复聚类/保留代表样本
    ...

def dedup_simhash(records: Iterable[Record]) -> Iterable[Record]:
    # SimHash 指纹 + 海明距离阈值
    ...

def filter_anomalies(records: Iterable[Record]) -> Iterable[Record]:
    # 长度/字符比例/重复字符/乱码/模板壳
    ...

def sanitize(records: Iterable[Record]) -> Iterable[Record]:
    # PII 脱敏、禁词标注、敏感字段处理(可审计)
    ...

def format_fix(records: Iterable[Record]) -> Iterable[Record]:
    # JSON 输出类任务:修复引号/逗号/字段名映射;标记不可修复样本
    ...

去重实现落地时:MinHash+LSH 的工程路线(shingles → minhash → LSH → 候选对校验)可以直接参考 Datasketch 的实践讲解。(Yury Kashnitsky)

SimHash 的"指纹 + 海明距离检索"原理可参考经典 simhash/近重复检测论文。


✅ 交付物 2:数据 schema(训练/评测通用 JSONL)

清洗完的 processed.jsonl 建议统一成这套 schema(最小够用,后续可扩展到 SFT):

json 复制代码
{
  "id": "doc123#p07#seg03",
  "doc_id": "doc123",
  "source": "wiki_internal|ticket|pdf|url",
  "loc": { "page": 7, "para": 3, "span": [120, 560] },
  "title": "xx系统部署步骤",
  "content": "(清洗规范化后的正文)",
  "meta": {
    "lang": "zh",
    "created_at": "2026-02-10",
    "license": "internal_authorized",
    "pii_redacted": true,
    "dedup": { "exact": false, "near": true, "method": "minhash", "cluster_id": "c_102" },
    "quality": { "len": 420, "badword_hits": 0, "anomaly_flags": [] }
  }
}

如果你要直接用于指令微调(SFT),导出阶段再映射成:

  • instruction / input / output(或 chat 格式 messages

🧾 清洗验收门禁(建议贴 CI,不通过不准进训练)

  • Exact dup 比例 < 5%(按数据源可调)
  • Near dup 聚类后保留率合理(避免只剩模板壳)
  • 语言/字符集异常样本占比 < 1%
  • PII 脱敏覆盖率 100%(抽检)
  • 结构化样本(JSON)可解析率 ≥ 99%
  • dropped.jsonl 每条都有 drop_reason(可审计)
  • report.json 输出:重复率、Top 重复簇、异常分布、修复成功率(让质量"可量化")

📚参考资料(工程去重与近重复检测)

  • Hugging Face:大规模近重复去重动机与 MinHash/LSH 实战(BigCode)。(Hugging Face)
  • FineWeb:在数据构建中系统讨论去重策略与粒度影响。
  • SimHash/近重复检测:指纹法与海明距离检索的经典路线。
  • Datasketch + LSH:MinHash-LSH 近重复检测的可落地流程。(Yury Kashnitsky)
相关推荐
董厂长4 小时前
RAG 中的分块策略(Chunking Strategy)
人工智能·llm·rag·分块策略
爱听歌的周童鞋5 小时前
斯坦福大学 | CS336 | 从零开始构建语言模型 | Spring 2025 | 笔记 | Assignment 2: FlashAttention-2
llm·triton·assignment·flashattention·cs336·jit-compiler
海棠AI实验室5 小时前
第五章 指令数据怎么写:从“有用”到“可学”的指令模板库
python·模型训练·私有模型训练
_Johnny_6 小时前
LLM模型多AI服务 API 接口兼容 CLIProxyAPI
llm·cliproxyapi
Asher阿舍技术站6 小时前
【AI基础学习系列】三、LLM基础知识
人工智能·学习·llm
山顶夕景1 天前
【MLLM】科学领域Innovator-VL多模态模型
llm·多模态·图生文
Baihai IDP1 天前
Prompt caching 技术是如何实现 1 折的推理成本优化的?
人工智能·ai·llm
德育处主任1 天前
『n8n』让大模型识别图片内容
人工智能·llm·aigc
spencer_tseng1 天前
Break the Sequential Dependency of LLM Inference Using Lookahead Decoding
ai·llm