600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 知识图谱-LSTM+CRF人物关系抽取实战

知识图谱-LSTM+CRF人物关系抽取实战

时间:2018-08-17 23:39:04

相关推荐

知识图谱-LSTM+CRF人物关系抽取实战

文章目录

一、引言二、实践简介1、数据来源2、预测类别(7个)3、框架4、模型结构5、项目流程三、数据标注四、实战1、数据预处理1.1 词典映射1.2 从训练文件中获取句子和标签1.3 输入文本转id1.4 数据填充2、模型构建3、测试4、总结

一、引言

本文的idea主要来源于LSTM+CRF的命名实体识别,在命名实体识别中,可以通过BIO或者BIOSE等标注进行人名、地名、机构名或者其他专有名词的识别,那么把三元组的主语、谓语、宾语(也可理解为:实体-关系-实体)三个部分当成三个需要识别的专有名词,也就可以实现三元组的抽取了,基于此想法,具体实践看看效果。

二、实践简介

1、数据来源

本文主要基于历史文章中的人物关系抽取,数据来源于和/

2、预测类别(7个)

主语开头:B-SUBJECT

主语非开头:I-SUBJECT

谓语开头:B-PREDICATE

谓语非开头:I-PREDICATE

宾语开头:B-OBJECT

宾语非开头:I-OBJECT

其他:O

3、框架

keras

4、模型结构

本次抽取本质上还是基于LSTM的一个分类问题,至于CRF层,完全是为了保证序列的输出严格性,因为CRF对于预测序列有较强的的限制性,比如B-PRESON后面只能为I-PERSON或者O之类的限制。

_________________________________________________________________Layer (type) Output Shape Param # =================================================================embedding_1 (Embedding)(None, 91, 100) 60000_________________________________________________________________bidirectional_1 (Bidirection (None, 91, 100) 60400_________________________________________________________________time_distributed_1 (TimeDist (None, 91, 7) 707 _________________________________________________________________crf_1 (CRF) (None, 91, 7) 119 =================================================================Total params: 121,226Trainable params: 61,226Non-trainable params: 60,000

5、项目流程

# 获取词典映射word2id, tag2id, id2word, id2tag = getWordAndTagId('train.txt')# 获取句子和标注sentences, tags=getSentencesAndTags('train.txt')# 将句子和标注转换为idsentencesIds, tagsIds = sentencesAndTags2id(sentences, tags,word2id, tag2id)# 将句子和标注进行填充,确保输入维度一致sentencesIds = pad_sequences(sentencesIds, padding='post')tagsIds = pad_sequences(tagsIds, padding='post')print(sentencesIds.shape)print(tagsIds.shape)# 载入模型model=model(len(word2id),100,sentencesIds.shape[1],len(tag2id))# 训练history = model.fit(sentencesIds, tagsIds.reshape([len(tagsIds),-1,1]), epochs=500)

三、数据标注

关于训练数据,未找到合适的标注数据,只能自己标注了,如下:

长 B-SUBJECT孙 I-SUBJECT无 I-SUBJECT忌 I-SUBJECT看 O到 O外 B-PREDICATE甥 I-PREDICATE承 B-OBJECT乾 I-OBJECT、 O李 B-OBJECT泰 I-OBJECT都 O完 O了 O。 O唐 B-SUBJECT玄 I-SUBJECT宗 I-SUBJECT有 O两 O个 O同 O母 O妹 B-PREDICATE妹 I-PREDICATE: O金 B-OBJECT仙 I-OBJECT公 I-OBJECT主 I-OBJECT和 O玉 B-OBJECT真 I-OBJECT公 I-OBJECT主 I-OBJECT。 O...此处省略n多李 B-SUBJECT文 I-SUBJECT有 O两 O个 O妹 B-PREDICATE妹 I-PREDICATE, O一 O个 O叫 O宇 B-OBJECT宇 I-OBJECT, O一 O个 O叫 O佳 B-OBJECT佳 I-OBJECT。 O

四、实战

1、数据预处理

1.1 词典映射

主要是低频词过滤字与id的映射(word2id)、预测类别与id的映射(lable2id),具体实现方式各有不同,不做重点讲解,但要特别注意未登录词的处理:

word_size = len(words)word2id = {count[0]: index for index, count in enumerate(words,start=1)} id2word = {index: count[0] for index, count in enumerate(words,start=1)}tag2id = {count[0]: index for index, count in enumerate(tags)}id2tag = {index: count[0] for index, count in enumerate(tags)}# 填充词word2id['<PAD>'] = 0# 未登录词word2id['<UNK>'] = word_size + 1

1.2 从训练文件中获取句子和标签

def getSentencesAndTags(filePath):'''从文件里面获取句子和标注:param filePath::return:'''with open(filePath,encoding='utf-8') as file:wordsAndtags=[line.split() for line in file]sentences=[]tags=[]sentence=[]tag=[]for wordAndTag in wordsAndtags:if len(wordAndTag)==2:sentence.append(wordAndTag[0])tag.append(wordAndTag[1])else:sentences.append(sentence)tags.append(tag)sentence=[]tag = []return sentences,tags

1.3 输入文本转id

将输入的文本,通过词典,转换成数字序列:

def sentencesAndTags2id(sentences,tags,word2id, tag2id):'''将句子和标注转换为id:param sentences::param tags::param word2id::param tag2id::return:'''sentencesIds = [[word2id.get(char,len(word2id)) for char in sentence] for sentence in sentences]tagsIds = [[tag2id[char] for char in tag] for tag in tags]return sentencesIds,tagsIds

1.4 数据填充

为了保证数据的维度一致,进行句子填充

from keras_preprocessing.sequence import pad_sequencessentencesIds = pad_sequences(sentencesIds, padding='post')tagsIds = pad_sequences(tagsIds, padding='post')

2、模型构建

def model(vocabSize,embeddingDim,inputLength,tagSize):model = Sequential()model.add(Embedding(vocabSize + 1,embeddingDim,input_length=inputLength,mask_zero=True))model.add(Bidirectional(LSTM(50, return_sequences=True)))model.add(TimeDistributed(Dense(tagSize)))crf_layer = CRF(tagSize, sparse_target=True)model.add(crf_layer)pile('adam', loss=crf_layer.loss_function, metrics=[crf_layer.accuracy])model.summary()return model

3、测试

通过简单的测试结果如下:

比较简单的句子上都能取得比较好的成果,但是由于训练数据不够,还是会出现无法抽取到结果或者抽取错误的情况,比如:

4、总结

本文主要针对历史故事的人物关系进行抽取,从数据获取,到数据标注,到模型训练。由于时间和人力关系,很多方面都采取了简单模式,比如数据标注,数据量远远没有达到一个量级,比如测试环节,主要还是通过人为观察抽取结果来验证是否准确,无法达到工业级别。但对于三元组的抽取,可以作为一种参考和借鉴。

特别说明:鉴于好多童鞋使用代码,但是运行不起来,在这里说明一下代码的版本情况

tensorflow=1.14.0

keras=2.2.4

keras-contrib=2.0.8

keras-contrib安装参考:/keras-team/keras-contrib

另外由于本人没能及时回复的原因,代码已放在

LSTM+CRF人物关系抽取实战下载,找到资源下载模块自取

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。