人工智能之语言领域 自然语言处理 第八章 关系抽取

人工智能之语言领域

第八章 关系抽取


文章目录

  • 人工智能之语言领域
  • [前言 关系抽取](#前言 关系抽取)
    • [8.1 关系抽取概述](#8.1 关系抽取概述)
      • [8.1.1 关系类型](#8.1.1 关系类型)
      • [8.1.2 任务类型](#8.1.2 任务类型)
    • [8.2 传统关系抽取方法](#8.2 传统关系抽取方法)
      • [8.2.1 基于特征工程的方法](#8.2.1 基于特征工程的方法)
      • [8.2.2 基于核函数的方法](#8.2.2 基于核函数的方法)
    • [8.3 深度学习关系抽取方法](#8.3 深度学习关系抽取方法)
      • [8.3.1 基于CNN的关系抽取:局部特征匹配](#8.3.1 基于CNN的关系抽取:局部特征匹配)
      • [8.3.2 基于注意力机制的关系抽取](#8.3.2 基于注意力机制的关系抽取)
      • [8.3.3 预训练模型在关系抽取中的微调](#8.3.3 预训练模型在关系抽取中的微调)
    • [8.4 联合抽取技术](#8.4 联合抽取技术)
      • [8.4.1 实体识别与关系抽取联合模型](#8.4.1 实体识别与关系抽取联合模型)
      • [8.4.2 联合模型的训练与优化](#8.4.2 联合模型的训练与优化)
    • [8.5 实战案例:金融领域"公司-产品-合作"关系抽取](#8.5 实战案例:金融领域“公司-产品-合作”关系抽取)
    • 关系抽取挑战与前沿
    • 小结
  • 资料关注

前言 关系抽取

关系抽取(Relation Extraction, RE)属于自然语言处理中信息抽取 范畴,可以从非结构化文本中自动识别两个或多个实体之间的语义关系 。它是构建知识图谱、智能问答、风险控制等系统的基石。如果说命名实体识别(NER)回答"谁/什么 ",那么关系抽取回答"它们之间是什么关系"。本章将系统介绍关系抽取的任务形式、传统与深度学习方法、联合抽取技术,并通过金融领域实战案例完整演示端到端流程。


8.1 关系抽取概述

8.1.1 关系类型

关系抽取关注两类主要关系:

类型 说明 示例
语义关系 语言学定义的通用关系 "位于"、"出生于"、"创始人是"
实体间关联关系 领域特定业务关系 "公司A 与 公司B 合作开发 产品X"

常见标准关系集

  • ACE 2005PER-SOC(社会关系)、ORG-AFF(组织隶属)
  • SemEval-2010 Task 8Cause-EffectComponent-Whole
  • 中文金融关系合作投资控股供应

🌰 示例句子:

"阿里巴巴 (ORG)投资小鹏汽车 (ORG)。"

→ 抽取三元组:(阿里巴巴, 投资, 小鹏汽车)
原始文本
实体识别
(阿里巴巴, ORG)
(小鹏汽车, ORG)
关系分类
投资
阿里巴巴, 投资, 小鹏汽车


8.1.2 任务类型

类型 说明 数据来源 挑战
有监督关系抽取 使用人工标注的句子-关系对训练 专家标注数据集 标注成本高
远程监督关系抽取 利用知识库(如 Freebase)自动标注 知识库 + 文本语料 噪声标签(错误对齐)

🔍 远程监督假设

若两个实体在知识库中有关系,则包含这两个实体的所有句子 都表达该关系。

❌ 问题:句子"马云创立了阿里巴巴"和"马云访问了阿里巴巴总部"都被标为 (马云, 创始人, 阿里巴巴),但后者不表达该关系。


8.2 传统关系抽取方法

8.2.1 基于特征工程的方法

核心思想:人工设计特征,输入分类器(如 SVM)。

常用特征

  • 词法特征:实体类型、词性、依存路径
  • 句法特征:最短依存路径(Shortest Dependency Path, SDP)
  • 上下文特征:实体前后窗口词

📐 示例:

句子:"马云 创立 了 阿里巴巴"

SDP:马云 ← nsubj ← 创立 → dobj → 阿里巴巴

特征向量:[nsubj, dobj, "创立", PER, ORG]

python 复制代码
# 伪代码:特征提取
def extract_features(sentence, e1, e2):
    features = {
        'e1_type': get_entity_type(e1),
        'e2_type': get_entity_type(e2),
        'between_words': get_words_between(e1, e2),
        'dependency_path': get_dependency_path(e1, e2)
    }
    return features

✅ 优点:可解释性强

❌ 缺点:依赖 NLP 工具(分词、句法分析),泛化能力弱


8.2.2 基于核函数的方法

思想:通过核函数(Kernel)直接计算句子相似度,避免显式特征工程。

  • 子树核(Subtree Kernel):比较句法树子结构
  • 卷积核(Convolution Kernel):组合多源特征

📊 在 SemEval 等早期竞赛中表现优异,但实现复杂,已被深度学习取代。


8.3 深度学习关系抽取方法

8.3.1 基于CNN的关系抽取:局部特征匹配

原理:将句子视为词向量序列,用 CNN 提取局部 n-gram 特征。

关键技巧位置嵌入(Position Embedding)

  • 为每个词添加相对于两个实体的相对距离
  • 帮助模型聚焦实体附近信息

词序列 + 实体位置
Word + Position Embedding
Multi-size CNN
Max Pooling
全连接+Softmax
关系类别

python 复制代码
import torch
import torch.nn as nn

class CNNRelationExtractor(nn.Module):
    def __init__(self, vocab_size, embed_dim=128, pos_embed_dim=16, num_relations=10, kernel_sizes=[2,3,4]):
        super().__init__()
        self.word_embed = nn.Embedding(vocab_size, embed_dim)
        self.pos1_embed = nn.Embedding(2*MAX_LEN, pos_embed_dim)  # 相对位置范围 [-L, L]
        self.pos2_embed = nn.Embedding(2*MAX_LEN, pos_embed_dim)
        
        self.convs = nn.ModuleList([
            nn.Conv2d(1, 100, (k, embed_dim + 2*pos_embed_dim)) for k in kernel_sizes
        ])
        self.dropout = nn.Dropout(0.5)
        self.fc = nn.Linear(100 * len(kernel_sizes), num_relations)

    def forward(self, words, pos1, pos2):
        # words: [B, L], pos1/pos2: [B, L]
        w_emb = self.word_embed(words)          # [B, L, D]
        p1_emb = self.pos1_embed(pos1)          # [B, L, P]
        p2_emb = self.pos2_embed(pos2)          # [B, L, P]
        x = torch.cat([w_emb, p1_emb, p2_emb], dim=2)  # [B, L, D+2P]
        x = x.unsqueeze(1)  # [B, 1, L, D+2P]

        xs = []
        for conv in self.convs:
            c = torch.relu(conv(x)).squeeze(3)  # [B, F, L-k+1]
            p = torch.max_pool1d(c, c.size(2)).squeeze(2)  # [B, F]
            xs.append(p)
        x = torch.cat(xs, 1)
        x = self.dropout(x)
        return self.fc(x)

✅ 优势:并行计算快,擅长捕捉关键词组合

❌ 劣势:忽略长距离依赖和全局结构


8.3.2 基于注意力机制的关系抽取

思想:让模型自动关注对关系判断最重要的词。

  • 自注意力(Self-Attention):计算词间相关性
  • 实体为中心的注意力:以两个实体为查询,加权句子其他部分
python 复制代码
class AttentionRE(nn.Module):
    def __init__(self, hidden_dim, num_relations):
        super().__init__()
        self.attn = nn.MultiheadAttention(hidden_dim, num_heads=8, batch_first=True)
        self.fc = nn.Linear(hidden_dim, num_relations)

    def forward(self, h, e1_idx, e2_idx):
        # h: [B, L, H] (e.g., from BiLSTM)
        # 以 e1 和 e2 的表示作为 Query
        query = torch.stack([h[torch.arange(h.size(0)), e1_idx],
                             h[torch.arange(h.size(0)), e2_idx]], dim=1)  # [B, 2, H]
        attn_out, _ = self.attn(query, h, h)  # [B, 2, H]
        sentence_rep = attn_out.mean(dim=1)   # [B, H]
        return self.fc(sentence_rep)

💡 注意力权重可可视化,提升模型可解释性。


8.3.3 预训练模型在关系抽取中的微调

主流方案:BERT + 分类头

输入格式(标记实体位置):

[CLS] 马云 [E1] 创立 [/E1] 了 [E2] 阿里巴巴 [/E2]。[SEP]

或使用实体类型标记

[CLS] 马云 (PER) 创立 了 阿里巴巴 (ORG)。[SEP]

python 复制代码
from transformers import AutoTokenizer, AutoModel
import torch.nn as nn

class BertForRE(nn.Module):
    def __init__(self, model_name, num_relations):
        super().__init__()
        self.bert = AutoModel.from_pretrained(model_name)
        self.dropout = nn.Dropout(0.1)
        self.classifier = nn.Linear(self.bert.config.hidden_size, num_relations)

    def forward(self, input_ids, attention_mask):
        outputs = self.bert(input_ids=input_ids, attention_mask=attention_mask)
        cls_output = outputs.last_hidden_state[:, 0]  # [CLS] 向量
        logits = self.classifier(self.dropout(cls_output))
        return logits

# Tokenizer 处理带标记的句子
tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese")
text = "马云 [E1] 创立 [/E1] 了 [E2] 阿里巴巴 [/E2]。"
inputs = tokenizer(text, return_tensors="pt", padding=True, truncation=True)

🌐 中文推荐:hfl/chinese-roberta-wwm-ext(性能优于原生 BERT)


8.4 联合抽取技术

传统流水线(先 NER 再 RE)存在错误传播 问题:NER 错 → RE 必错。
联合模型同时优化两个任务,提升整体性能。

8.4.1 实体识别与关系抽取联合模型

主流架构:
  1. 共享编码器 + 多任务头
    • BERT 编码 → NER 头(CRF) + RE 头(分类)
  2. 基于指针网络(Pointer Network)
    • 直接预测实体起止位置和关系
  3. 基于表格填充(Table Filling)
    • 构建 token-token 矩阵,每个单元格预测关系

输入文本
BERT Encoder
NER Head: CRF
RE Head: 分类器
实体列表
关系列表
三元组

开源实现推荐:
  • CasRel(2020):基于关系的指针网络
  • TPLinker(2020):统一处理重叠关系
  • PURE(2020):先抽实体再配对,但联合训练

8.4.2 联合模型的训练与优化

损失函数:多任务加权损失

L = λ 1 L N E R + λ 2 L R E \mathcal{L} = \lambda_1 \mathcal{L}{NER} + \lambda_2 \mathcal{L}{RE} L=λ1LNER+λ2LRE

训练技巧

  • 课程学习:先训 NER,再联合微调
  • 对抗训练:提升鲁棒性(如 FGM、PGD)
  • 解码约束:确保关系两端是有效实体

8.5 实战案例:金融领域"公司-产品-合作"关系抽取

任务目标

从新闻/公告中抽取三元组:
(公司A, 合作, 公司B)(公司, 发布, 产品)

🌰 示例:

"腾讯华为 宣布合作开发鸿蒙版微信 。"

→ 三元组1: (腾讯, 合作, 华为)

→ 三元组2: (腾讯, 发布, 鸿蒙版微信)

→ 三元组3: (华为, 发布, 鸿蒙版微信)

数据准备

使用公开金融关系数据集 FinRE(或自行标注)。

BERT 微调

python 复制代码
# Step 1: 定义关系类型
RELATIONS = ["合作", "投资", "控股", "发布", "供应", "竞争", "无关系"]
rel2id = {r: i for i, r in enumerate(RELATIONS)}

# Step 2: 构造带标记的输入
def mark_entities(text, e1_start, e1_end, e2_start, e2_end, e1_type, e2_type):
    # 在实体前后插入特殊标记
    chars = list(text)
    # 从后往前插入,避免索引偏移
    chars.insert(e2_end, f"[/E2:{e2_type}]")
    chars.insert(e2_start, f"[E2:{e2_type}]")
    chars.insert(e1_end, f"[/E1:{e1_type}]")
    chars.insert(e1_start, f"[E1:{e1_type}]")
    return "".join(chars)

# 示例
text = "腾讯与华为合作开发鸿蒙版微信"
marked = mark_entities(text, 0, 2, 3, 5, "ORG", "ORG")
# 输出: "[E1:ORG]腾讯[/E1:ORG]与[E2:ORG]华为[/E2:ORG]合作开发鸿蒙版微信"

# Step 3: Tokenize & 训练
from transformers import AutoTokenizer, AutoModelForSequenceClassification, Trainer

tokenizer = AutoTokenizer.from_pretrained("hfl/chinese-roberta-wwm-ext")
model = AutoModelForSequenceClassification.from_pretrained(
    "hfl/chinese-roberta-wwm-ext", 
    num_labels=len(RELATIONS)
)

def tokenize_function(examples):
    return tokenizer(
        examples["marked_text"],
        truncation=True,
        padding=True,
        max_length=128
    )

# 假设 dataset 包含 "marked_text" 和 "label"(关系ID)
tokenized_datasets = dataset.map(tokenize_function, batched=True)

training_args = TrainingArguments(
    output_dir="./fin-re-model",
    evaluation_strategy="epoch",
    learning_rate=2e-5,
    per_device_train_batch_size=16,
    num_train_epochs=5,
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_datasets["train"],
    eval_dataset=tokenized_datasets["test"],
)

trainer.train()

# Step 4: 预测新句子
def predict_relation(text, e1, e2, e1_type, e2_type):
    marked = mark_entities(text, e1[0], e1[1], e2[0], e2[1], e1_type, e2_type)
    inputs = tokenizer(marked, return_tensors="pt", padding=True, truncation=True, max_length=128)
    with torch.no_grad():
        logits = model(**inputs).logits
        pred_id = logits.argmax().item()
        prob = torch.softmax(logits, dim=1)[0][pred_id].item()
    return RELATIONS[pred_id], prob

# 示例调用
relation, confidence = predict_relation(
    "腾讯与华为合作开发鸿蒙版微信",
    (0, 2), (3, 5), "ORG", "ORG"
)
print(f"关系: {relation}, 置信度: {confidence:.3f}")
# 输出: 关系: 合作, 置信度: 0.982

系统集成建议

  1. 前置 NER:用医疗/金融领域 NER 模型识别实体
  2. 实体配对:对同一句中所有实体对进行关系分类
  3. 后处理:过滤低置信度结果,合并重叠三元组

关系抽取挑战与前沿

挑战 解决方案
重叠关系(一个实体参与多个关系) TPLinker、CasRel 等联合模型
少样本关系 Prompt-tuning、原型网络
文档级关系(跨句) 图神经网络(GNN)+ 文档编码
开放关系抽取 无预定义关系类型,聚类或生成式方法

小结

关系抽取从早期的特征工程发展到今天的预训练语言模型,已成为构建结构化知识的核心技术。BERT 微调 是当前工业界主流方案,而联合抽取模型 能有效缓解流水线错误传播问题。在金融、医疗、法律等专业领域,结合领域知识远程监督 是突破数据瓶颈的关键。未来,关系抽取将与大语言模型知识图谱补全多模态理解深度融合,迈向更精准、更开放的信息抽取。


资料关注

咚咚王

《Python 编程:从入门到实践》

《利用 Python 进行数据分析》

《算法导论中文第三版》

《概率论与数理统计(第四版) (盛骤) 》

《程序员的数学》

《线性代数应该这样学第 3 版》

《微积分和数学分析引论》

《(西瓜书)周志华-机器学习》

《TensorFlow 机器学习实战指南》

《Sklearn 与 TensorFlow 机器学习实用指南》

《模式识别(第四版)》

《深度学习 deep learning》伊恩·古德费洛著 花书

《Python 深度学习第二版(中文版)【纯文本】 (登封大数据 (Francois Choliet)) (Z-Library)》

《深入浅出神经网络与深度学习 +(迈克尔·尼尔森(Michael+Nielsen)》

《自然语言处理综论 第 2 版》

《Natural-Language-Processing-with-PyTorch》

《计算机视觉-算法与应用(中文版)》

《Learning OpenCV 4》

《AIGC:智能创作时代》杜雨 +&+ 张孜铭

《AIGC 原理与实践:零基础学大语言模型、扩散模型和多模态模型》

《从零构建大语言模型(中文版)》

《实战 AI 大模型》

《AI 3.0》

相关推荐
袋鼠云数栈2 小时前
构建金融级数据防线:数栈 DataAPI 的全生命周期管理实践
java·大数据·数据库·人工智能·api
扬大平仔2 小时前
我用AI写了一个AI助手
人工智能·arcgis
云飞云共享云桌面2 小时前
广东某智能装备工厂8人共享一台服务器
大数据·运维·服务器·人工智能·3d·自动化·电脑
小超同学你好2 小时前
Transformer 10. Decoder Only Transformer 架构以及每一步骤的详细计算
人工智能·语言模型·transformer
芯盾时代2 小时前
部署OpenClaw的安全风险
人工智能·安全·ai
chaors2 小时前
Langchain入门到精通0x05:预制链
人工智能·langchain·ai编程
GWQ3332 小时前
2026中国南京国际电池及储能技术博览会影响力如何?商机在哪里?
大数据·人工智能
AI工程架构师2 小时前
langChain 快速入门
人工智能
gustt2 小时前
RAG 实战:彻底搞懂 LangChain 文本切割器(Splitter)
人工智能·llm