news 2026/10/21 5:20:54

无监督阅读理解实战:摆脱标注数据,用MLM与自训练构建问答系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
无监督阅读理解实战:摆脱标注数据,用MLM与自训练构建问答系统

做过NLP的人基本都懂那个潜规则:凡是靠监督学习吃饭的任务,一半时间不是在调模型,而是在跟标注数据搏斗。尤其是阅读理解这类任务——你给模型一篇文章,让它回答“文中提到的主角为什么离开城市”,看似简单,但想凑齐一份高质量训练集,得先让标注员通读全文、设计问题、再到原文里框出答案的起止位置,还要反复检查歧义和漏洞。一个熟练标注员一天能稳定产出几百个问答对已经算效率爆棚,放到大规模落地场景里,这个成本会直接让你怀疑人生。

这也是“无监督学习”这几年被反复提起的根源之一。简单说,我们想让AI在没有标准答案的情况下,直接利用海量文本自己摸索出“如何理解一段话并回答相关问题”。本文会从原理、技术路径到可复现代码,完整拆解“无监督阅读理解”这件事,帮你在标注资源几乎为零的前提下,跑通一个能用的阅读理解流程。不管你是面临预算压力的算法工程师,还是正在入门NLP的学生,这篇文章的内容都能直接拿去做参考。

1. 摘掉“标注眼镜”:无监督学习解决阅读理解的第一性思考

1.1 标注数据为什么是NLP的“阿喀琉斯之踵”

先看清楚问题本身。机器阅读理解通常被建模成一个抽取式任务:给一段上下文文本,再给一个问题,模型需要在文本中找到连续片段作为答案。这个任务在监督设定下表现不错,前提是有大量三元组数据——(文章, 问题, 答案位置)——用来训练模型。

但这类数据远比想象中难获取。首先,设计一个好问题本身就需要创造力和对文章结构的把握,不同人问出的问题难度差异极大;其次,答案位置需要精确到字符级,稍有偏差就变成噪声样本;最后,质量控制流程几乎无法完全自动化。一个项目要启动时,往往先被标注成本吓退,这就是所谓的“标注噩梦”。

更要命的是领域迁移问题。你在通用语料上标注好数据并训练完模型,换到医疗、法律、工业设备说明书等垂直领域,效果迅速下滑,又得重新标注。现实的资源约束下,很多团队根本撑不到第一版模型上线。

无监督学习正是冲着这个痛点去的。它的目标很直接:利用几乎无限的非结构化文本,让模型在没有任何人工标注的条件下,自己构建起“阅读文章、定位关键信息、组织答案”的能力。严格来说,无监督不能做到完美的抽取式问答,但它可以把冷启动成本从“数十万标注样本”降到“只有一批原始文档”,甚至降到零。

1.2 无监督学习的本质:从数据中挖掘结构

无监督学习不是“魔法”,它的本质是用数据自身携带的结构来构造监督信号。以自然语言为例,一个句子内部存在很强的共现关系、上下文约束和冗余信息,这些都可以变成模型的学习目标。

最典型的是掩码语言模型(Masked Language Model,MLM)。随机挖掉句子中一部分词,让模型根据剩下的上下文去预测被挖掉的词,这就是一个天然的“自监督”任务。做阅读理解需要的能力——理解上下文、推断缺失信息、捕捉实体间关系——在MLM预训练中已经隐含地得到了大量锻炼。也就是说,模型其实早就会“阅读”,只是我们过去非要再喂一遍人工标注,它才愿意在下游任务上“开口答题”。

类比起来,这很像学外语的沉浸式环境。小孩学母语时,并没有人逐句告诉他“这句话是主语、那句是谓语”,他通过大量听、读、猜,最终自动掌握了语言结构。无监督阅读理解就是想复刻这个过程:让AI大量阅读原文,自己揣摩词语之间的关系,等到真正遇到问题时,它已经储备了足够的语义理解能力。

这部分被很多人忽视,但实际上非常重要:无监督不是“不训练模型”,而是“把训练目标换成模型能自己生成的内容”。理解了这一点,后面所有技术路径就都顺理成章了。

2. 三条技术路径:AI如何在没有标准答案的情况下学会阅读

2.1 掩码语言模型:让模型在“完形填空”中建立语感

MLM是目前最成熟、也最容易被低估的无监督学习路径。它的逻辑很简单:给定一段文本,随机掩盖掉其中15%的单词,让模型预测被掩盖位置的原文。因为模型不知道原文是什么,只能依赖左右两侧的上下文信息,所以每一次预测都是一次强制的上下文理解。

实操中,MLM一般作为预训练阶段的核心任务,也可以作为领域自适应的继续训练任务。比如你手上有一批法律文书,但下游要做的是“根据合同条文回答争议点”,这时不需要任何标注,只需要拿这批合同文本继续做MLM训练,模型就能快速适应法律文书的用词习惯和句式结构。

为什么这有助于阅读理解?阅读理解的标准定义是“根据给定文本回答问题”,而MLM时刻都在做类似的事:它必须根据给定文本,预测某个缺失的信息。唯一的差别是,阅读理解中缺失的信息是“用户问题的答案”,而MLM中缺失的信息是“原文中的某个词”。将二者打通后,模型对文本中任何位置的语义关系都有了很强的建模能力。

实操中有几个关键细节直接影响MLM的效果:

  • 掩盖比例一般设为15%,太低则任务太简单,模型学不到深层关系;太高则上下文信息不足,训练难以收敛。
  • 不要只做token级别的随机掩盖,尽量用whole word masking,也就是把完整词语的所有子词一起掩盖。否则模型容易通过拼凑子词预测答案,而不是理解语义。
  • 如果数据量不大,建议把MLM训练和原始预训练混合进行,避免灾难性遗忘。

我见过很多团队把MLM训练当成例行公事,随便调几个参数就跑,结果下游任务收益甚微。其实MLM训练的质量,很大程度决定了无监督阅读理解的上限。

2.2 对比学习:教会模型区分“相关”与“无关”

如果说MLM在训练模型“读懂文本”,那对比学习就是在训练模型“找出重点”。阅读理解能力中非常关键的一环是:看到一个问题时,模型要在文章中定位与问题相关的片段,忽略无关信息。

对比学习的核心操作是构造“正样本对”和“负样本对”。比如同一篇文档中,连续的两个句子语义紧密相关,可以作为正样本对;不同文档中的句子语义差异较大,可以作为负样本对。模型的任务是让正样本对在向量空间中的距离更近,负样本对更远。

放到无监督阅读理解中,一种常见的做法是:把“问题”和“包含答案的文档片段”视作正样本对,把“问题”和“随机文档片段”视作负样本对。问题是,没有标注时我们不知道哪个片段包含答案。不过没关系,我们可以利用无监督方式构造近似正样本。

例如,假设用户问题来自文档A,那么文档A中的任意一个完整段落,天然比文档B中的段落更可能与问题相关。这种粗略的相关性信号,虽然不如人工标注那么精确,但已经足够训练一个不错的文本匹配模型。

实操中,对比学习通常采用如下流程:

  • 用编码器将句子/段落转换为向量。
  • 在一个batch内构造多个正负样本对。
  • 使用类似InfoNCE的损失函数拉近正样本、推远负样本。

这套思路非常灵活,既可以用来做“问题到段落”的粗筛,也可以用来做“问题到句子”的精排。

需要注意,对比学习非常依赖batch size。batch越大,负样本越丰富,效果越好。有条件的话,batch size至少开到128以上,可以用梯度累积来模拟大batch。

2.3 自训练与伪标注:模型给自己出题,自己批改

自训练是另一种无监督/半监督路线,思路更简单粗暴:先用某种基础方法让模型对无标注数据做出预测,接着把高置信度的预测结果当作“伪标注”,再拿伪标注数据继续训练模型。

阅读理解场景中,这套流程可以这样展开:

  1. 在少量有标注数据上(甚至完全没有)训练一个初始模型。即使初始模型效果很差,也没关系。
  2. 让初始模型对大量无标注文档进行预测,产出候选问答对。
  3. 根据模型输出的置信度、答案长度、位置分布等信息,筛选出可靠样本。
  4. 将可靠样本加入训练集,重新训练模型。
  5. 重复2到4步若干轮。

如果你连少量标注都没有,也可以完全无监督启动:用规则、词典、语言模型本身来构造初始训练集。比如从文档中抽取名词短语作为候选答案,再利用MLM模型判断哪些候选答案在原文中是“实体”且具有信息量,从而生成弱标注样本。

这轮迭代是典型的“AI教AI”,效果上限取决于筛选策略。如果筛选太严,样本量太小,模型学不到新东西;如果筛得太松,噪声大量涌入,模型被带偏,后面几轮会越来越离谱。所以伪标注的置信度阈值和多样性控制,是自训练技术中最核心的工程问题。

3. 从零搭建:一个无监督阅读理解系统的完整实操

3.1 环境与数据准备

先说明一下,这里展示的是一个能跑通的简化流程,不代表工业级最终方案,但足以让你直观理解“无监督”每一步在做什么。

环境方面,核心依赖是PyTorch和transformers库。数据方面,不需要任何问答标注,只需要一批纯文本文档。示例中我用一个本地文本文件作为语料,实际项目里可以用爬虫抓取行业文章、产品文档、公开报告等,注意版权与合规即可。

import torch from transformers import AutoTokenizer, AutoModelForMaskedLM, DataCollatorForLanguageModeling, Trainer, TrainingArguments from datasets import Dataset # 1. 准备无标注语料,每行一段文本 with open("corpus.txt", "r", encoding="utf-8") as f: lines = [line.strip() for line in f if len(line.strip()) > 20] dataset = Dataset.from_dict({"text": lines})

这里没有“正确答案”,但每一段文本都是天然的MLM训练样本。语料规模越大、覆盖面越广,后续得到的阅读能力越扎实。

3.2 掩码语言模型训练实战

加载一个基础编码器模型,然后进行领域MLM继续训练。这里选择编码器架构,因为它更适合抽取式阅读理解任务。

model_name = "your-pretrained-encoder" # 替换为可用的预训练编码器模型 tokenizer = AutoTokenizer.from_pretrained(model_name) model = AutoModelForMaskedLM.from_pretrained(model_name) def tokenize_function(examples): return tokenizer(examples["text"], truncation=True, padding="max_length", max_length=512) tokenized_dataset = dataset.map(tokenize_function, batched=True, remove_columns=["text"]) data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm_probability=0.15) training_args = TrainingArguments( output_dir="./mlm_checkpoints", per_device_train_batch_size=16, gradient_accumulation_steps=4, learning_rate=5e-5, num_train_epochs=3, save_steps=1000, logging_steps=100, fp16=True, ) trainer = Trainer( model=model, args=training_args, train_dataset=tokenized_dataset, data_collator=data_collator, ) trainer.train()

几个参数值得说道说道:

  • mlm_probability固定为0.15是经验值,不需要频繁调整。
  • 如果语料小于10万句,建议学习率降到2e-5,epochs减少到2,防止过拟合到小语料。
  • fp16在支持混合精度的显卡上能明显加快训练、减少显存占用,但务必确认操作的稳定性。

训练完成后,这个模型已经具备了针对当前领域文本的上下文理解能力。下一步我们用它来做无监督的答案定位。

3.3 用掩码预测实现无监督答案定位

核心思路是把“阅读理解”转化为“掩码预测”。具体做法是:将用户问题与文档片段拼接,把文档中每个候选答案位置分别掩码掉,然后计算模型对掩码位置的预测概率。概率越高,说明该片段越可能是用户要找的答案。

为了减少计算量,先进行粗筛。候选答案通常是文档中的名词短语或命名实体,可以用简单的词性规则抽取,这里我用一个简化版本演示流程:

def get_candidate_spans(doc, max_span_len=8): # 简化版:按标点切分短句,再把短句中的连续词窗作为候选 sent = doc.split("。") candidates = [] for s in sent: words = s.split() for i in range(len(words)): for j in range(i+1, min(i+max_span_len, len(words))+1): span = " ".join(words[i:j]) if 2 <= len(words[i:j]) <= max_span_len: candidates.append(span) return candidates def score_answer(question, doc, span, model, tokenizer): # 将span替换为[mask],让模型预测span的概率 masked_doc = doc.replace(span, tokenizer.mask_token, 1) text = question + tokenizer.sep_token + masked_doc inputs = tokenizer(text, return_tensors="pt", truncation=True, max_length=512) mask_position = (inputs["input_ids"] == tokenizer.mask_token_id).nonzero()[0, 1].item() with torch.no_grad(): outputs = model(**inputs) logits = outputs.logits[0, mask_position] span_tokens = tokenizer.encode(span, add_special_tokens=False) score = sum([logits[t].item() for t in span_tokens]) / len(span_tokens) return score

对所有候选span计算分数后,取最高分的span作为预测答案。这套方法听起来有点笨,但它是纯无监督的,不需要任何训练标注,而且实际效果并不差——模型在MLM训练中已经记住了大量常见搭配和语义关联,足够识别出“哪个位置填上去最像答案”。

如果觉得逐span计算太慢,可以把候选span列表按长度聚合,一次性构造多个掩码样本送入batch推理,速度能提升不少。工程上具体如何做,取决于你的实时性要求。

4. 踩坑实录:无监督阅读理解常见问题与排查技巧

4.1 模型“自嗨”:学到的特征不具泛化性

无监督模型最容易出现的毛病是“看起来损失很低,实际问答效果一塌糊涂”。原因通常在于,模型只是背下了训练语料中的某些高频模板,并没有真正理解语义。比如,你问“这篇故事发生在哪个季节”,模型总是倾向于预测文档中出现频率最高的名词,而不是正确答案。

排查技巧:单独构造一批测试问题,这些问题的答案在文档中出现了但并非高频词。如果模型仍然给出高频词,说明MLM训练不足或语料太单一。解决办法是增加语料多样性、提高whole word masking比例,并检查是否有数据泄露导致模型记忆了答案。

另一个常见问题是学习率过大导致模型在MLM阶段丢失原有预训练知识。如果loss下降过快,但下游评估反而变差,大概率是灾难性遗忘。此时要降低学习率,或者在训练目标中混合一部分通用语料的MLM任务。

4.2 伪标注噪声污染:如何设置过滤机制

自训练路线中,伪标注的质量直接决定迭代效果。很多开发者只根据置信度分数过滤,但置信度高并不等于正确。例如模型对某个错误答案给出非常自信的预测,因为那个位置在语法上很通顺,但语义上并不是问题要问的内容。

我建议从三个维度共同过滤:

  • 置信度阈值:初步筛选,通常取0.7以上。
  • 答案位置合理性:预测答案不应横跨多个不相关句子,不应包含句子开头的虚词。
  • 答案可验证性:如果候选答案是一个命名实体,可以用外部知识库或词表校验;如果是普通短语,可以要求问题与文档片段的相似度超过某个下限。

如果条件允许,加一个“多模型投票”机制效果更好:同一个问题用两个不同随机种子训练得到的模型分别预测,只有二者答案一致时,才保留该伪标注样本。

4.3 训练不收敛与显存不足的工程化解决

无监督MLM训练过程中,loss曲线通常表现为“快速下降后缓慢波动”,这属于正常现象。但如果loss始终不下降,或者反复震荡,优先检查数据预处理:填充长度是否统一、特殊token是否正确、语料是否有大量乱码。

显存不足几乎是必踩的坑。max_length=512、batch_size=16,再加上gradient_accumulation_steps=4,很容易碰触显存上限。我的习惯是优先降低batch_size到8或4,然后增加梯度累积步数,尽量保持有效batch size不变,这样既缓解显存压力,又不影响收敛。如果显存依旧不够,可以开启gradient_checkpointing,用少量训练时间换取显存空间,效果非常明显。

还有一个小技巧:不要一开始就用512的序列长度。先用128或256做初步训练,让模型学会大部分短文本语义,再切换到512做收尾训练。这样不仅速度快,还能提升长文本理解能力。

4.4 评估指标怎么定:无监督任务没有标准答案

最后聊一个方法论层面的问题:无监督阅读理解怎么评估?没有人工标注,很难算精确的F1和EM。我的实践经验是,构建一个小规模的“影子测试集”和“人工抽查池”。

影子测试集:从公开已有标注的数据集中抽取100到200条样本,隐藏掉答案,只用来评估最终模型。虽然这些样本没有参与训练,但能在一定程度上反映模型的真实阅读能力。

人工抽查池:随机抽20条模型预测结果,让人眼判断“这个答案是否能在原文中找到依据”。不需要精确标注,只需要判断“靠谱”和“不靠谱”两个类别。这个工作10分钟就能完成,却能避免被单一指标欺骗。

这两类评估手段成本都很低,但对无监督系统的迭代方向至关重要。否则你根本无法判断调参到底让模型变好了还是变坏了。

如果你正准备在标注预算几乎为零的项目里使用阅读理解技术,建议先把MLM训练和伪标注流程跑通,用影子测试集看一轮效果。不要指望一步到位,无监督系统需要几轮迭代才能趋于稳定。但它的长期价值非常大——每一次新语料的注入都不需要人工介入,模型自己会持续成长。

我个人在实际操作中最大的体会是:无监督模式真正解决的并不是“完全不用标注”,而是把标注从“前置的大规模工程”变成了“后置的小规模抽检”。这个转变,对很多资源有限的团队来说,可能才是最终被采纳的决定性因素。数据永远是越攒越多,标注成本却不会自己降下来,学会让AI自己从文本里吸收知识,时间越久,优势越明显。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 5:20:28

极简标题“rea”拆解指南:从模糊缩写到可执行技术方案

1. 从“rea”这个标题说起&#xff1a;一个被低估的通用缩写第一次看到“rea”这个标题的时候&#xff0c;我脑子里蹦出来的第一反应是——这大概率又是一个被缩写玩坏的项目名。在技术圈混久了你会发现&#xff0c;越是短到只有三个字母的标题&#xff0c;背后藏的东西往往越不…

作者头像 李华
网站建设 2026/10/21 5:20:12

Opencode + Sisyphus:搭建全自动AI编码外包流水线

今天不聊“AI能不能写代码”这种老掉牙的问题了&#xff0c;直接说怎么把写代码这件事变成“发一句任务&#xff0c;全程不用盯”的外包流水线。我试过在很多场景下用Cursor辅助编码&#xff0c;日常小需求确实省事&#xff0c;但凡是项目级、需要连续改十几个文件、跑一轮测试…

作者头像 李华
网站建设 2026/10/21 5:20:10

Windows 7 SP1与Server 2008 R2最终版补丁集成镜像制作指南

很多运维老哥手里都还压着几台 Win7 工控机和 Server 2008 R2 老服务器&#xff0c;不是不想换&#xff0c;是真换不动。这几个月我一直在琢磨怎么把补丁一次到位&#xff0c;直到看到 Windows 7 SP1 & Server 2008 R2 2026年2月最终版这个概念&#xff0c;我立刻动手重新做…

作者头像 李华
网站建设 2026/10/21 5:19:10

DELL R730 装 Windows Server 2008 R2 驱动全攻略:从 F6 加载到离线集成

简介&#xff1a;这份驱动包面向需要在Windows Server 2008 R2 64位系统上部署DELL PowerEdge R730服务器的运维人员与装机工程师&#xff0c;用于解决服务器重装或系统迁移后网卡、芯片组、磁盘阵列卡、显卡等设备缺少匹配驱动、无法正常识别的问题。包内共96个文件&#xff0…

作者头像 李华
网站建设 2026/10/21 5:18:40

从模糊的skills到可落地的技能矩阵:能力拆解与运营框架

1. 从“skills”这个标题说起&#xff1a;一个被严重低估的元概念“skills”这个词&#xff0c;单独拎出来看&#xff0c;信息量几乎为零。它不像“如何用Python做数据清洗”那样具体&#xff0c;也不像“三小时搭建个人博客”那样有明确交付物。但恰恰是这种极简的标题&#x…

作者头像 李华
网站建设 2026/10/21 5:18:39

knowledge-work-plugins:知识工作插件化流水线设计与实践

1. 这个插件体系到底在解决什么问题第一次看到 knowledge-work-plugins 这个名字&#xff0c;我脑子里蹦出来的第一个念头是&#xff1a;又是一个插件集合&#xff1f;市面上插件框架一抓一大把&#xff0c;凭什么这个值得单独拿出来聊。但真正翻完它的设计思路和几个典型插件的…

作者头像 李华