NLP学习笔记06:关系抽取------从规则方法到预训练模型
作者:Ye Shun
日期:2026-04-17
一、前言
关系抽取(Relation Extraction)是自然语言处理(NLP)中的一个重要任务,它的目标是从非结构化文本中识别实体之间的语义关系。简单来说,关系抽取要回答的问题是:
- 谁和谁有关联?
- 这种关联是什么?
例如在句子:
马云创立了阿里巴巴。
中,我们不仅能识别出两个实体:
马云阿里巴巴
还希望进一步抽取出它们之间的关系:
(马云,创始人,阿里巴巴)
如果说命名实体识别(NER)解决的是"文本里有哪些关键对象",那么关系抽取解决的就是"这些对象之间是什么关系"。因此,关系抽取通常被视为信息抽取、知识图谱和问答系统中的关键一步。
这篇笔记将围绕以下几个问题展开:
- 什么是关系抽取,它和 NER 有什么联系
- 关系抽取的核心要素是什么
- 常见方法有哪些,各自优缺点是什么
- 如何评估关系抽取系统
- 如何用一个简单示例理解关系抽取流程
二、关系抽取的核心要素
一个完整的关系抽取任务,通常包含三个核心部分:
1. 实体识别
关系必须发生在实体之间,因此第一步往往要先识别文本中的实体。这一步通常依赖命名实体识别(NER)系统,或者由人工预先标注实体。
例如在句子:
北京是中国的首都。
中,可以先识别出:
北京:地点中国:国家
2. 关系分类
识别出实体之后,接下来要判断它们之间是否存在某种关系。如果存在,还要判断关系属于哪一类。
在上面的例子中,模型需要判断:
北京和中国之间的关系是首都
3. 关系表示
关系抽取的结果通常会被转换成结构化形式。最常见的表示方式是三元组:
text
(头实体, 关系, 尾实体)
例如:
(马云,创始人,阿里巴巴)(北京,首都,中国)
这种结构化结果非常适合进一步用于:
- 知识图谱构建
- 问答系统
- 检索增强
- 事件分析
三、关系抽取的应用场景
关系抽取并不是一个纯学术任务,它在很多实际系统中都很重要。
1. 知识图谱构建
关系抽取是知识图谱构建中的核心模块之一。知识图谱不仅需要实体节点,还需要实体之间的边,而这些边往往就是通过关系抽取得到的。
2. 智能问答系统
很多问答问题实际上都对应某种关系查询。例如:
- "阿里巴巴是谁创立的?"
- "中国的首都是哪里?"
如果系统已经从文本中抽取出了相关三元组,就能更容易回答这类问题。
3. 信息检索与摘要
关系抽取可以帮助系统抓住文本中的核心事实,而不只是关键词匹配。例如财经新闻里,系统不仅知道"公司名",还知道"谁收购了谁""谁投资了谁"。
4. 生物医学文献挖掘
在生物医学领域,关系抽取常用于识别:
- 药物与疾病的关系
- 基因与疾病的关系
- 蛋白质与蛋白质的相互作用
这类关系对科研和临床辅助系统都非常有价值。
四、关系抽取的主要方法
从方法发展路径来看,关系抽取大致可以分为四类:
- 基于规则的方法
- 监督学习方法
- 半监督 / 远程监督方法
- 基于预训练语言模型的方法
1. 基于规则的方法
规则方法是最直观的一类思路。它依赖人工总结的语言模式、模板和关键词来抽取关系。
例如,对于句子:
马云创立了阿里巴巴
可以使用简单规则:
python
import re
text = "马云创立了阿里巴巴"
pattern = r"(.+?)创立了(.+?)"
match = re.search(pattern, text)
if match:
print(f"创始人: {match.group(1)}, 公司: {match.group(2)}")
优点
- 实现简单
- 在规则稳定的场景下准确率高
- 可解释性强
缺点
- 覆盖范围有限
- 难以处理复杂句式和表达变体
- 规则维护成本高
因此,规则法更适合处理固定格式关系,比如"时间""金额""地理位置"这类相对稳定的表达。
2. 监督学习方法
监督学习方法需要使用带标注的关系数据进行训练。通常的做法是:
- 先识别句子中的实体
- 构造实体对
- 判断实体对之间的关系类别
常见算法包括:
- 支持向量机(SVM)
- 条件随机场(CRF)
- 各类神经网络模型
相较于规则法,监督学习方法可以从数据中学习更多表达模式,因此泛化能力更强。
例如,使用 spaCy 先识别实体:
python
import spacy
nlp = spacy.load("en_core_web_sm")
text = "Apple was founded by Steve Jobs in 1976."
doc = nlp(text)
for ent in doc.ents:
print(ent.text, ent.label_)
在完整系统中,实体识别之后通常还要再接一个关系分类模块,而不仅仅停留在识别实体上。
3. 半监督与远程监督方法
监督学习的一个核心难点是:关系标注数据很昂贵。
为了降低人工标注成本,研究者提出了半监督和远程监督方法。
半监督方法
利用少量标注数据和大量未标注数据一起训练模型,希望模型从更丰富的数据中学习到关系模式。
远程监督方法
利用现有知识库自动对文本进行弱标注。例如,如果知识库中已有:
(马云,创始人,阿里巴巴)
那么当文本里同时出现"马云"和"阿里巴巴"时,就可能自动把它标为这类关系样本。
这种方法能快速构造大规模训练数据,但也会引入噪声。
4. 基于预训练语言模型的方法
近年来,关系抽取越来越多地依赖预训练语言模型,例如:
- BERT
- RoBERTa
- GPT 类模型
这类方法的优势在于:
- 更强的上下文建模能力
- 更好的泛化性能
- 对复杂句式和长距离依赖更稳健
例如,使用 Hugging Face 工具可以快速搭建文本分类或关系判别原型:
python
from transformers import pipeline
classifier = pipeline("text-classification", model="bert-base-uncased")
result = classifier("马云是阿里巴巴的创始人")
print(result)
严格来说,这段代码本身还不是一个完整的关系抽取系统,但它说明了一个重要趋势:预训练模型可以作为关系分类器的基础表示层。
五、关系抽取的关键技术点
虽然关系抽取的最终目标是输出关系,但它往往依赖多个子任务共同配合。
1. 实体识别
关系抽取通常建立在命名实体识别(NER)之上,因此实体识别质量会直接影响关系抽取结果。
如果实体边界都识别错了,后面的关系判断几乎不可能完全正确。
2. 实体链接
在一些复杂应用中,仅识别出"文本中这个词是实体"还不够,还需要把它链接到知识库中的具体实体。例如:
Apple是水果还是公司?
实体链接可以帮助系统更准确地理解实体真实含义。
3. 关系分类
关系分类是关系抽取的核心。它决定两个实体之间到底是:
- 创始人
- 位于
- 首都
- 属于
- 治疗
还是根本不存在关系。
4. 关系表示形式
最常见的是二元关系,也就是一个头实体和一个尾实体之间的关系。但在很多复杂场景中,还会遇到:
- n 元关系
- 层次化关系
- 事件型关系
这会让任务复杂度进一步提高。
六、评估指标
关系抽取和很多 NLP 任务一样,通常使用以下指标评估:
| 指标 | 说明 |
|---|---|
| Precision | 正确预测的关系占所有预测关系的比例 |
| Recall | 正确预测的关系占所有真实关系的比例 |
| F1 | Precision 和 Recall 的调和平均 |
这里要注意,关系抽取通常要求:
- 实体边界正确
- 关系类型正确
- 实体配对正确
只有这些都对,才算一次真正的命中。
七、关系抽取的常见挑战
关系抽取看起来像是在做"实体对分类",但真正实现起来并不简单。
1. 语言表达多样性
同一种关系可以有很多不同表达方式。例如"创立""创办""成立了""是......的创始人"都可能表达相近关系。
2. 实体歧义
相同实体在不同上下文中可能有不同含义,影响关系判断。
3. 长距离依赖
有些关系对应的两个实体在句子中相距很远,中间还夹杂很多修饰成分,这对模型提出了更高要求。
4. 数据稀疏
一些关系类型本身就很少见,标注数据更少,模型训练会比较困难。
5. 领域适应问题
在新闻领域训练好的模型,不一定能直接用于医疗、金融或法律文本。
八、实践案例:构建一个简单的关系抽取系统
为了更直观理解关系抽取流程,我们可以从一个小型示例出发。
步骤1:准备数据
例如:
python
data = [
{"text": "比尔盖茨是微软的创始人", "relations": [{"head": "比尔盖茨", "tail": "微软", "type": "创始人"}]},
{"text": "北京是中国的首都", "relations": [{"head": "北京", "tail": "中国", "type": "首都"}]}
]
这里每条样本都包含:
- 原始文本
- 头实体
- 尾实体
- 关系类型
步骤2:特征工程
最简单的思路是先把句子表示成 TF-IDF 特征:
python
from sklearn.feature_extraction.text import TfidfVectorizer
texts = [d["text"] for d in data]
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(texts)
步骤3:训练模型
然后把关系类型作为标签训练分类器:
python
from sklearn.svm import SVC
y = [d["relations"][0]["type"] for d in data]
model = SVC()
model.fit(X, y)
步骤4:预测应用
python
test_text = "乔布斯创立了苹果公司"
test_vec = vectorizer.transform([test_text])
prediction = model.predict(test_vec)
print(f"预测关系: {prediction[0]}")
这个示例非常简化,但已经能帮助我们理解关系抽取系统的基本流程:
- 准备关系样本
- 抽取文本特征
- 训练关系分类器
- 对新句子进行关系预测
在真正的工业系统中,通常还会加入:
- 实体识别模块
- 候选实体对生成
- 关系筛选模块
- 多跳推理或知识库对齐
九、学习建议
如果想系统学习关系抽取,我比较建议按下面的顺序推进:
1. 先理解三元组表达
把关系抽取结果理解成:
(头实体,关系,尾实体)
这是最核心的表示方式。
2. 先从规则方法入门
因为规则法最容易帮助你直观看懂"关系抽取到底在抽什么"。
3. 再学习监督学习方法
理解如何把"关系抽取"转化为"关系分类"问题。
4. 最后过渡到 BERT 等预训练模型
这样更容易理解现代方法到底比传统方法强在哪里。
十、总结
关系抽取是 NLP 中非常重要的一类信息抽取任务。它的目标,不只是找到文本中的实体,更是要进一步判断这些实体之间的语义关系。
从方法演进来看:
- 规则方法适合简单明确的模式
- 监督学习方法提升了泛化能力
- 半监督与远程监督缓解了标注成本问题
- 预训练语言模型则进一步提升了上下文建模和复杂关系理解能力
从应用角度看,关系抽取是知识图谱、问答系统、文档分析和行业 NLP 应用中的关键基础模块。理解它,不仅能帮助我们更好掌握 NLP 信息抽取方向,也能为后续学习事件抽取、知识图谱构建和多跳推理打下基础。