命名实体识别

命名实体识别(Named Entity Recognition,NER),指识别文本中具有特定意义的实体,包括人名、地名、机构名、专有名词等。

常用的方法如下。

数据集一览

数据集下载地址 提取码:s249

看一下我们的数据集,分为句子、单词、词性和标签。 在标签里面我们不关注的单词被标记为"O",而关注的是非"O",有

  • geo 地点
  • per 人名
  • org 组织

详情请参考spacy中关于标签的定义

其中开头的"B"开始 某个实体的开始,"I"表示某个实体的剩下部分。
比如 B-geo 地点的开头,I-geo 地点的中间或结尾。

上图"Hyde Park"两个单词可以看成是一个专有名词,都表示地点。

词性的话这里就不展开了。

import pandas as pd
import numpy as np
data = pd.read_csv("./data/ner_dataset.csv", encoding="latin1")data = data.fillna(method="ffill") # 向下填充,以none上面的非none元素填充
data.tail(10)

words = list(set(data["Word"].values))
n_words = len(words)
print(n_words) #35178

总共有3万多个单词。

基于规则的方法

基于规则的方法想法简单,但实现起来比较繁琐。需要考虑的比较全面。

比如定义正则表达式来识别电话、邮箱、身份证号码等。 或者利用已定义的词典来匹配。

基于投票的方法

统计每个单词的实体类型,记录针对每个单词概率最大的实体类型。下次碰到这个单词,就认为是这个实体类型。

由于实现起来简单,不需要学习,准确率还可以,应该通常用作基准。

from sklearn.base import BaseEstimator, TransformerMixinclass MajorityVoting(BaseEstimator, TransformerMixin):def fit(self, X, y):"""X: 单词列表y: 单词对应的标签列表"""word2cnt = {}self.tags = []self.mjvote = {}for x, t in zip(X, y):if t not in self.tags:self.tags.append(t)if x in word2cnt:if t in word2cnt[x]:word2cnt[x][t] += 1else:word2cnt[x][t] = 1else:word2cnt[x] = {t: 1}for k, d in word2cnt.items():self.mjvote[k] = max(d, key=d.get)def predict(self, X, y=None):'''通过内存中缓存的多数投票结果预测单词的标签,未知单词预测为'O''''return [self.mjvote.get(x, 'O') for x in X]words = data["Word"].values.tolist()
tags = data["Tag"].values.tolist()from sklearn.model_selection import cross_val_predict
from sklearn.metrics import classification_reportmodel = MajorityVoting()pred = cross_val_predict(estimator=model, X=words, y=tags, cv=5)
report = classification_report(y_pred=pred, y_true=tags)print(report)


这种方法也能达到94%的一个准确率。

利用分类模型

要想利用分类模型,我们需要一些特征。这里就需要用到特征工程来提取单词的特征。

特征工程

提取每个单词的最简单的特征,比如单词长度。

以语句“The professor Colin proposed a(停止词) model for NER in 1999”为例,假设我们考虑单词“Colin”

特征词袋模型

  • 当前词: Colin
  • 前后词:professor,proposed
  • 前前,后后词:the,model
  • Bi-gram: professor Colin,Colin proposed,The professor,proposed model
  • Tri-gram:…

词性特征

  • 当前词:名词
  • 前后词:名,动
  • 前前,后后词:冠词,名词
  • n-gram:…

前缀&后缀

  • 当前词:Co,in
  • 前后词:pr,or,pr,ed
  • 前前,后后词:…

当前词的特性

  • 词长
  • 含有多个大写字母
  • 是否大写开头(Title)
  • 是否包含特殊符号(“-”)?
  • 是否包含数字

词干特征

做完特征工程之后,就可以得到特征向量,然后就可以喂给分类模型进行分类。

首先我们用一些比较简单的特征,并用随机森林模型来进行分类。

from sklearn.ensemble import RandomForestClassifier
def get_feature(word):# 返回一些简单的特征 是否为标题(首字母大写,其他字母小写),是否全小写,是否全大写,单词长度,是否为数字,是否为字母return np.array([word.istitle(), word.islower(), word.isupper(), len(word),word.isdigit(),  word.isalpha()])words = [get_feature(w) for w in data["Word"].values.tolist()]
tags = data["Tag"].values.tolist()from sklearn.model_selection import cross_val_predict
from sklearn.metrics import classification_report
pred = cross_val_predict(RandomForestClassifier(n_estimators=20), X=words, y=tags, cv=5)
report = classification_report(y_pred=pred, y_true=tags)
print(report)


这里只是进行了简单的特征提取,只考虑了标题、小写、大写、数字等,可以看到结果还没有基准好。说明我们的特征提取的不够,下面我们进行更详细的特征提取。

from sklearn.preprocessing import LabelEncoderdef get_sentences(data):agg_func = lambda s: [(w, p, t) for w, p, t in zip(s["Word"].values.tolist(),s["POS"].values.tolist(),s["Tag"].values.tolist())]sentence_grouped = data.groupby("Sentence #").apply(agg_func)return [s for s in sentence_grouped] # 转换成句子
sentences = get_sentences(data)out = []
y = []
mv_tagger = MajorityVoting()
# LabelEncoder将标签转换为数值(索引)
tag_encoder = LabelEncoder()
pos_encoder = LabelEncoder()words = data["Word"].values.tolist()
pos = data["POS"].values.tolist()
tags = data["Tag"].values.tolist()mv_tagger.fit(words, tags)
tag_encoder.fit(tags)
pos_encoder.fit(pos)it = 0for sentence in sentences:for i in range(len(sentence)):w, p, t = sentence[i][0], sentence[i][1], sentence[i][2]if i < len(sentence)-1:# 如果不是最后一个单词,则可以用到下文的信息mem_tag_r = tag_encoder.transform(mv_tagger.predict([sentence[i+1][0]]))[0] #预测的标签true_pos_r = pos_encoder.transform([sentence[i+1][1]])[0] #实际的词性else:mem_tag_r = tag_encoder.transform(['O'])[0]true_pos_r =  pos_encoder.transform(['.'])[0]if i > 0: # 如果不是第一个单词,则可以用到上文的信息mem_tag_l = tag_encoder.transform(mv_tagger.predict([sentence[i-1][0]]))[0]true_pos_l = pos_encoder.transform([sentence[i-1][1]])[0]else:mem_tag_l = tag_encoder.transform(['O'])[0]true_pos_l =  pos_encoder.transform(['.'])[0]#print (mem_tag_r, true_pos_r, mem_tag_l, true_pos_l)out.append(np.array([w.istitle(), w.islower(), w.isupper(), len(w), w.isdigit(), w.isalpha(),tag_encoder.transform(mv_tagger.predict([sentence[i][0]])),pos_encoder.transform([p])[0], mem_tag_r, true_pos_r, mem_tag_l, true_pos_l]))y.append(t)it = it + 1if it % 1000 == 0 :print(it) #打印进行到哪了

这里不仅考虑到了每个单词的词性、标签,还考虑了上下文(左右单词)的信息。

LabelEncoder的用法见

然后输出测试结果。

from sklearn.model_selection import cross_val_predict
from sklearn.metrics import classification_report
pred = cross_val_predict(RandomForestClassifier(n_estimators=20), X=out, y=y, cv=5)
report = classification_report(y_pred=pred, y_true=y)
print(report)

如结果所示,现在准确率是97%,比基准好了3%。这是我们考虑了前后单词的结果,如果考虑前前、后后会不会更好呢,感兴趣的可以自己尝试一下。

以上就是命名实体识别的简单介绍,后面会推出更多内容。

参考

  1. 贪心学院课程

自然语言处理——命名实体识别相关推荐

  1. 基于spaCy的领域命名实体识别

    基于spaCy的命名实体识别 ----以"大屠杀"领域命名实体识别研究为例 作者: Dr. W.J.B. Mattingly Postdoctoral Fellow at the ...

  2. 自然语言处理NLP之分词、词性标注(POS)、组块分析(Chunking)、命名实体识别(Named Entity Recognition,简称NER)

    自然语言处理NLP之分词.词性标注(POS).组块分析(Chunking).命名实体识别(Named Entity Recognition,简称NER) 目录

  3. 自然语言处理(二)——词性标注与命名实体识别

    文章目录 一.Jieba 二.NLPIR 三.nltk 四.SnowNLP 五.StandFordNLP 六.thulac 七.StandfordNLP 八.结论 本次依然使用上篇博客( 自然语言处理 ...

  4. 自然语言处理(NLP)之命名实体识别

    本文将会简单介绍自然语言处理(NLP)中的命名实体识别(NER). 命名实体识别(Named Entity Recognition,简称NER)是信息提取.问答系统.句法分析.机器翻译等应用领域的重要 ...

  5. 自然语言处理 文本预处理(上)(分词、词性标注、命名实体识别等)

    文章目录 一.认识文本预处理 1 文本预处理及其作用 2. 文本预处理中包含的主要环节 3. 概览 二.文本处理的基本方法 1. 分词 1.1 什么是分词 1.2 分词的作用 1.3 流行中文分词工具 ...

  6. 「自然语言处理(NLP)论文解读」中文命名实体识别(Lattice-LSTM模型优化)

    来源:AINLPer微信公众号 编辑: ShuYini 校稿: ShuYini 时间: 2019-8-27 引言     今天主要和大家分享一篇关于中文命名实体识别的文章,本文分析Lattice-LS ...

  7. 自然语言处理之——词性标注和命名实体识别

    1. 摘要 基于上次分享的分词技术介绍,本次继续分享在分词后与词相关联的两个技术:词性标注和命名实体识别.词性是词汇基本的语法属性,也可以称为词类.词性标注的行为就是在给定的中文句子中判定每个词的语法 ...

  8. 自然语言处理(NLP)之pyltp的介绍与使用(中文分词、词性标注、命名实体识别、依存句法分析、语义角色标注)

    pyltp的简介   语言技术平台(LTP)经过哈工大社会计算与信息检索研究中心 11 年的持续研发和推广, 是国内外最具影响力的中文处理基础平台.它提供的功能包括中文分词.词性标注.命名实体识别.依 ...

  9. 自然语言处理学习8:python使用standford CoreNLP进行中文分词、标注和命名实体识别

    jieba分词可以进行中文分词和标注,但是无法进行命名实体识别. 1. 环境配置 (1) 下载安装JDK 1.8及以上版本 (2)下载Stanford CoreNLP文件,解压. (3)处理中文还需要 ...

最新文章

  1. shell-变量的数值计算
  2. c语言gets多组测试,C语言如何实现输入多组数据测试
  3. input框输入完回车即可查询事件
  4. html表白_HTML 表白网页
  5. c语言结果九位数,C语言实例:九位累进可除数
  6. php 结构体_【开发规范】PHP编码开发规范下篇:PSR-2编码风格规范
  7. 修改打印机ip工具_使用富士施乐一体机因动态IP导致不能打印与扫描的解决方法...
  8. html5 打包ios.上架,iOS帮客户打包App上架的正确姿势
  9. 李楠评华为Mate X/小米MIX Alpha:适合土豪做非主力手机用
  10. 多线程中使用信号机制 pthread_sigmask()
  11. 3.3 垃圾回收算法
  12. 如何在eclipse中配置反编译工具JadClipse
  13. apktool + dex2jar + xjad反编译apk文件
  14. 判断视频中是否存在移动物体
  15. bean named 'transactionManager' available: No matching PlatformTransactionManager bean found for qua
  16. 自燃、断轴、失控,新能源车还能买吗?
  17. 多目标优化算法:多目标非洲秃鹫优化算法MOAVOA(提供Matlab代码)
  18. 迪杰斯特拉算法和弗洛伊德算法
  19. 高考选地理化学生物能考计算机专业吗,高考选科物理化学地理可以报考什么专业...
  20. 上传项目到github报错:Permission to xxx/xxx.git denied to xxxxxxx.

热门文章

  1. 高压放大器在铁电材料中的应用研究
  2. 补单平台源码发布,支持演示
  3. mysql数据库sysdate_mysql now() sysdate() 区别
  4. 莘松路隧道几百米的路程要走一个多小时!
  5. 同城跑腿app开发需要具备哪些功能?
  6. 阿里云服务器安全组如何配置?
  7. Ubuntu上安装运行 rotated_maskrcnn
  8. 爬虫项目——B站石原里美视频数据爬取
  9. opencv-图像上显示中文
  10. 理财通app的设计与实现(一)