☰
开放关系抽取的关系知识迁移:从监督数据到无监督数据
2026/10/15 11:59:55 网站建设 项目流程

做关系抽取最让人头疼的是什么?不是模型训练不起来,而是数据永远不够用。尤其是当你想做一个开放关系抽取(Open Relation Extraction)系统时,这个问题会被无限放大。封闭集合下你还能靠标注几千条句子把十几个关系刷出不错的F1,但一旦放开到开放场景,关系类型可能成百上千,且不断有新关系冒出来,标注工作就变成了无底洞。我最初在一个非结构化文本挖掘项目里就是被这个问题卡住,明明手里有大量无标签文本,却因为缺少关系标签白白浪费掉。后来我认真梳理了标题里这条思路——从监督数据到无监督数据的关系知识迁移,把已有标注数据里学到的关系知识,迁移到完全没有标注的数据上,整个系统的生产力立刻不一样了。

这篇文章就围绕这个思路展开,我会拆解它背后的核心问题、关键组件、训练流程,以及我在实测过程中踩过的各种坑。如果你正面临“标注数据不够,但无标注语料一大堆”的困境,这篇文章应该能帮你把这条路走通。

1. 开放关系抽取的“数据鸿沟”:为什么标注数据永远不够用

1.1 从封闭到开放:任务定义与真正的难点

传统关系抽取是这么定义的:预先给定一个关系类型集合,比如“出生于”“任职于”“治疗某种疾病”等等,然后训练一个分类器,把句子中的实体对映射到这些预定义的关系上。这种做法在限定领域、限定关系集合时很有效,因为类别空间是闭合的,甚至可以用纯规则、远程监督或者小规模人工标注就能拿到不错的效果。

但到了开放关系抽取,任务定义变了:你事先不知道用户会关心什么关系,也不知道文本里会产生哪些关系。系统需要能够抽出任意实体对之间的关系,并且常常要用自然语言短语来描述这个关系,而不是映射到一个封闭集合。这就带来两个麻烦:第一,关系类别的粒度怎么定?“张三的父亲”和“张三的爸爸”算不算同一个关系?“参与研发”和“主持研发”又怎么区分?第二,标注代价几乎不可控。封闭场景下标注几百个关系类别的成本已经很高,开放场景下你连“一共有多少个关系”都不知道,自然没法用传统的静态标签集。

很多团队一开始会用规则模板或者依赖外部知识库去自动生成标注,但规则模板覆盖有限,外部知识库在垂直领域又经常稀疏。最终你大概率会陷入一个死局:模型效果不够好,需要更多标注;但更多标注又带来更高成本,于是继续用弱监督,效果继续差。与其在死局里打转,倒不如换一个思路:既然我已经有了一部分高质量的监督数据(哪怕领域不同、关系集合不同),为什么不把从这些数据里学到的“关系判断能力”迁移到那些没有标注的数据上去呢?

1.2 监督数据与无监督数据之间的“知识落差”

这里需要先分清两类数据。监督数据指带有关系标签的句子,比如“某公司在某年发布了某产品”标注为“发布产品”;无监督数据则是大量纯文本,没有任何关系标注。注意,监督数据未必和目标数据来自同一个领域。比如监督数据可能是从新闻稿里人工标注出来的,而你的无监督语料是社交媒体、客服聊天记录或者医疗病历。领域不同、文本风格不同、实体类型也不同,这是迁移的第一个落差。

第二个落差是关系分布不同。监督数据里的关系集合往往是基于设计者当时的需求挑选出来的,肯定覆盖不全;而无监督数据里真实存在的关系,可能有很多在监督数据里完全没有出现过。打个比方,你在学校课堂上学过“猫科动物”“犬科动物”这类生物分类,现在让你去街头识别路上的宠物狗,你能认出大部分,但突然冒出来一只狐狸,你可能会犹豫它到底算不算犬科。关系迁移也是一样,监督数据教你认识了“A就职于B”“A收购B”这些关系,但没有教过你“A被任命为B的CEO”,当无监督数据里大量出现这种新关系时,模型要么强行把它归到相近的老关系里,要么干脆漏掉。

还有一个很容易被忽略的落差是语义表达的多样性。同一个关系在不同数据源里的措辞差异极大。新闻里说“某某接任某某公司首席执行官”,论坛里可能说“某某现在是某某公司的老大”,口语化和书面语、显式表达和隐式暗示,都会让监督数据里学到的特征失效。所以,关系知识迁移的本质不是把一个分类模型直接搬到另一个数据集上,而是要让模型具备一种能力:即使在新的语言环境和新的关系语境下,也能抽象出“实体之间的潜在关系”并准确表达出来。

1.3 迁移关系的核心挑战:关系语义漂移与类别错配

理解了落差之后,就会明白迁移的最大难点并不在于模型结构,而在于“关系语义”如何在不同数据之间保持一致。我把它拆成两个具体问题。

第一个是关系语义漂移。同一个关系,在源数据里的正例可能都是“A是B的上司”这种句式,而在目标数据里,同样的关系可能写成“B向A汇报工作”。表面特征完全不一样,但语义内核相同。反过来,源数据里的“某公司发布某产品”和无监督数据里“某人发布一条状态”都包含“发布”这个词,但前者的关系是产品发布,后者是社交动态发布。如果模型只靠词汇特征,就很容易发生漂移。要抑制漂移,就不能只看字面,还要结合实体类型、上下文语义、甚至常识知识来综合判断。

第二个是类别错配。监督数据中的关系标签集合和目标数据中真实存在的关系集合,两边的对应关系是不完整的,甚至可能是矛盾的。比如监督数据里有“创始人”关系,无监督数据里大量出现“当前CEO”这个语义,二者有交集但不等价。你没法简单地做成一个标签映射表,因为开放关系的类别是开放的,新关系随时可能出现。这时候就不能再用“类别的ID对应”来迁移,而要用更柔性的方式,比如把每个关系表示成一个连续语义空间中的原型向量,让模型在无监督数据上通过相似度来做软匹配,而不是硬编码到一个固定分类头上。

2. 关系知识迁移的关键设计:三个必须拆解的组件

看了不少模仿这个标题思路的工作之后,我逐渐意识到,真正能跑通的方案,无论论文里包装成什么样,都离不开三个核心组件:特征空间对齐、关系类型映射、置信度自训练。这三个组件一环扣一环,缺一个都不行。

2.1 特征空间对齐:让两个数据集“说同一种语言”

迁移学习里最经典的问题就是数据分布不一致。在关系抽取场景下,监督数据和无监督数据的分布差异更麻烦:不仅句子结构不同,连实体类型都可能不同。直接拿源数据训练出的模型去给目标数据打标签,效果通常很惨,因为模型的特征分布是扭曲的。

我当时采用的方案是共享编码器加对抗对齐。具体来说,句子和实体对会被编码成一个向量表示,无论是来自源数据还是目标数据,都经过同一个编码器,然后在编码器后面接一个域分类器,试图判断某个表示来自哪个数据域。同时,通过梯度反转层让编码器学会“骗过”域分类器,也就是让两个数据域的表示在语义空间里尽量不分家。这就像把两个方言区的人放在同一个集训营里训练,逼着他们找到共同表达方式。选预训练语言模型做编码器时,我建议加载一个在多种语料上预先训练过的模型,比如通用的中文模型或领域混合模型,这能让特征对齐的起点更接近,训练也更容易收敛。

不过需要提醒的是,对抗对齐只能让表示分部分布接近,它并不能保证关系语义的一致性。原因很简单,对齐是全局层面的,而关系是局部语义层面的。所以后两个组件才是解决关系级语义匹配的关键。

2.2 关系类型映射:用原型向量替代固定标签

当关系集合是开放的时候,你没法再维护一张从关系名到类别ID的表。更合理的做法是给每个关系学一个“原型向量”。这个原型向量可以理解为该关系在语义空间中的典型表示,它不依赖具体词汇,而是把“属于该关系”的句子编码后取平均或聚类中心。有了原型向量,无监督数据里的每个候选句子实体对,都可以通过计算其表示与原型的相似度来判断是否属于该关系。

这个设计的妙处在于,它可以自然地支持新关系的涌现。如果你在无监督数据上发现了聚成一团、且距离现有原型都比较远的样本,就可以把它当成一个潜在的新关系,单独建立一个原型,而不是硬塞到旧关系里。我在做某知识库扩充项目时,就是因为加了这个机制,才把一个原本只认识“任职、收购、发布”等二十来种关系的系统,扩展到了上百种细粒度关系,而且大部分新关系不是预设的,而是从无监督数据里自动发现的。

那么原型向量应该怎么构建呢?我的经验是先让监督数据训练出的模型给无监督数据打一轮初始的弱标签,然后以这些弱标签样本的表示向量作为初始原型。接着,用聚类的办法把无监督数据中相似的关系语义归为一簇,不断更新原型。这个过程需要反复迭代,直到原型的分布和数量趋于稳定。如果你用的是预训练语言模型,编码后的表示已经具备一定的语义区分度,原型更新通常不会太难。

2.3 置信度自训练:从无监督噪声中挑选可信样本

有了原型向量,接下来就是怎么利用无监督数据本身来迭代。一个很自然的方法是自训练:先用源数据训练一个初始模型,给无监督数据打伪标签,然后选出置信度高的样本加入训练集,继续训练模型,如此循环。听起来简单,但实际操作时,伪标签的噪声非常高。如果盲目把低置信度的样本也加进去,模型会越学越歪。

所以我强烈建议设置一个动态阈值,而不是固定阈值。最开始阈值可以定高一点,比如0.95,保证进入训练集的样本都是模型非常有把握的;随着迭代进行,模型逐渐变强,再逐步降低阈值,比如每次迭代降0.02,直到下限0.75左右。这样做的原理是课程学习——先易后难,让模型先从干净的高置信度样本学习,再逐渐适应更模糊更复杂的边界情况。

另外,自训练不是简单地给样本打个标签再丢回去。我还会做两件事:一是对候选样本做实体类型的过滤,如果关系原型明确要求是“人-机构”类型,而某个样本的实体是“药物-疾病”,那即便置信度高也不应该进入训练集;二是过滤关系描述太笼统的样本,比如有些句子只是说了“存在关系”但根本没给出具体语义,这种样本对原型更新毫无帮助。

3. 一次完整的迁移训练流程:从数据准备到模型收敛

无论理论说得多么漂亮,最终还是要落到训练流程上。我把自己做过的一个模拟项目X的流程完整复盘一遍,你可以直接把这个流程当成模板来用。

3.1 源数据与目标数据的预处理细节

源数据就是带关系标签的监督语料,一般长这样:一个句子,里面标出了实体对的位置和类型,还有人工或远程监督给的关系标签。这种数据在很多资源平台都能找到,但我不建议直接拿来用,因为里面通常混着噪声。比如远程监督自动生成的数据经常存在标签错误,典型表现是两个实体在句中被一个无关的关系词连接。我的习惯是:先用一个简单的匹配器看看源数据里每个关系的典型表达是否合理,再挑出最干净的一部分做验证集,防止模型在训练过程中过拟合到噪声标签。

目标数据就是你要迁移去的那批无监督语料。预处理时最关键的步骤是实体识别和实体对抽取。如果目标数据里连实体对都没有,那就算迁移了关系也没有用。我一般会用现成的命名实体识别工具先抽取出人名、机构名、地名、产品名等,再把同一句子中的实体两两配对。这里有个小窍门:不要所有实体对都保留,只保留那些在句中出现位置相邻、或者有某种句法依赖关系的实体对。否则一个长句子里有七八个实体,光排列组合就有几十对,绝大多数都是无意义的负样本,反而会干扰模型。

3.2 两阶段训练:先对齐,再自训练

我把整个训练分成两个阶段,分别解决不同的问题,不要一上来就混合训练。

第一阶段是特征对齐阶段。我用共享编码器加上域分类器,把源数据和目标数据混在一起,只做特征分布对齐。这一阶段不使用关系标签,训练目标只有一个:让编码器输出的表示无法被区分来自哪个数据域。我习惯先用一个较小的学习率(比如2e-5)训练这个阶段,大概进行三五个epoch。需要注意的是,对抗训练很容易不稳定,所以要适当降低对抗损失权重,比如设置在0.5左右,避免编码器为了骗过域分类器而丢掉太多语义信息。这一步结束后,源数据和目标数据的表示已经比较接近了,可以进行下一阶段。

第二阶段是关系自训练阶段。先用阶段的编码器加上一个关系分类头,在源数据上训练出一个初始关系模型。然后用这个模型对目标数据中的每组实体对进行预测,得到关系类别和置信度。根据前面设置的动态阈值挑选高置信度候选集,再结合原型的聚类结果给这些候选样本分配伪标签。把伪标注后的目标数据放入训练集,继续训练模型。这个过程循环数轮,每一轮都重新生成伪标签、更新原型、扩大训练集,直到验证集上的效果不再提升或者伪标签几乎没有新增样本为止。

3.3 关键超参数与调优经验

我整理了自己在多个实验里最终稳定下来的参数配置,你可以参考:

超参数我常用的值影响说明
编码器基础中文预训练模型(引用通用版本)有领域预训练更好,但对齐阶段能拉回来一部分
对抗损失权重0.5太高会让表示失真,太低对齐效果差
初始置信度阈值0.95高起点保证第一轮伪标签干净
阈值衰减步长0.02 / 轮降太快噪声爆炸,降太慢无效
自训练轮数5-8 轮具体看验证曲线的变化
批量大小32小数据量时16更好
学习率5e-5(分类头)、2e-5(编码器)编码器用较小的防止灾难性遗忘

还有两个经验要特意说一下。第一,每一轮自训练后,都要回到源数据上做一次快速评测。如果源数据上的准确率掉得厉害,说明模型发生了灾难性遗忘,这时候要往目标数据训练集里混入部分源数据样本,或者给源数据的损失加一个较高的权重。第二,伪标签并不是越多越好。我见过很多同学追求每轮加入大量伪标签样本,结果模型效果越来越差。真实的经验是每一轮最多增加10%-20%的新样本比较安全,加多了模型会被少数错误样本主导。

4. 评测效果与实测中的“翻车现场”

聊完了训练流程,再来说说效果评测。这部分的坑比训练本身还多,因为开放关系抽取的评测本身就是一个难题,更不要说加上迁移学习这一层。

4.1 与直接训练和纯无监督方法的对比

在模拟项目X里,我对比了三种方案:直接用源数据模型零样本迁移到目标数据、完全不做迁移的纯无监督聚类、以及前面这套关系知识迁移方案。为了评测方便,我在目标数据上额外标注了一小批测试集,只用来做最终测试,不参与训练。

指标零样本迁移纯无监督聚类关系知识迁移方案
关系分类准确率41.3%26.7%63.8%
关系召回率38.5%22.9%59.2%
发现的稳定关系数191487
手工复检准确率62%35%78%

单纯看数字,关系知识迁移方案的提升幅度是很可观的,但只要仔细看,就能发现问题:准确率虽然到了六成多,但手工复检准确率比分类准确率低了十几个百分点。这说明自动评测里的很多标签本身就是错的,或者专家的标注标准和模型的预测标准不完全一致。这也是开放关系抽取评测的一个老毛病:没有唯一正确答案。

4.2 三个高发问题:标签噪声、长尾关系、域偏置

实测中最常见的三个问题,我一个个说。

第一个是标签噪声。源数据的监督标签本身就有噪声,尤其是用远程监督自动生成的标签,某些关系判断得非常牵强。我检查过一个案例,源数据里有一句“A公司的CEO张三参加了行业峰会”,远程监督根据知识库里的“CEO张三”标注成“任职”,但句子上下文实际表达的是一种参会行为,而不是任职关系。这种噪声在自训练过程中会被放大,最终导致目标数据上的伪标签跟着错。解决办法是每次迭代后用当前模型重新审视源数据的预测,把那些“模型高置信但标签却不对”的样本挑出来人工检查,虽然费时间,但效果好。

第二个是长尾关系。无监督数据中,大部分关系只出现几次,只有少数关系频繁出现。模型天然会倾向于学习频繁关系,长尾关系则容易被忽略。我在实验中发现,即使第一阶段对齐做得不错,仅仅采用阈值筛选伪标签,长尾关系的召回率依然非常低。后来我在损失函数里加入了关系频率的平衡项,让低频率的关系提升一点权重,并且特意为低频关系保留了更多的原型候选,才勉强改善了情况。

第三个是域偏置。如果你的源数据是新闻领域,目标数据是社交网络领域,迁移后模型在社交网络里会存在一种“新闻腔”,表达方式很正式,动不动就用“某某机构宣布”。这倒不是模型全错了,而是它习惯了正规表述,在识别口语化、省略主语甚至句法不完整的表达时非常迟钝。我后来在预处理目标数据时加入了风格归一化,比如把网络用语、缩写、表情符号的干扰弱化,同时给目标语料增加了一部分被改写成口语化的句子作为增强数据,域偏置才好了一些。

4.3 如何排查自己的迁移结果是否“虚高”

开放关系抽取的评测有很多陷阱,最典型的就是测试集标注口径不统一。比如“北京是中国的首都”这句话,关系是“首都”还是“位于”?不同标注者可能给出不同答案。模型如果碰巧学习到了一种比较宽泛的关系表达,在自动测试集上很可能拿到高分,但实际落地时却发现它把很多不相关的关系也归到了一起。

我建议在做迁移效果评估时,至少做三件事。第一,测试集要包含多组独立的标注人员或者多轮标注结果,统计标注一致性,如果一致性太低,任何自动指标都不可信。第二,不仅看分类准确率,还要看模型是否区分了关系语义的粗细粒度。你可以故意构造一些关系语义非常接近、但表达目的不同的样本,看看模型能不能把他们区分开。第三,要人工抽查模型在新关系上的表现。迁移的价值在于新发现,如果你迁移完只能识别源数据里那几十种关系,那说明迁移并没有真正发生,模型只是在无监督数据里重复了旧知识。

5. 把同样思路迁移到你的业务场景中的落地建议

如果你手头正有一个需要做关系抽取但标注稀缺的业务,这套“从监督到无监督”的思路大概率可以直接套用,但有几个地方需要根据场景调整。

5.1 哪些任务适合做“监督到无监督”的关系知识迁移

最适合的是那些“关系表达相对稳定、但类型多样且不断出现新关系”的文本场景。比如金融领域的公司公告和研报,里面存在“融资”“并购”“董事会变更”“股权质押”等关系,公告数据尽管无标签但数量巨大,而带标签的小批量样本可以来自人工整理的某几类核心关系。再比如医疗领域的临床笔记,里面存在“剂量调整”“不良反应”“患者自述症状”等关系,无监督病历语料取之不竭,但标注极其昂贵。这样的场景下,迁移的效果往往很明显。

反过来,如果你的目标数据本身就和源数据非常相似,比如源数据也是同一领域的新闻稿,目标数据只是换了一年的新闻,那么直接用模型微调可能就够了,不必花大力气搭迁移管线。因为迁移的前提是分布有差异,没有差异还不如老老实实用有监督训练。

5.2 构建无监督语料时的三个实用技巧

第一个技巧是领域平衡。无监督语料不要逮着一个来源猛拉,而是要尽量覆盖不同的来源、不同的时间、不同的文体。否则模型会过拟合到某一个子域的特色表达上,迁移能力反而下降。我通常会把多个来源的数据混合后再做随机切分,确保训练的目标数据分布足够多样化。

第二个技巧是比例控制。无监督语料和监督语料的比例并不是越大越好。如果无监督数据比监督数据大几十倍,训练时间会暴增,伪标签噪声总量也会很大。我一般会控制二者比例在5:1到10:1之间,后续再根据验证效果逐步扩大。

第三个技巧是清洗与去重。很多无监督语料都是从网页、爬虫抓下来的,里面有大量重复段落、广告模板、乱码。重复样本进入训练集不但没有帮助,还会让模型在那些模板化表达上过度自信。去重之后我还建议做一轮首尾内容的裁切,保留核心正文段落即可。

5.3 越做越顺的迭代策略:从小步验证到全量训练

如果让我给你一个最可执行的建议,就是千万不要一开始就搭一个庞大复杂的迁移系统,而是先做一个最小可行版本。具体步骤是很简单的:先拿一小部分目标数据,比如一万条句子,走一遍特征对齐、伪标注、原型更新的流程,观察效果;如果效果不行,先别怀疑模型,而是先看数据,比如伪标签里最常见的错误是什么,错误集中在哪些实体对或者句子类型上。把这些问题归因清楚,再决定是调阈值还是换特征。

小步验证跑通以后,再扩大到全量数据。全量训练时要注意引入增量式的伪标签生成,不要把全量无监督数据一次性塞进自训练循环,而是按批次迭代。每轮加入新数据之前,先跑一遍已有伪标签集的抽样校验,看看错误率是否在可接受范围内。我见过太多项目是在全量过程中因为噪声堆积而崩掉的,但凡是分批迭代的,大多都能平稳收敛。

最后再分享一个小技巧:保存每一轮的原型向量和伪标签样本,绘制一个“原型迁移轨迹图”,其实就是把不同轮次的原型向量做一次降维可视化。你可以直观看到哪些新关系逐渐被探索出来,哪些原本混乱的原型逐渐分离开。我每次迭代到三四轮时,看到图上清晰的长尾关系簇一点点分离出来,那种成就感特别强。这也是为什么我一直坚持把这套流程沉淀下来——它不只是把一个算法跑通,而是让你真的理解到,关系知识是可以被迁移的,而不只是被标注出来的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询