关系抽取是自然语言处理中的一个重要的任务。关系抽取任务分为pipline式抽取和joint line式抽取。其中pipline抽取的方式一般将关系抽取分为两个过程,分别是先进行实体抽取,在对实体进行分类得到实体间的关系,将关系抽取转化为一个分类问题。joint line式抽取是同时抽取实体和关系,joint line式关系抽取将会成为关系抽取的一个重要方向。本博客介绍一个关系抽取想法比较好的模型——R-BERT模型。内容大致分为以下几个部分:
R-BERT模型是基于预训练BERT模型的关系分类模型,模型的核心部分大致如下:
(1)利用预训练BERT进行字词的特征表示
(2)抽取出预训练BERT分类任务中特殊标记符号的"[CLS]"的特征信息,subject的特征信息以及object的特征信息进行关系分类。
R-BERT模型中利用了实体的信息进行分类,提出了一种新的关系分类模型。R-BERT模型结构如下图:
R-BERT模型的作者开源了代码,是在torch和transformers实现的。下面介绍subject和object两个实体的抽取以及实体间的关系分类。
(1)subject和object实体抽取
def entity_average(hidden_output, e_mask):
"""
Average the entity hidden state vectors (H_i ~ H_j)
:param hidden_output: [batch_size, j-i+1, dim]
:param e_mask: [batch_size, max_seq_len]
e.g. e_mask[0] == [0, 0, 0, 1, 1, 1, 0, 0, ... 0]
:return: [batch_size, dim]
"""
e_mask_unsqueeze = e_mask.unsqueeze(1) # [b, 1, j-i+1]
length_tensor = (e_mask != 0).sum(dim=1).unsqueeze(1) # [batch_size, 1]
# [b, 1, j-i+1] * [b, j-i+1, dim] = [b, 1, dim] -> [b, dim]
sum_vector = torch.bmm(e_mask_unsqueeze.float(), hidden_output).squeeze(1)
avg_vector = sum_vector.float() / length_tensor.float() # broadcasting
return avg_vector
对subject和object进行0和1的mask,在实体位置处mask为1,其余位置mask为0,从而获取到subject和object的预训练字词的表征。
(2)关系分类
self.cls_fc_layer = FCLayer(config.hidden_size,
config.hidden_size,
args.dropout_rate)
self.entity_fc_layer = FCLayer(config.hidden_size,
config.hidden_size,
args.dropout_rate)
self.label_classifier = FCLayer(
config.hidden_size * 3,
config.num_labels,
args.dropout_rate,
use_activation=False,
)
其中FCLayer是全连接层。
(3)R-BERT对subject和object前后插入特殊符号进行实体标记。
在ccks2019关系抽取数据集上,R-BERT模型效果见下图
以上是对R-BERT模型的介绍,如有不准确的地方,欢迎大家指正。