学习 OpenNRE:基于深度学习的关系抽取模型

📅 2026/6/28 6:04:36
学习 OpenNRE:基于深度学习的关系抽取模型
学习 OpenNRE基于深度学习的关系抽取模型1. 为什么要学习 NRE关系抽取的任务是从非结构化文本中识别两个实体之间的语义关系。例如Bill Gates founded Microsoft.如果已经知道实体Bill Gates和Microsoft的位置关系抽取模型需要判断二者之间的关系输出类似(Bill Gates, founded, Microsoft)这类三元组可以进一步进入知识图谱用于搜索、问答、推荐、风控、舆情分析、科研知识管理等任务。OpenNRE 是清华大学 THUNLP 开源的神经关系抽取工具包。它是把关系抽取拆成了几个相对清晰的模块数据读取 - 文本编码器 - 关系分类/Bag 聚合模型 - 训练框架 - 评估与推理2. OpenNRE 支持的任务设定OpenNRE 主要覆盖两类关系抽取任务。第一类是句子级关系抽取sentence-level relation extraction。输入是一句话以及句中两个实体的位置。模型直接判断这两个实体之间的关系。例如{text:Bill Gates founded Microsoft in 1975.,h:{pos:(0,10)},t:{pos:(19,28)}}输出founder, 0.93第二类是远程监督关系抽取远程监督的假设是如果知识库中存在(h, r, t)那么包含实体对(h, t)的句子可能表达关系r。但这会带来噪声因为不是每个包含实体对的句子都真的表达这个关系。因此 OpenNRE 会把同一个实体对或同一个关系事实对应的多个句子组成一个 bag再在 bag 内做one / average / attention聚合。可以简单理解为句子级 RE一句话判断一次关系 Bag 级 RE多句话共同判断一个实体对的关系3. 项目代码结构OpenNRE 的核心代码集中在opennre目录下结构大致如下OpenNRE/ opennre/ __init__.py pretrain.py encoder/ base_encoder.py cnn_encoder.py pcnn_encoder.py bert_encoder.py model/ base_model.py softmax_nn.py sigmoid_nn.py bag_one.py bag_average.py bag_attention.py framework/ data_loader.py sentence_re.py bag_re.py multi_label_sentence_re.py module/ nn/ cnn.py rnn.py lstm.py pool/ max_pool.py avg_pool.py tokenization/ word_tokenizer.py bert_tokenizer.py basic_tokenizer.py word_piece_tokenizer.py example/ train_supervised_bert.py train_supervised_cnn.py train_bag_bert.py train_bag_cnn.py test_multilabel_bert.py test_multilabel_cnn.py可以按功能这样理解模块作用pretrain.py下载数据、下载预训练模型、通过get_model()加载已训练模型encoder/把输入文本和实体位置编码成向量model/在句向量或 bag 向量上做关系分类framework/封装训练、验证、测试、指标计算module/一些底层神经网络组件tokenization/分词与 token id 转换example/官方训练脚本适合作为自己实验的入口这是一种比较经典的深度学习项目组织方式encoder负责表示学习model负责任务头framework负责训练流程。4. 数据格式模型到底吃什么OpenNRE 的句子级数据是一行一个 Python 字典风格的样本。核心字段包括{text:Bill Gates founded Microsoft in 1975.,h:{pos:[0,10]},t:{pos:[19,28]},relation:founder}其中字段含义text原始句子token可选如果已经预分词可以用 token 序列代替 texthhead entity头实体ttail entity尾实体pos实体在句子中的位置relation关系标签推理时不需要relation训练时需要。需要注意如果使用textpos通常是字符级区间如果使用tokenpos是 token 级区间。5. 模型结构一CNN / PCNN 编码器OpenNRE 的 CNN 编码器位于opennre/encoder/cnn_encoder.py opennre/encoder/pcnn_encoder.py以CNNEncoder为例它的输入包括token: 词 id 序列 pos1: 每个 token 到头实体的相对位置 pos2: 每个 token 到尾实体的相对位置编码流程可以概括为word embedding position embedding to head entity position embedding to tail entity ↓ 拼接成 token 表示 ↓ 1D CNN ↓ ReLU ↓ MaxPool ↓ 句子向量也就是[word_emb; pos1_emb; pos2_emb] - Conv1D - MaxPool - sentence representation普通 CNN 使用整句 max pooling。PCNNPiecewise CNN则进一步利用两个实体的位置把句子切成三段实体前片段 / 两实体之间片段 / 实体后片段分别池化后再拼接因此 PCNN 更显式地利用实体相对位置。OpenNRE 中PCNNEncoder的hidden_size最后会变成三倍因为它拼接了三个片段的池化结果。6. 模型结构二BERT 编码器OpenNRE 的 BERT 编码器位于opennre/encoder/bert_encoder.py它提供两种池化方式。第一种是BERTEncoder使用 BERT 的 pooled output也就是常见的[CLS]表示输入句子 - BERT - pooled output - 关系分类第二种是BERTEntityEncoder不直接使用[CLS]而是取头实体起始位置和尾实体起始位置的 hidden state然后拼接head entity hidden state tail entity hidden state ↓ concat ↓ linear ↓ relation representation这对关系抽取很自然因为关系本来就是两个实体之间的语义联系。相比单纯用[CLS]实体表示拼接通常能更明确地告诉模型当前要判断的是哪两个实体。OpenNRE 还会在 BERT 输入中插入特殊标记[unused0] head entity [unused1] [unused2] tail entity [unused3]这相当于给 BERT 明确标注实体边界。7. 模型结构三SoftmaxNN 和 SigmoidNN句子级分类模型主要在opennre/model/softmax_nn.py opennre/model/sigmoid_nn.pySoftmaxNN的结构非常简单sentence_encoder - dropout - Linear(hidden_size, num_class) - logits推理时logits - softmax - 取概率最大的关系它适合单标签关系抽取也就是一个实体对在一个句子中只预测一个关系。SigmoidNN则使用 sigmoid将每个关系看成一个独立的二分类问题适合多标签场景即一句话或一个实体对可能同时对应多个关系。8. 模型结构四Bag 级关系抽取远程监督关系抽取的核心问题是噪声。例如知识库中有(Apple, founded_by, Steve Jobs)但新闻里所有同时出现Apple和Steve Jobs的句子并不一定都表达founded_by。有的可能只是说 Steve Jobs 回归 Apple有的可能是产品发布会背景。因此 Bag 级模型不会只看单句而是看一个实体对对应的一组句子。OpenNRE 提供了三种 bag 聚合方式模型文件思想BagOnemodel/bag_one.py从 bag 中选择最能表达目标关系的一句话BagAveragemodel/bag_average.py对 bag 内句子表示取平均BagAttentionmodel/bag_attention.py对 bag 内不同句子分配注意力权重其中BagAttention最有代表性。它的思想是同一个 bag 中不同句子对关系判断的贡献不同模型应该自动学会关注更有用的句子。可以把它理解为bag [sentence_1, sentence_2, ..., sentence_n] 每个 sentence_i 先经过 encoder 得到 rep_i 然后根据当前关系计算 attention score 再加权求和得到 bag representation 最后做关系分类训练时OpenNRE 会根据已知标签取对应关系的分类权重作为 query计算每个句子的注意力分数。测试时它会为每个候选关系分别计算 attention再得到每个关系的置信度。这就是论文中常见的“instance-level attention for distant supervision”思想。9. 训练框架OpenNRE 如何跑实验训练逻辑主要在opennre/framework/sentence_re.py opennre/framework/bag_re.py opennre/framework/data_loader.py句子级训练流程如下读取 train / val / test 文件 ↓ SentenceRELoader 构建 DataLoader ↓ 调用 model(*args) 得到 logits ↓ CrossEntropyLoss ↓ 反向传播 loss.backward() ↓ optimizer.step() ↓ 在验证集上计算 acc / micro precision / micro recall / micro F1 ↓ 保存最优 checkpointBag 级训练流程类似但 DataLoader 会先构造 bag读入所有句子 ↓ 按实体对或关系事实分组 ↓ 每个 batch 包含多个 bag ↓ 模型对 bag 预测关系 ↓ 用 AUC / micro F1 等指标评估这两个 framework 的设计有一个优点如果你要换模型通常只需要换encoder或model训练流程可以复用。10. 快速推理直接调用预训练模型OpenNRE 提供了get_model()可以直接加载预训练模型。官方 README 中支持的模型包括wiki80_cnn_softmax wiki80_bert_softmax wiki80_bertentity_softmax tacred_bert_softmax tacred_bertentity_softmax最小推理代码如下importopennre modelopennre.get_model(wiki80_bertentity_softmax)item{text:Bill Gates founded Microsoft in 1975.,h:{pos:(0,10)},t:{pos:(19,28)}}relation,scoremodel.infer(item)print(relation,score)如果有 GPUmodelmodel.cuda()11. 实际场景设计企业新闻知识图谱自动构建下面设计一个实际场景从企业新闻、公告、研报中抽取结构化关系构建“公司-人物-产品-地区”的知识图谱。11.1 场景目标输入是一批企业相关新闻例如Tesla appointed Tom Zhu as senior vice president of automotive operations. Microsoft acquired Activision Blizzard in 2023. Apple released Vision Pro in the United States.希望抽取出(Tesla, appoint, Tom Zhu) (Microsoft, acquire, Activision Blizzard) (Apple, release_product, Vision Pro) (Vision Pro, released_in, United States)这些结果可以用于企业图谱构建 投研信息抽取 产业链分析 舆情监控 自动问答 搜索增强11.2 系统流程一个可落地的系统可以分为五步1. 文档采集新闻、公告、网页、PDF 2. 实体识别识别人名、公司名、产品名、地区名 3. 候选实体对生成在同一句中两两组合实体 4. OpenNRE 关系预测对每个实体对判断关系 5. 三元组入库写入 Neo4j、PostgreSQL 或 Elasticsearch更具体一点raw text ↓ sentence split ↓ NER / entity linking ↓ candidate pairs ↓ OpenNRE infer ↓ confidence filtering ↓ triples ↓ knowledge graph11.3 调用示例下面是一个简化版示例。为了突出 OpenNRE 的调用方式这里假设实体识别已经完成。importopennredefspan_of(text,entity):starttext.index(entity)endstartlen(entity)returnstart,end modelopennre.get_model(wiki80_bertentity_softmax)textMicrosoft acquired Activision Blizzard in 2023.headMicrosofttailActivision Blizzarditem{text:text,h:{name:head,pos:span_of(text,head)},t:{name:tail,pos:span_of(text,tail)}}relation,scoremodel.infer(item)ifscore0.7:triple{head:head,relation:relation,tail:tail,score:score,source:text}print(triple)输出形式可以设计成{head:Microsoft,relation:acquirer,tail:Activision Blizzard,score:0.86,source:Microsoft acquired Activision Blizzard in 2023.}真实系统中还需要做几件事同义实体归一化Microsoft、Microsoft Corp.、MSFT 要归一成同一实体 关系标签映射把模型标签映射成业务关系如 acquired_by、founded_by 置信度阈值低分关系进入人工审核 去重同一个三元组可能来自多篇文章 溯源保留原文、句子、发布时间、来源 URL11.4 批量抽取示例如果一篇文章中已经识别出多个实体可以批量生成候选实体对importitertoolsimportopennredefbuild_item(text,h,t):return{text:text,h:{name:h[name],pos:h[pos]},t:{name:t[name],pos:t[pos]}}defextract_relations(text,entities,model,threshold0.7):triples[]forh,tinitertools.permutations(entities,2):itembuild_item(text,h,t)relation,scoremodel.infer(item)ifrelationnotin[NA,no_relation]andscorethreshold:triples.append({head:h[name],relation:relation,tail:t[name],score:float(score),source:text})returntriples modelopennre.get_model(wiki80_bertentity_softmax)textMicrosoft acquired Activision Blizzard in 2023.entities[{name:Microsoft,type:ORG,pos:(0,9)},{name:Activision Blizzard,type:ORG,pos:(19,38)}]triplesextract_relations(text,entities,model)print(triples)这个示例可以作为企业知识图谱抽取服务的原型。12. 总结OpenNRE 是一个适合学习神经关系抽取的开源框架。它把关系抽取任务拆成了数据、编码器、分类模型、bag 聚合和训练框架几个部分代码结构比较清楚。从模型角度看OpenNRE 支持 CNN、PCNN、BERT 等编码器也支持句子级分类和远程监督 bag 级分类。从工程角度看它提供了数据加载、训练、验证、测试、checkpoint 保存和预训练模型调用适合快速复现实验。