关系抽取模型介绍和实践

关系抽取预知识和发展介绍

事实知识:
三元组表示实体间关系

关系抽取:
文本中蕴藏含着大量事实知识
一个完整关系抽取系统通常包含以下模块:
NER
Entity Linking(避免重复添加到知识图谱、消歧)
Relation Classification

构成知识图谱:
知识图谱下游:搜索引擎、问答系统。。。

关系抽取模型的发展
Pattern Mining
Feature-Based Methods
Kernel-Based Methods(SVM等)
Graphical Models
Neural Models

神经网络关系抽取
RecursiveNN
CNN
RNN(word embbeding,position embedding)
Graph Neural Networks(信息传递,推理)
Transformers

经典关系抽取:大量、人工训练数据,单句内,限定关系集的关系分类

实际应用挑战和解决方案
数据获取昂贵-----远程监督(引入噪声)
远程监督降噪:
在这里插入图片描述
关系长尾现象严重(数据不平衡)------少次学习,N-Way K-Shot(易受到噪声的干扰)
在这里插入图片描述
给句子不同权重,给特征不同维度权重
在这里插入图片描述
设定简单
在这里插入图片描述

度量:
Prototypical Ner
在这里插入图片描述

许多事实知识隐藏再更复杂的上下文中-----文档关系抽取

关系的不断增长—开放的关系抽取
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

参照:实体抽取的现状和未来

实体抽取简介

NER又称作专名识别,是自然语言处理中的一项基础任务,应用范围非常广泛。命名实体一般指的是文本中具有特定意义或者指代性强的实体,通常包括人名、地名、组织机构名、日期时间、专有名词等。NER系统就是从非结构化的输入文本中抽取出上述实体,并且可以按照业务需求识别出更多类别的实体,比如产品名称、型号、价格等。因此实体这个概念可以很广,只要是业务需要的特殊文本片段都可以称为实体。

NER是NLP中一项基础性关键任务。从自然语言处理的流程来看,NER可以看作词法分析中未登录词识别的一种,是未登录词中数量最多、识别难度最大、对分词效果影响最大问题。同时NER也是关系抽取、事件抽取、知识图谱、机器翻译、问答系统等诸多NLP任务的基础。

BIO标注:将每个元素标注为“B-X”、“I-X”或者“O”。其中,“B-X”表示此元素所在的片段属于X类型并且此元素在此片段的开头,“I-X”表示此元素所在的片段属于X类型并且此元素在此片段的中间位置,“O”表示不属于任何类型。

参考:https://blog.csdn.net/qq_27586341/article/details/103062651

关系抽取简介

实体抽取后,抽取实体间的关系。是知识图谱的基础

对于有监督的关系抽取任务,通常也将其分为两大类
Pipline:将实体抽取与关系抽取分为两个独立的过程,关系抽取依赖实体抽取的结果,容易造成误差累积
Joint Model:实体抽取与关系抽取同时进行,通常用模型参数共享的方法来实现
参考:https://www.cnblogs.com/sandwichnlp/p/12020066.html

BERT 模型的使用主要有两种用途:
一、当作文本特征提取的工具,类似Word2vec模型一样
二、作为一个可训练的层,后面可接入客制化的网络,做迁移学习
本次模型使用第一次用途。

实践

对有标签和实体信息的数据做关系抽取模型训练。

思路:

关系抽取模型,基于管道模型的思路,先进行实体抽取,依据实体抽取的结果根据先验知识组合判断,训练数据是已经标记了的数据。也有实体抽取模型可以预测得到数据。

模型输入的数据

模型输入的数据是文本,已经明确实体类型和位置的数据,根据实体类型可以直接排除掉一些关系类型(先验知识)。两两组合判断就将关系抽取转换为二分类,输入关系类型和实体信息,判断是否存在这种关系。正例样本就是两两组合正确的样本,负例样本就是组合不正确的样本(即实体A[1,2,3],实体B[‘a’,‘b’],若果1和a存在关系,则组合为正样本,而1和b组合就是负样本)。

模型输入格式:4部分
直接送入bert模型的序列数据,仿照token功能进行构造
实体位置信息数据,头实体,尾实体embedding
以实体为中心,进行实体周边位置的联合embedding
类别one-hot编码信息

实现

函数主要包括:模型、评价函数、loss作图函数、训练验证模型函数,加载转换数据、预测数据的函数。数据来源于现病史,个人史,主诉,现病史数据较长,如果超过bert510字符限制,需要再单独处理。

做的时候感到的难点:

1.模型构成
2.转换数据(创建负样本,转换中间数据格式确定)
3.记录每种关系类型的accuracy,precision,recall,f1,数量等信息
4.预测:根据实体抽取模型/标记数据的到的实体类型和位置信息,再根据先验知识(某两个实体只存在某些关系或者不存在关系),设置最大间距长度,如果两个实体间距超过多少则默认不再判断关系

建议:

1.服务器上,文件名最好用英文,不然可能报文件不存在的错误(乱码)
程序后台运行等代码的命令

nohup python -u main.py > log.txt 2>&1 &
ps -ef|grep python
kill - 9 PID号

source home/env/pytorch_1.6/bin/activate激活多个环境中的一个

2.输入格式注意,输入最好一个batch,各个类别正负样本均衡,保证模型的泛化性,并且每条数据格式一致,且需要打乱顺序

3.如果在多核gpu跑,可能报错,caught runtimeError in replica 0 on device 0.这是因为第一个gpu有数据计算,第二个没有,比如数据共有100,batch是40,有2个gpu,第一轮后只剩下20条数据,分给第一个gpu后,第二个gpu上就没有数据了。解决办法,把最后一个epoch,不足一个batch数据丢掉,或者调整batch;loss也要mean(),否则会报错

4.模型编写时,判断一下device,并且模型输入和标签和loss函数 都要to.device(),

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu'
model.to(device)
if torch.cuda.device_count()>0
	model = torch.nn.DataParallel(model)

if torch.cuda.device_count()>0:
	loss = loss.mean()

5.模型保存,再多核GPU上训练的模型,直接到cpu上加载会报错,因此model=model.module,再保存

6.过程数据,包括每种关系的f1,accuracy,…,全部关系,最好记录,否则没有衡量的法则

7.如果batch太大,测试集跑完后,第二轮保存了第一轮的参数后,就没有多余的内存跑了,报错cuda out of memory,需要减少batch,
并释放内存torch.cuda.empty_cache()删除一些不需要的变量,或者

8.用utf-8读取excel可能报错,utf-8 codec can’t decode byte …,就换一个编码,gbk,或者gb18030,扩大编码范围,pd.read_csv(file_path,encoding=’’)

9.弄清楚自己写的代码意思,不然跑了很久才报错,调试成本太大。并且做的时候校验下,适当输出一些肉眼能判断是否数据正确的信息。

10.保存与加载模型,模型是在多上GPU跑的,但调试是在cpu上的电脑做的

model_to_save = model.module if hasattr(model,"module") else model
torch.save({
'model_state_dict':model_to_save.state_dict()
},save_path,__use__new_zipfile_serialzation=Fale)

11.比较loss,在区间中比较,前n个loss最小的与当前loss相减,如果小于***,则跳出

加载

model = Model()
checkpoint = torch.load(save_path,map_location='cpu')
model.load_state_dict(checkpoint ['model_state_dict'],False)
#如果不加False会报错,有个key,bert_model.embeddings.position_ids或找不到

代码优化方向:
深度学习:需要了解更多,方才能更好调参和定位问题
函数方面:解耦(做着做着可能发现数据类型需要修改)
多用高阶函数,map替代多个for循环

预知识:
输入模型的数据格式。
输入数据包括四部分,直接送入bert模型的序列数据,第二部分是实体位置信息数据,第三部分是以实体为中心,进行实体周边位置联合embedding,第四部分是onehot编码信息
在这里插入图片描述
实体模型输入一个文本,输出:实体类型,索引,文本,这些信息预测关系类型将会用到,格式类似如下
在这里插入图片描述

关系模型(使用transformer的bertModel得到词向量,并冻结前几层,避免重新训练模型)

结果:经过9个epoch,2次测试,
发现优化器选择Adam较SGDloss收敛需要的次数更少,以后用Adam当默认优化器。对于window=10,优化器为SGD,epoch=9总体来说f1(第四列)不错,大部分超过75%,注意,测试了2次,其中另一个测试B,其中一类经过7个epoch精准度还是30%,但是当前有两个类f1只有60%多,测试B的f1除了一个类,其余类f1都超过了75%。说明还没有拟合足够,需要继续迭代计算,把训练集loss_flag设置小点,比如0.001,可能至少要迭代10轮,训练集loss几乎不变才说明不能继续迭代了,或者计算验证集的loss,当current loss比之前最小的loss小,则保存模型
在这里插入图片描述
epoch=2,优化器选择Adam,可以看到效果很好在这里插入图片描述
模型预测输出结果(包括实体预测),线上返回格式应为json格式的文件:
key:content,text_id,entity,relation,大概如下
在这里插入图片描述
真实使用中,由于负样本太多,就算模型f1达到80%多,结果还是很差,可以借助规则方面的tip改善

补充:后来发现负样本生成有错误地方,修改后,在打乱标签的数据验证,平均f1达到96%,数据处理非常中央

关键函数

(用手机照的)

关系模型:
在这里插入图片描述

在这里插入图片描述
数据加载转换函数:
先得到每个数据对应负样本,如果该文本同种类型只存在一个,则该类型无法创建负样本,先判断该类型在该句子是否存在多个
把每个类的数据分别放在一个篮子里,然后用过抽样的方式,让每种类别数量相等,正负样本数量也相等,然后从每个篮子依次抽取batch_size/类别数量/2 条数据,形成一个batch,加载的到的数据就有多个batch.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
data_balance函数:
首先把数据分成训练集和测试集,训练集采用过抽样,保证每种类别的数量均衡
在这里插入图片描述

评价函数,训练的时候也打印出结果,在服务器excel不方便查看
在这里插入图片描述

模型训练代码:此时的数据,一个list有n个listA,每个listA有42条数据,每种类别分别2个正,2个负例子,在模型训练中list可以suffle,(不用在数据加载函数suffle,不然每次从头开始训练的时候训练集的数据可能都不同)
在这里插入图片描述

在这里插入图片描述

主函数:有7种关系,batch_size必须是14的倍数

在这里插入图片描述

预测函数
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 1
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值