Python使用NLTK实现命名实体识别时实体误判漏判问题咨询
问题产生原因
- NLTK自带的
ne_chunk实体识别模块是基于传统统计模型在规范书面新闻语料上训练的,本身对口语化文本、大小写不规范文本的适配性极差,识别准确率本就不适合直接用在生产场景。 - 测试文本存在不符合英文书写规范的乱大写问题:正常英文书写中仅句首词、专有名词需要首字母大写,第一个测试句里句中的代词
We被错误大写,会直接干扰词性标注结果——NLTK的词性标注器会优先将首字母大写的词判定为专有名词(NNP),再加上口语化的问候语序不在模型训练的语料分布内,直接把句首的问候语Hey错判为人名实体,后续相邻的Marsh因为挨着错误大写的We,实体边界被打乱,就出现了漏判。 - 第二个测试句里的人名
Jana出现在句尾、前面直接接第二人称代词you,属于非常口语化的表达句式,在NLTK训练用的规范新闻语料里极少出现,模型没有足够的特征判定其为人名,因此产生漏识别。 - 最初设想的「靠NNP词性标签判定目标实体」的思路本身存在缺陷:NNP标签会覆盖所有首字母大写的词,包含大量普通大写词、句首普通词,根本无法区分需要的姓名、职位、地理、行业类实体,天生误判率极高。
可行修复方案
- 先做文本规范化预处理
在分词、词性标注、实体识别之前,先对输入文本做大小写还原,把句中乱大写的普通词(比如第一个测试句里的We)转为正确的小写形式,仅保留句首词、真实专有名词的首字母大写,从源头降低词性标注的误判。可以用TrueCase工具实现自动大小写还原,修正后的基础代码示例:
from nltk.tag import pos_tag from nltk.tokenize import word_tokenize, sent_tokenize from nltk.chunk import ne_chunk from truecase import get_true_case def pers(sentence): # 先做大小写规范化 norm_sentence = get_true_case(sentence) for sent in sent_tokenize(norm_sentence): for chunk in ne_chunk(pos_tag(word_tokenize(sent))): if hasattr(chunk, 'label'): # 按需过滤只保留需要的实体类型 if chunk.label() in ["PERSON", "GPE", "POSITION", "ORGANIZATION"]: print(chunk.label(), ' '.join(c[0] for c in chunk))
- 替换精度更高的实体识别模型
NLTK自带的NER模型仅适合教学演示,实际使用建议替换为spaCy的Transformer版本英文预训练模型,对口语化文本、非常规位置的实体识别准确率远高于NLTK原生模型,且原生支持人名、地理实体、职位、机构、行业类实体的标签输出,不需要依赖NNP词性标签做二次判断。简单实现示例:
import spacy # 加载英文预训练Transformer模型 nlp = spacy.load("en_core_web_trf") def pers(sentence): doc = nlp(sentence) for ent in doc.ents: # 过滤需要的实体类别 if ent.label_ in ["PERSON", "GPE", "LOC", "JOB_TITLE", "ORG", "INDUSTRY"]: print(ent.label_, ent.text)
- 增加规则层兜底
如果暂时不想替换现有NLTK方案,可以在识别结果后增加规则校验:把Hey、Hi、Hello这类常见句首问候语加入黑名单,识别为PERSON且命中黑名单的结果直接剔除;另外补充人名词典匹配规则,针对句中首字母大写、符合常见人名特征但未被模型识别的词做补判,降低漏判率。
内容的提问来源于stack exchange,提问作者user18148705
相关产品推荐
相关产品推荐

