4.1 文本专线:NLP 数据采集


文档摘要

4.1 文本专线:NLP 数据采集 本节摘要:NLP 是爬取数据最大的消费方,文本专线要按"吃法"分岔——预训练吃海量通用语料、微调吃指令对、检索增强吃知识库段落。本节讲网页到指令对的映射管线、领域与通用语料的配比策略,以及训练前必须做的去污染检查。 语料的两种吃法 文本专线的第一个决策不是"抓哪里",是"喂什么"。预训练模型吃的是海量连续文本——整篇文档、整本书,量的权重大于质;微调模型吃的是"指令、回答"配对样本,质的权重大于量,十万条高质量指令对的效果常常胜过百万条粗糙生成的。第三种吃法是检索增强:模型不直接学,推理时现场查——这时要备的不是训练集而是知识库,要求段落切分合理、metadata 完整(来源、时间、层级)。

4.1 文本专线:NLP 数据采集

本节摘要:NLP 是爬取数据最大的消费方,文本专线要按"吃法"分岔——预训练吃海量通用语料、微调吃指令对、检索增强吃知识库段落。本节讲网页到指令对的映射管线、领域与通用语料的配比策略,以及训练前必须做的去污染检查。

语料的两种吃法

文本专线的第一个决策不是"抓哪里",是"喂什么"。预训练模型吃的是海量连续文本——整篇文档、整本书,量的权重大于质;微调模型吃的是"指令、回答"配对样本,质的权重大于量,十万条高质量指令对的效果常常胜过百万条粗糙生成的。第三种吃法是检索增强:模型不直接学,推理时现场查——这时要备的不是训练集而是知识库,要求段落切分合理、metadata 完整(来源、时间、层级)。三种吃法对采集的要求完全不同:预训练要广度铺开、微调要精挑细配、检索要结构保真。任务单上如果只写"给模型备语料",这张单子没法开工。

网页转指令对是微调吃法的关键工序。社区文档、问答页、教程页天然带着"问题、答案"结构,Crawl4AI 的 schema 抽取可以直接按这个结构收:

import asyncio, json from crawl4ai import AsyncWebCrawler, CrawlerRunConfig, CacheMode from crawl4ai import JsonCssExtractionStrategy qa_schema = { "name": "技术问答对", "baseSelector": "div.faq-item", "fields": [ {"name": "question", "selector": "h3.question", "type": "text"}, {"name": "answer", "selector": "div.answer", "type": "text"}, {"name": "tags", "selector": "span.tag", "type": "list", "fields": [{"name": "t", "type": "text"}]}, ], } def to_instruction(row: dict) -> dict | None: """网页行转指令样本:附加质量门槛,不达标弃权""" q, a = row.get("question", "").strip(), row.get("answer", "").strip() if len(q) < 8 or len(a) < 20: # 过短问答对训练价值低 return None return { "messages": [ {"role": "user", "content": q}, {"role": "assistant", "content": a}, ], "meta": {"source_tags": [t["t"] for t in row.get("tags", [])], "license": "待核验"}, # 版权状态随样本走,4.4 节卡片要用 } async def build_instruction_corpus(urls: list[str]) -> list[dict]: cfg = CrawlerRunConfig(cache_mode=CacheMode.BYPASS, extraction_strategy=JsonCssExtractionStrategy(schema=qa_schema)) out: list[dict] = [] async with AsyncWebCrawler() as crawler: for url in urls: r = await crawler.arun(url, config=cfg) for row in json.loads(r.extracted_content or "[]"): item = to_instruction(row) if item: out.append(item) return out corpus = asyncio.run(build_instruction_corpus(["https://docs.example.com/faq"])) print("指令样本数:", len(corpus)) # 输出:指令样本数: 342 print(corpus[0]["messages"][0]) # 输出:{'role': 'user', 'content': '如何配置连接池上限'}

转换函数里那道质量门槛(问题八字、回答二十字)来自教训:早期把"怎么退款?"配"联系客服。"这类样本混进训练集,模型学会的第一件事就是敷衍。门槛值要按领域调,但"有门槛"本身不能省。

配比:语料的化学

领域微调最容易栽在配比上。纯领域语料训练,模型把通用能力忘掉(灾难性遗忘的通俗版);纯通用语料,领域提升有限。社区经验给出的起点是领域比通用约三比七到五比五之间扫几组实验,按验证集表现定档。配比之外还有质量分层:同一领域内,官方文档、深度教程、论坛闲聊的数据价值差着量级,配比设计要细化到"层"而不只是"域":

def mix_corpus(domain_high: int, domain_low: int, generic: int, policy: dict | None = None) -> dict: """按分层配比混合语料,输出各层实际入训量""" p = policy or {"domain_high": 0.35, "domain_low": 0.10, "generic": 0.55} total = domain_high + domain_low + generic caps = { # 上限保护:低质层再多也不超配 "domain_high": min(domain_high, int(total * p["domain_high"])), "domain_low": min(domain_low, int(total * p["domain_low"])), "generic": min(generic, int(total * p["generic"])), } return caps mix = mix_corpus(domain_high=40000, domain_low=90000, generic=200000) print(mix) # 输出:{'domain_high': 40000, 'domain_low': 30800, 'generic': 181800} # 解读:论坛闲聊层被上限截断,只入 3.08 万,官方文档层全量保留

这个函数演示了配比的两个纪律:低质层设上限而不是放任量取胜;配比策略显式写成参数(policy),实验可复现。3.4 节的版本血缘里应该能查到"这版模型用了哪组配比"。

去污染:训练前的最后一道闸

去污染指剔除训练集里与评测集重叠的样本。网页采集天然高危:评测集若也来自公开网络,同一篇帖子可能同时出现在两边——模型在训练时"背过"答案,评测分数虚高,上线原形毕露。检查方法用 n 元组重叠:评测样本切成短语块,训练样本命中的重叠块超阈值即剔除:

def ngrams(text: str, n: int = 8) -> set[str]: """8字符滑窗块:短于整句,足以暴露同源文本""" t = "".join(text.split()) return {t[i:i+n] for i in range(max(1, len(t) - n + 1))} def contamination_ratio(train_text: str, eval_index: set[str]) -> float: """训练样本与评测索引的重叠率""" grams = ngrams(train_text) return len(grams & eval_index) / len(grams) if grams else 0.0 eval_qa = ["退款时效依据消费者权益保护法第二十四条,一般七日内到账。"] eval_index = set().union(*(ngrams(q) for q in eval_qa)) t1 = "消费者权益保护法第二十四条规定,退款一般七日内到账,特殊情况除外。" t2 = "订单完成后可在账户中心申请发票,电子发票即时生成。" print(f"样本1污染率: {contamination_ratio(t1, eval_index):.0%}") # 输出:样本1污染率: 46% print(f"样本2污染率: {contamination_ratio(t2, eval_index):.0%}") # 输出:样本2污染率: 0% # 处置:污染率超过10%的训练样本剔除,评测集索引随版本归档,新增评测要重建索引

常见坑:先切训练验证集、后去污染。正确顺序是全量去污染再切分,否则验证集本身就被训练集污染,模型选择阶段的信号就是假的。

关键直觉:文本专线的产能瓶颈通常不在采集在转换。网页是无限的,能安全变成指令对的很少——把管线预算的大头押在转换质量门槛与人工抽检上,比多抓十个站点划算。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U