第4章 知识抽取之关系抽取:管道式与联合抽取、远程监督、基于预训练模型的关系分类

关系抽取,说白了就是让机器读懂实体之间的「关系」。

比如「苹果公司发布了iPhone 14」这句话,实体是「苹果公司」和「iPhone 14」,关系是「发布」。机器得学会把这种隐含的结构拎出来。

我个人习惯把关系抽取分为三大流派:管道式、联合抽取、以及基于预训练模型的分类方法。今天咱们一个一个拆开看。

4.1 管道式抽取:先抽实体,再判关系

这是最朴素的做法。先在句子里把实体标注出来,然后针对每一对实体做关系分类。

核心流程:
  1. 实体识别(NER)——找到句子中的主语和宾语。
  2. 关系分类——对每一对候选实体,判断它们之间是否有关系,以及是什么关系。

举个例子,句子「特斯拉收购了太阳城公司」:

  • NER 阶段标注出「特斯拉」和「太阳城公司」
  • 关系分类阶段判断这两者之间的关系标签——「收购」

这种方法直观,但有一个大问题:错误传播。NER 漏了一个实体,关系就跟着丢了。我在项目中遇到过这样的情况:NER 把「北京」识别成了人名,结果整个关系链全乱套。

避坑指南: 我曾经在一个金融文本项目里用管道式抽取,NER 准确率只有82%,最终关系抽取的F1值直接掉到了67%。所以如果你要做管道式,NER 的精度必须拉到95%以上,否则后面全是噪音。
# 伪代码示意:管道式关系抽取
from ner_model import extract_entities
from relation_model import classify_relation

def pipeline_extraction(sentence):
    entities = extract_entities(sentence)
    # 枚举所有实体对
    for i in range(len(entities)):
        for j in range(i+1, len(entities)):
            rel = classify_relation(sentence, entities[i], entities[j])
            if rel is not None:
                print(f"{entities[i]} --{rel}--> {entities[j]}")

4.2 联合抽取:端到端解决问题

管道式的缺点很明显——任务分裂。联合抽取想干一件事:同时输出实体和关系,不再分两步走。

说白了,它把序列标注和关系分类合并到一个模型里。典型做法是在解码阶段设计一个特殊的标注体系,或者使用多任务学习。

对比维度 管道式 联合抽取
错误传播 严重 较轻
解耦难度 容易 困难
模型复杂度 低 高
训练数据需求 分开标注 需要完整的实体-关系三元组

联合抽取的代表工作包括CasRel和TPLinker。我记得第一次复现 CasRel 时,那个主题标注的思路让我眼前一亮——它用「头实体标注 + 尾实体与关系联合标注」的方式,一步到位。

# CasRel 的输入输出示意
# 输入:句子
sentence = "乔布斯在1976年创立了苹果公司"

# 输出:三元组列表
{ 
  "head": "乔布斯", 
  "relation": "创立", 
  "tail": "苹果公司" 
},
{ 
  "head": "苹果公司", 
  "relation": "成立时间", 
  "tail": "1976年" 
}

但联合抽取也有痛处。它对解码的要求很高,一旦关系数很多(比如几千种),解码空间暴涨,训练非常不稳定。我建议刚入门的朋友先从管道式入手,把流程跑通再说。

4.3 远程监督:自动打标,数据不用愁

标签数据永远不够,怎么办?远程监督来救场。

它的思想很粗暴:把知识图谱中的三元组拿来对齐到文本。如果一个句子中同时出现了图谱中的两个实体,就认为这个句子表达了图谱中对应的关系。

关键假设: 所有包含同一对实体的句子,都表达了相同的语义关系。这个假设很强,所以叫「远程监督」——离得远,监督信号弱。

举个例子,知识图谱里有一条三元组 (比尔·盖茨,创办,微软),那么任何同时提到「比尔·盖茨」和「微软」的句子,都被自动打上「创办」标签。哪怕句子说的是「比尔·盖茨曾经在微软担任CEO」——实际上不是创办关系,但也算。

这种做法会引入大量噪声。我在一个生物医学知识图谱项目中用过远程监督,结果发现60%的自动标注样本都是错的。后来我们加了一层句子级别的注意力机制,才把有效样本比例提到75%。

注意: 远程监督生成的数据集必须做去噪处理,常用的方法有:
  • 多实例学习(MIL)
  • 句子级别注意力(PCNN-ATT等)
  • 对比学习筛选
千万不要拿远程监督的数据直接训练生产模型,否则你会被噪声害惨。

4.4 基于预训练模型的关系分类

现在的大语言模型给关系抽取带来了新玩法。你可以把关系分类任务看成一个文本分类问题或问答问题。

典型做法有两种:

  1. 序列分类:把句子+实体标记拼成输入序列,让BERT或GPT直接输出关系标签
  2. 提示学习(Prompt-tuning):把关系定义写入提示模板,让模型生成答案
我最推荐的做法: 使用预训练模型+提示学习。比如定义提示模板「{head}和{tail}之间的关系是[Z]」,让模型填空。这种做法的好处是零样本能力强,迁移到新关系类型时不需要重新全量训练。
# 基于预训练模型的关系分类(提示学习方式)
prompt = f"{head_entity} 和 {tail_entity} 之间的关系是 [Z]"

# 模型输出候选关系
model_output = "收购"  # 假设模型推理得出

# 你也可以做成多选题:
prompt = f"请问 '{head_entity}' 和 '{tail_entity}' 之间的关系是?"
options = ["收购", "投资", "合作", "无关系"]
# 模型从中选一个

我建议你关注一下当前的主流实践:

  • Noah's Ark Lab 的 KnowPrompt——专门为关系抽取设计的提示方法
  • GPT-3/4 的零样本能力——不需要任何训练样本,直接扔上下文就能做
  • 微调策略——如果数据量少,用 LoRA 微调;数据量大,做全参数微调

使用预训练模型做关系分类,最大的坑是实体标记的有效性。如果你直接输入纯文本,模型可能搞不清到底是哪两个实体之间的关系。所以我们通常会在实体前后加

最后给你一个总结表,方便对比:

方法 代表技术 适用场景 核心风险
管道式 NER + 分类器 数据量小、流程透明 错误传播
联合抽取 CasRel, TPLinker 关系类型固定、精度要求高 解码复杂度高
远程监督 PCNN-ATT, MIL 大冷启动、无标注数据 噪声极其严重
预训练模型 BERT, GPT, KnowPrompt 零样本、少样本、高泛化 实体标记、推理成本
关系抽取技术演进 1. 管道式 NER → 关系分类 2. 联合抽取 端到端解码 3. 远程监督 知识图谱对齐 4. 基于预训练模型 序列分类式 提示学习式 零样本分类 底层技术路线不断演进 但业务上我建议根据实际数据量选择方法
一个小建议: 如果你在实际项目中需要快速出成果,我建议用预训练模型 + 提示学习的方式。几年前我做一个电商平台的关系抽取时,零样本下就能达到85%的准确率,再稍加微调就上92%。相比管道式,省了至少两周的实体标注时间。