自然语言处理——命名实体识别

article/2025/9/19 7:53:59

命名实体识别

命名实体识别(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. 贪心学院课程

http://chatgpt.dhexx.cn/article/IaQQUtA8.shtml

相关文章

NLP算法-命名实体识别

命名实体识别 什么是命名实体识别&#xff1f;NER 研究的命名实体NER研究目前所遇到的问题命名实体识别的主要方法&#xff1a; 基于条件随机场的命名实体识别常用的NER模型1、Spacy NER 模型2、斯坦福命名实体识别器 中文人名识别中文姓名的构成规律姓名的上下文环境分析Hanlp…

命名实体识别(NER)综述

本文是中文信息处理课程的期末考核大作业&#xff0c;对于自然语言处理主流任务的调研报告 ———————————————— 版权声明&#xff1a;本文为CSDN博主「<Running Snail>」的原创文章&#xff0c;遵循CC 4.0 BY-SA版权协议&#xff0c;转载请附上原文出处链接…

命名实体识别

转载https://blog.csdn.net/fendouaini/article/details/81137424 link 作者&#xff1a;Walker 目录 一&#xff0e;什么是命名实体识别 二&#xff0e;基于NLTK的命名实体识别 三&#xff0e;基于Stanford的NER 四&#xff0e;总结 一 、什么是命名实体识别&#xff1f; 命名…

NER入门:命名实体识别介绍及经验分享

每天给你送来NLP技术干货&#xff01; 来自&#xff1a;AI有温度 大家好&#xff0c;我是泰哥。本篇文章从什么是命名实体讲到为什么要做命名实体&#xff0c;然后讲到了NER数据处理及建模经验&#xff0c;对于做NER的同学&#xff0c;不论你是新手还是老手都非常值得一看&…

命名实体识别主要方法

命名实体识别主要方法 命名实体识别&#xff08;Named Entity Recognition&#xff0c;简称NER&#xff09;&#xff0c;又称作“专名识别”&#xff0c;是自然语言处理中的一项基础任务&#xff0c;应用范围非常广泛。命名实体一般指的是文本中具有特定意义或者指代性强的实体…

【实体识别】深入浅出讲解命名实体识别(介绍、常用算法)

本文收录于《深入浅出讲解自然语言处理》专栏&#xff0c;此专栏聚焦于自然语言处理领域的各大经典算法&#xff0c;将持续更新&#xff0c;欢迎大家订阅&#xff01;个人主页&#xff1a;有梦想的程序星空个人介绍&#xff1a;小编是人工智能领域硕士&#xff0c;全栈工程师&a…

命名实体识别(二)——基于条件随机场的命名实体识别

一、条件随机场 首先&#xff0c;我们看一下条件随机场的定义&#xff1a;在给定一组输入序列的条件下&#xff0c;另一组输出序列的条件概率分布模型。设X和Y是联合随机变量&#xff0c;若随机变量Y构成一个无向图G(V,E)表示的马尔科夫模型&#xff0c;则其条件概率分布P(Y|X…

正则表达式字符数字匹配

基础知识 数字&#xff1a;[0-9]或者[\d],不止一个就用 字母&#xff1a;[a-z]或者[A-Z]区分大小写 |&#xff1a;或的意思 工具 在线测试网站 拿不准的先可以测试一下&#xff0c;输入输出如下&#xff1a; 实战 改名字&#xff0c;其中注意正则式的小括号括起来的才可…

1.3 正则表达式【匹配数字】

数字匹配符 \d \d 可以配置 0到9的整数&#xff0c;等价于上一节 中的 [0-9] 。 测试实例 被匹配字符串 private static final String test1 "a12adf31d2tt"; 匹配公式1 匹配公式&#xff1a; String expression1 "\\d"; 匹配结果&#xff1a; 匹…

1.4 正则表达式【匹配非数字】

数字匹配符 \D \D 可以配置非数字&#xff0c;等价于上一节 中的 [^0-9] 。 测试实例 被匹配字符串 private static final String test1 "a12adf31d2tt"; 匹配公式3 匹配公式 String expression3 "\\D"; 匹配结果 匹配公式4 匹配公式 String exp…

1.6 正则表达式【匹配非字母和数字】

字母和数字匹配符 \W \W 可以配置 非字母和数字&#xff0c;等价于 [^a-zA-Z0-9] 。 测试实例 被匹配字符串 private static final String test1 "a12.a,df3.1d-2tt.*"; 匹配公式3 匹配公式 String expression3 "\\W"; 匹配结果 匹配公式4 匹配…

Python正则表达式匹配字符串中的数字

导读这篇文章主要介绍了Python正则表达式匹配字符串中的数字&#xff0c;本文通过实例代码给大家介绍的非常详细&#xff0c;具有一定的参考借鉴价值,需要的朋友可以参考下 1.使用“\d”匹配全数字 代码&#xff1a; import re zen "Arizona 479, 501, 870. Carliforn…

正则表达式匹配数字、字母和汉字等各类汇总

最近在开发中遇到一个需求是只匹配字母和汉字&#xff0c;于是在网上找了一个比较全的记录一下。日后再用~ 正则表达式来匹配规范一段文本中的特定种类字符&#xff0c;下面是对常用的正则匹配做了一个归纳整理。 1、匹配中文:[\u4e00-\u9fa5] 2、英文字母:[a-zA-Z] 3、数字…

类加载机制、类加载顺序

1 类加载顺序 Java 的类加载过程可以分为 5 个阶段&#xff1a;载入、验证、准备、解析和初始化。这 5 个阶段一般是顺序发生的&#xff0c;但在动态绑定的情况下&#xff0c;解析阶段发生在初始化阶段之后。 1&#xff09;Loading&#xff08;载入&#xff09; JVM 在该阶段…

深入理解——Java类加载机制

我们知道&#xff0c;我们写的java文件是不能直接运行的&#xff0c;我们可以在IDEA中右键文件名点击运行&#xff0c;这中间其实掺杂了一系列的复杂处理过程。这篇文章&#xff0c;我们只讨论我们的代码在运行之前的一个环节&#xff0c;叫做类的加载。按照我写文章的常规惯例…

理解类加载机制

一般来说&#xff0c;我们日常的开发都是在IDE上进行的&#xff0c;这能让我们将更多的注意力放在业务的处理上&#xff0c;但是久而久之我们就忘记了其底层的实现原理。这是一把双刃剑&#xff0c;我们看不到底层实现&#xff0c;但是当有某些问题出现的时候&#xff0c;也只有…

谈谈类加载机制

前言 类的加载其实就是将.class文件加载的jvm的内存之中。在JVM中并不是一次性把所有的文件都加载到&#xff0c;而是一步一步的&#xff0c;按照需要来加载。JVM启动时会通过不同的类加载器加载不同的类&#xff0c;而且同一个类也不可能由多个加载器来进行加载。正是这种分级…

【JVM】详解类加载机制

JVM的类加载机制 一、类的生命周期二、类加载的过程1.加载2.连接3.初始化 三、类加载器的介绍3.1 启动类加载器&#xff08;根类加载器/引导类加载器&#xff09;&#xff08;Bootstrap ClassLoader&#xff09;3.2 扩展类加载器3.3 系统类加载器 四、双亲委派模型4.1 双亲委派…

tomcat类加载机制

目录 一、JVM类加载机制简介 二、TOMCAT类加载机制 三、违反双亲委托机制 一、JVM类加载机制简介 简述JVM双亲委派模型&#xff1a; JVM中包括集中类加载器&#xff1a; BootStrapClassLoader 引导类加载器ExtClassLoader 扩展类加载器AppClassLoader 应用类加载器Custom…

JAVA类加载机制详解

上一篇文章我们简单说了一下类的创建过程&#xff0c;但是如果JVM需要加载类&#xff0c;会经过哪些具体的过程呢&#xff1f;下面我们就来谈一谈。 要了解加载类的过程&#xff0c;我们就必须要了解类加载器。 在很多初学者刚听到类加载器的时候觉得很高大上&#xff0c;其实…