自己也是一个初学者,主要是总结一下最近的学习,大佬见笑。
说到命名实体抽取,先要了解一下基于字标注的中文分词。
比如一句话
"我爱北京天安门”。
分词的结果可以是
“我/爱/北京/天安门”。
那什么是基于字标注呢?
“我/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里有两个版本,pytorch版直接用的pytorch tutorial里的Bilstm+crf模型。
运行train.py训练即可。由于使用的是cpu,而且也没有使用batch,所以训练速度比较慢。想简单跑一下代码的话,建议只使用部分数据跑一下。pytorch暂时不再更新。
tensorflow版使用 python train.py
开始训练,训练的模型会存到model文件夹中。
使用 python train.py pretrained
会使用预训练的词向量开始训练,vec.txt是在网上找的一个比较小的预训练词向量,可以参照我的代码修改使用其他更好的预训练词向量。
使用 python train.py test
进行测试,会自动读取model文件夹中最新的模型,输入中文测试即可,测试结果当然根据模型的准确度而定。
命名实体识别的准确度判断有三个值。准确率、召回率和f值。
这里需要先定义一个交集,是经过模型抽取出来的实体,与数据集中的所有实体,取交集。
准确率=交集/模型抽取出的实体
召回率=交集/数据集中的所有实体
f值=2×(准确率×召回率) / (准确率+召回率)
能讲的感觉也就这么多,主要是学一下pytorch或者tensorflow。