零基础入门--中文命名实体识别(BiLSTM+CRF模型,含代码)

版权声明:转载请注明博客地址谢谢。 https://blog.csdn.net/buppt/article/details/81180361

自己也是一个初学者,主要是总结一下最近的学习,大佬见笑。

中文分词

说到命名实体抽取,先要了解一下基于字标注的中文分词。
比如一句话

“我爱北京天安门”。

分词的结果可以是

“我/爱/北京/天安门”。

那什么是基于字标注呢?

“我/O 爱/O 北/B 京/E 天/B 安/M 门/E”。

就是这样,给每个字都进行一个标注。我们可以发现这句话中字的标注一共有四种。他们分别代表的意义如下。

B | 词首
M | 词中
E | 词尾
O | 单字

B表示一个词的开始,E表示一个词的结尾,M表示词中间的字。如果这个词只有一个字的话,用O表示。

命名实体识别

数据处理

了解了中文分词,那么实体识别也差不多。就是把不属于实体的字用O标注,把实体用BME规则标注,最后按照BME规则把实体提取出来就ok了。

数据可以自己标注,也可以找个公开的数据集先练练手。我是用的是玻森数据提供的命名实体识别数据,https://bosonnlp.com 这是官网,在数据下载里面有一个命名实体识别数据集,或者在我的github里下载。

这个数据集一个包含了6个实体类别:

time: 时间
location: 地点
person_name: 人名
org_name: 组织名
company_name: 公司名
product_name: 产品名

例:

{{product_name:浙江在线杭州}}{{time:4月25日}}讯(记者{{person_name: 施宇翔}} 通讯员 {{person_name:方英}})毒贩很“时髦”,用{{product_name:微信}}交易毒品。没料想警方也很“潮”,将计就计,一举将其擒获。

每个实体用都用大括号括了起来,并标明实体类别。当然自己标注的时候也不一定要这么标,只要能提取出来就可以。

然后我们要做的就是把原始数据按照BMEO规则变成字标注的形式,以便模型训练。这使用python实现还是比较简单的,嫌麻烦的可以看我github里的代码。按字标注后结果如下。

浙/B_product_name 江/M_product_name 在/M_product_name 线/M_product_name 杭/M_product_name 州/E_product_name 4/B_time 月/M_time 2/M_time 5/M_time 日/E_time 讯/O (/O 记/O 者/O /B_person_name 施/M_person_name 宇/M_person_name 翔/E_person_name /O 通/O 讯/O 员/O /O 方/B_person_name 英/E_person_name )/O 毒/O 贩/O 很/O “/O 时/O 髦/O ”/O ,/O 用/O 微/B_product_name 信/E_product_name 交/O 易/O 毒/O 品/O 。/O 没/O 料/O 想/O 警/O 方/O 也/O 很/O “/O 潮/O ”/O ,/O 将/O 计/O 就/O 计/O ,/O 一/O 举/O 将/O 其/O 擒/O 获/O 。

然后我们习惯按照标点符号把一个长句分成几个短句,反正一般实体里面也没有标点符号。结果如下。

浙/B_product_name 江/M_product_name 在/M_product_name 线/M_product_name 杭/M_product_name 州/E_product_name 4/B_time 月/M_time 2/M_time 5/M_time 日/E_time 讯/O
记/O 者/O /B_person_name 施/M_person_name 宇/M_person_name 翔/E_person_name /O 通/O 讯/O 员/O /O 方/B_person_name 英/E_person_name
毒/O 贩/O 很/O
时/O 髦/O
用/O 微/B_product_name 信/E_product_name 交/O 易/O 毒/O 品/O
没/O 料/O 想/O 警/O 方/O 也/O 很/O
潮/O
将/O 计/O 就/O 计/O
一/O 举/O 将/O 其/O 擒/O 获/O

然后的思路就是建立一个word2id词典,把每个汉字转换成id。这里习惯现按照数据集中每个汉字出现的次数排序,id从1开始。
这里写图片描述
再建立一个tag2id词典,把每一个字标注的类型转换成id。这里的顺序我就随便搞的。
这里写图片描述

之后就把刚按标点分开的数据,按照一一对应的顺序,把汉字和每个字的标签转换成id,分别存到两个数组里面,一起保存到一个pkl文件中,这样模型使用时候就可以直接读取,不用每次都处理数据了。这里习惯把每一句话都转换成一样的长度。这个长度当然是自己设置的,比它长的就把后面舍弃,比它短的就在后面补零。
这里写图片描述
这里第一个数组里是这句话汉字转换成的id,第二个数组里存的是这句话每个字的标注转换成的id。

以上数据处理的代码是我的github里data_util.py实现的功能。

模型

这里模型就直接用的pytorch tutorial里的Bilstm+crf模型,也可以看BiLSTM_CRF.py这个文件。这个模型由于没有使用batch,速度比较慢,但是初学者就先用这个吧,学会了之后再进行修改。

至于想要看懂这部分的代码,就要学一下pytorch了,当然使用tensorflow也是可以的。推荐一下莫烦python的教程,pytorch和tensorflow都有。

pytorch里,lstm是写好的,可以直接使用,crf目前还没有,所以是直接写的。

lstm就是很经典的lstm,网上有很多讲解。crf我想另写一篇,详细讲一下。

训练

训练直接运行train.py就可以了。就是把之前存到pkl中的数据取出来,转换成tensor形式,输入到模型中。crf的损失函数是另外定义的。然后通过pytorch提供的

loss.backward()
optimizer.step()

反向传播和梯度下降,更新参数,让损失函数越来越小即可。看代码吧。

准确度判断

命名实体识别的准确度判断有三个值。准确率、召回率和f值。

这里需要先定义一个交集,是经过模型抽取出来的实体,与数据集中的所有实体,取交集。

准确率=交集/模型抽取出的实体
召回率=交集/数据集中的所有实体
f值=2×(准确率×召回率) / (准确率+召回率)

END

能讲的感觉也就这么多,主要是学一下pytorch或者tensorflow。

猜你喜欢

转载自blog.csdn.net/buppt/article/details/81180361