NLP-实体&关系联合抽取-2021:GPLinker

2023-11-19

基础思路

关系抽取乍看之下是三元组 ( s , p , o ) (s,p,o) (s,p,o)(即subject, predicate, object)的抽取,但落到具体实现上,它实际是“五元组” ( s h , s t , p , o h , o t ) (s_h,s_t,p,o_h,o_t) (sh,st,p,oh,ot) 的抽取,其中 s h , s t s_h,s_t sh,st 分别是 s s s 的首、尾位置,而 o h , o t o_h,o_t oh,ot 则分别是 o o o 的首、尾位置。

从概率图的角度来看,我们可以这样构建模型:

  1. 设计一个五元组的打分函数 S ( s h , s t , p , o h , o t ) S(s_h,s_t,p,o_h,o_t) S(sh,st,p,oh,ot)
  2. 训练时让标注的五元组 S ( s h , s t , p , o h , o t ) > 0 S(s_h,s_t,p,o_h,o_t) > 0 S(sh,st,p,oh,ot)>0,其余五元组则 S ( s h , s t , p , o h , o t ) < 0 S(s_h,s_t,p,o_h,o_t) < 0 S(sh,st,p,oh,ot)<0
  3. 预测时枚举所有可能的五元组,输出 S ( s h , s t , p , o h , o t ) > 0 S(s_h,s_t,p,o_h,o_t) > 0 S(sh,st,p,oh,ot)>0 的部分。

然而,直接枚举所有的五元组数目太多,假设句子长度为 l l l p p p的总数为 n n n,即便加上 s h ≤ s t s_h≤s_t shst o h ≤ o t o_h≤o_t ohot 的约束,所有五元组的数目也有

n × l ( l + 1 ) 2 × l ( l + 1 ) 2 = 1 4 n l 2 ( l + 1 ) 2 \begin{aligned} n\times \frac{l(l+1)}{2}\times \frac{l(l+1)}{2}=\frac{1}{4}nl^2(l+1)^2 \end{aligned} n×2l(l+1)×2l(l+1)=41nl2(l+1)2

这是长度的四次方级别的计算量,实际情况下难以实现,所以必须做一些简化。

简化分解

以我们目前的算力来看,一般最多也就能接受长度平方级别的计算量,所以我们每次顶多能识别“一对”首或尾,为此,我们可以用以下的分解:
S ( s h , s t , p , o h , o t ) = S ( s h , s t ) + S ( o h , o t ) + S ( s h , o h ∣ p ) + S ( s t , o t ∣ p ) \begin{aligned} S(s_h,s_t,p,o_h,o_t) = S(s_h,s_t) + S(o_h,o_t) + S(s_h,o_h| p) + S(s_t, o_t| p) \end{aligned} S(sh,st,p,oh,ot)=S(sh,st)+S(oh,ot)+S(sh,ohp)+S(st,otp)

要注意的是,该等式属于模型假设,是基于我们对任务的理解以及算力的限制所设计出来的,而不是理论推导出来的。其中,每一项都具直观的意义,比如:

  • S ( s h , s t ) S(s_h,s_t) S(sh,st) S ( o h , o t ) S(o_h,o_t) S(oh,ot) 分别是subject、object的首尾打分,通过 S ( s h , o h ∣ p ) S(s_h,o_h|p) S(sh,ohp) S ( o h , o t ) > 0 S(o_h,o_t) > 0 S(oh,ot)>0 来析出所有的subject和object。
  • 至于后两项,则是predicate的匹配:
    • S ( s h , o h ∣ p ) S(s_h,o_h|p) S(sh,ohp) 这一项代表以subject和object的首特征作为它们自身的表征来进行一次匹配,如果我们能确保subject内和object内是没有嵌套实体的,那么理论上 S ( s h , o h ∣ p ) > 0 S(s_h,o_h|p) > 0 S(sh,ohp)>0 就足够析出所有的predicate了,但考虑到存在嵌套实体的可能,所以我们还要对实体的尾再进行一次匹配,即 S ( s t , o t ∣ p ) S(s_t, o_t|p) S(st,otp) 这一项。

此时,训练和预测过程变为:

  1. 训练时让标注的五元组 S ( s h , s t ) > 0 S(s_h,s_t) > 0 S(sh,st)>0 S ( o h , o t ) > 0 S(o_h,o_t) > 0 S(oh,ot)>0 S ( s h , o h ∣ p ) > 0 S(s_h,o_h| p) > 0 S(sh,ohp)>0 S ( s t , o t ∣ p ) > 0 S(s_t, o_t| p) > 0 S(st,otp)>0,其余五元组则 S ( s h , s t ) < 0 S(s_h,s_t) < 0 S(sh,st)<0 S ( o h , o t ) < 0 S(o_h,o_t) < 0 S(oh,ot)<0 S ( s h , o h ∣ p ) < 0 S(s_h,o_h| p) < 0 S(sh,ohp)<0 S ( s t , o t ∣ p ) < 0 S(s_t, o_t| p) < 0 S(st,otp)<0
  2. 预测时枚举所有可能的五元组,逐次输出 S ( s h , s t ) > 0 S(s_h,s_t) > 0 S(sh,st)>0 S ( o h , o t ) > 0 S(o_h,o_t) > 0 S(oh,ot)>0 S ( s h , o h ∣ p ) > 0 S(s_h,o_h| p) > 0 S(sh,ohp)>0 S ( s t , o t ∣ p ) > 0 S(s_t, o_t| p) > 0 S(st,otp)>0 的部分,然后取它们的交集作为最终的输出(即同时满足4个条件)。

在实现上:

  • 由于 S ( s h , s t ) S(s_h,s_t) S(sh,st) S ( o h , o t ) S(o_h,o_t) S(oh,ot) 是用来识别subject、object对应的实体的,它相当于有两种实体类型的NER任务,所以我们可以用一个GlobalPointer来完成;
  • 至于 S ( s h , o h ∣ p ) S(s_h,o_h| p) S(sh,ohp),它是用来识别predicate为 p p p ( s h , o h ) (s_h,o_h) (sh,oh) 对,跟NER不同的是,它这里不需要 s h ≤ o h s_h≤o_h shoh 的约束,这里我们同样用GlobalPointer来完成,但为了识别出 s h > o h s_h>o_h sh>oh 的部分,要去掉GlobalPointer默认的下三角mask;最后 S ( s t , o t ∣ p ) S(s_t,o_t|p) S(st,otp) S ( s h , o h ∣ p ) S(s_h,o_h|p) S(sh,ohp) 同理,不再赘述。

这里再回顾一遍:我们知道,作为NER模块,GlobalPointer可以统一识别嵌套和非嵌套的实体,而这是它基于token-pair的识别来做到的。所以,我们应该进一步将GlobalPointer理解为一个token-pair的识别模型,而不是局限在NER范围内理解它。认识到这一点之后,我们就能明白上述 S ( s h , s t ) S(s_h,s_t) S(sh,st) S ( o h , o t ) S(o_h,o_t) S(oh,ot) S ( s h , o h ∣ p ) S(s_h,o_h| p) S(sh,ohp) S ( s t , o t ∣ p ) S(s_t, o_t|p) S(st,otp) 其实都可以用GlobalPointer来实现了,而要不要加下三角mask,则自行根据具体任务背景设置就好。

损失函数

现在我们已经把打分函数都设计好了,那么为了训练模型,就差损失函数了。这里继续使用GlobalPointer默认使用的、在 《将“softmax+交叉熵”推广到多标签分类问题》 中提出的多标签交叉熵,它的一般形式为:

log ⁡ ( 1 + ∑ i ∈ P e − S i ) + log ⁡ ( 1 + ∑ i ∈ N e S i ) \begin{aligned} \log \left(1 + \sum\limits_{i\in \mathcal{P}} e^{-S_i}\right) + \log \left(1 + \sum\limits_{i\in \mathcal{N}} e^{S_i}\right) \end{aligned} log(1+iPeSi)+log(1+iNeSi)

实验结果

为了方便称呼,我们暂且将上述模型称为GPLinker(GlobalPointer-based Linking),一个基于bert4keras的参考实现如下:

脚本链接:task_relation_extraction_gplinker.py

在LIC2019上的实验结果如下(CasRel的代码为task_relation_extraction.py):

模型 F1 CasRel 0.8220 GPLinker (Standard) 0.8272 GPLinker (Efficient) 0.8268 \begin{array}{c|c} \hline \text{模型} & \text{F1} \\ \hline \text{CasRel} & 0.8220 \\ \text{GPLinker (Standard)} & 0.8272\\ \text{GPLinker (Efficient)} & 0.8268\\ \hline \end{array} 模型CasRelGPLinker (Standard)GPLinker (Efficient)F10.82200.82720.8268

预训练模型是BERT base,Standard和Efficient的区别是分别使用了标准版GlobalPointerEfficient GlobalPointer。该实验结果说明了两件事情,一是GPLinker确实比CasRel更加有效,二是Efficient GlobalPointer的设计确实能在更少参数的情况下媲美标准版GlobalPointer的效果。要知道在LIC2019这个任务下,如果使用标准版GlobalPointer,那么GPLinker的参数量接近1千万,而用Efficient GlobalPointer的话只有30万左右。

此外,在3090上,相比于“multi hot”版的多标签交叉熵,使用稀疏版多标签交叉熵的模型在训练速度上能提高1.5倍而不会损失精度,跟CasRel相比,使用了稀疏版多标签交叉熵的GPLinker在训练速度上只慢15%,但是解码速度快将近一倍,算得上又快又好了。

相关工作

而对于了解这两年关系抽取SOTA模型进展的同学来说,理解上述模型后,会发现它跟TPLinker是非常相似的。确实如此,模型在设计之初确实充分借鉴了TPLinker,最后的结果也同样跟TPLinker很相似。

大体上来说,TPLinker与GPLinker的区别如下:

  1. TPLinker的token-pair分类特征是首尾特征后拼接做Dense变换得到的,其思想来源于Additive Attention;GPLinker则是用GlobalPointer实现,其思想来源于Scaled Dot-Product Attention。平均来说,后者拥有更少的显存占用和更快的计算速度。
  2. GPLinker分开识别subject和object的实体,而TPLinker将subject和object混合起来统一识别。笔者也在GPLinker中尝试了混合识别,发现最终效果跟分开识别没有明显区别。
  3. S ( s h , o h ∣ p ) S(s_h,o_h|p) S(sh,ohp) S ( s t , o t ∣ p ) S(s_t,o_t|p) S(st,otp),TPLinker将其转化为了 l ( l + 1 ) 2 \cfrac{l(l+1)}{2} 2l(l+1) 个3分类问题,这会有明显的类别不平衡问题;而GPLinker用到了笔者提出的多标签交叉熵,则不会存在不平衡问题,更容易训练。事实上后来TPLinker也意识到了这个问题,并提出了TPLinker-plus,其中也用到了该多标签交叉熵。

当然,在笔者看来,本文的最主要贡献,并不是提出GPLinker的这些改动,而是对关系联合抽取模型进行一次“自上而下”的理解:从开始的五元组打分 S ( s h , s t , p , o h , o t ) S(s_h,s_t,p,o_h,o_t) S(sh,st,p,oh,ot) 出发,分析其难处,然后简化分解式 S ( s h , s t , p , o h , o t ) = S ( s h , s t ) + S ( o h , o t ) + S ( s h , o h ∣ p ) + S ( s t , o t ∣ p ) \begin{aligned}S(s_h,s_t,p,o_h,o_t) = S(s_h,s_t) + S(o_h,o_t) + S(s_h,o_h| p) + S(s_t, o_t| p)\end{aligned} S(sh,st,p,oh,ot)=S(sh,st)+S(oh,ot)+S(sh,ohp)+S(st,otp) 来“逐个击破”。希望这个自上而下的理解过程,能给读者在为更复杂的任务设计模型时提供一定的思路。




参考资料:
GPLinker:基于GlobalPointer的实体关系联合抽取
关系抽取:TPLinker与GPLinker在讲些什么
GPLinker:基于GlobalPointer的实体关系联合抽取
GPLinker:基于GlobalPointer的事件联合抽取

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NLP-实体&关系联合抽取-2021:GPLinker 的相关文章

随机推荐

  • 唯品会 京东 淘宝 得物比价1.4.1,selenium登录后再隐藏浏览器

    原创于本人微信公众号 阿嚏个技术 文章地址 Compareprice比价10月8日更新 增加京东优惠券凑单 本次更新的版本为1 4 1 主要是增加了京东优惠券凑单页面的数据采集 该凑单页面需登录后才可以达到 软件会先打开京东登录页面 通过京
  • flutter text 左对齐_03、从头开始整 Flutter--基本小部件-Text&Image

    本节大纲 教程简介 1 阅读对象 本篇教程适合新手阅读 老手直接略过 2 教程难度 初级 本人水平有限 文章内容难免会出现问题 如果有问题欢迎指出 谢谢 正文 一 组件化思想 我们前面说过 Flutter 是借鉴了 React 的组件化思想
  • 深度学习训练和测试时出现问题:error: the following arguments are required: --dataroot,解决:训练文件的配置方法和测试文件的配置方法

    在深度学习训练和测试时出现问题 error the following arguments are required dataroot 出现这种问题的主要原因是 训练的配置文件和测试的配置文件有问题 具体解决方法见下 目录 1 配置训练文件
  • el-table中sort-change容易引发的bug之显示值与获取值不符合

    最近在优化 一起自律打卡 小程序后台数据展示 想着加上一些排序和搜索 这方便自己去查阅日活或者看看小程序最近的数据状况 说干就干 后台管理是用了vue和element UI的 直接去看开发文档Table 表格 Element Plus 当时
  • Python 安装 Numpy 出现 错误:只允许在 C99 模式下使用‘for’循环初始化声明 用gcc编译出现

    在Liunx 离线安装 Numpy 时候 python setup py install 用gcc编译出现 错误 只允许在 C99 模式下使用 for 循环初始化声明 然后执行命令 CC gcc std c99 python setup p
  • 解决-画图程序无法读取-无效的位图文件

    辛苦画的图 今天一打开就看到这个 心情是呵呵的 搜了一下大概是图太大了 右击win10自带的图片 给裁剪小了就OK了
  • 《精通Spring4.x 企业应用开发实战》第20章 实战型单元测试

    前言 TestNG是必须事先掌握的基础测试框架 大多数测试框架和测试工具都在此基础上扩展而来 Spring测试框架为集成 TestNG JUnit 等单元测试框架提供了很好的支持 并为测试 Spring 应用提供了许多基础设施 在项目单元测
  • 互联网摸鱼日报(2023-03-11)

    互联网摸鱼日报 2023 03 11 InfoQ 热门话题 架构师 2023 年 3 月 世界级编程大师Bob 大叔为 干净代码 辩护遭质疑 时代变了 别用Clean Code那套要求我们了 从传统数据库痛点看分布式数据库选型问题 API
  • linux学习课程从入门到精通:Centos8用户管理

    本人从事IT行业已有十多年 有着丰富的实战经验 总结了大量的学习方法 更是积累了很多的学习资料 很高兴能在这里跟大家交流学习 希望能在这里跟大家共同进步和成长 全套学习资料移步至公众号 学神来啦 更多学习资料添加扣扣资源群 66130895
  • Compiler- 自增运算

    我们来看一下C语言中的前自增 i 和后自增 i 这个经典案例 大家在学习C的时候肯定学过前自增是先自增 然后将结果用于计算 后自增是先参与计算 再增加 好 看一下这段代码的结果 include
  • 数据结构_二元组

    今天在牛客网上看到这样一个题目 当时做的时候直接没反应过来 后来看解析的时候 才知道 二元组 图论上学过嘛 而且 我们以前也经常接触 图 V E 就是嘛 下面的解释转载自 https www cnblogs com larryzeal p
  • Python Flask怎么实现前后端分离

    你可以在 Flask 中使用 ajax 和 JSON 来实现前后端分离 首先 在 Flask 中创建一个视图函数 它会返回一个 JSON 响应 例如 app route api data def get data data key valu
  • 卷积神经网络改进想法初探(上篇)

    最近一直在看卷积神经网络 想改进改进弄出点新东西来 看了好多论文 写了一篇综述 对深度学习中卷积神经网络有了一些新认识 和大家分享下 其实卷积神经网络并不是一项新兴的算法 早在上世纪八十年代就已经被提出来 但当时硬件运算能力有限 所以当时只
  • Java并发编程之设计模式

    同步模式之保护性暂停 1 定义 即 Guarded Suspension 用在一个线程等待另一个线程的执行结果 要点 有一个结果需要从一个线程传递到另一个线程 让他们关联同一个 GuardedObject 如果有结果不断从一个线程到另一个线
  • MIPI-DSI 协议深度解析-简单易懂协议详解

    1 MIPI MIPI 移动行业处理器接口 是 Mobile Industry Processor Interface 的缩写 MIPI 移动行 业处理器接口 是 MIPI 联盟发起的为移动应用处理器制定的开放标准 DCS DisplayC
  • vue项目history模式刷新404问题

    vue项目history模式部署到服务器后 根路径访问没有问题 但是进入其他功能再刷新页面就会出现404 因为你没在nginx或者apache配置上面加上重定向跳转 解决办法 只需要加上这段配置 nginx配置内容 location try
  • DNS详解

    1 背景 DNS 是 Domain Name System 的缩写 即域名系统 DNS可以理解是将域名 如 www baidu com 和IP地址进行相互映射的一个分布式数据库 人直接去记忆IP地址数串是相当困难的 像是电话号码 记忆常用的
  • VUE+js高德地图2.0API两幅地图联动同步缩放

  • 主机上连接到 vmware虚拟机的方式

    我们平时只有一台电脑 但是练习时需要有多台电脑 那么此时应该怎么办 答案是下载 vmware 可以在上面创建多台虚拟机 至于如何创建 不是本文的重点 下面先说说桥接是如何设置的 首先 进入配置好的虚拟机下面 选择 虚拟机 设置 网络适配器
  • NLP-实体&关系联合抽取-2021:GPLinker

    基础思路 关系抽取乍看之下是三元组 s p o s p o s p o 即subject pre