Python NLTK pos_tag 未返回正确的词性标记
- 2025-02-14 09:50:00
- admin 原创
- 44
问题描述:
有这个:
text = word_tokenize("The quick brown fox jumps over the lazy dog")
并运行:
nltk.pos_tag(text)
我得到:
[('The', 'DT'), ('quick', 'NN'), ('brown', 'NN'), ('fox', 'NN'), ('jumps', 'NNS'), ('over', 'IN'), ('the', 'DT'), ('lazy', 'NN'), ('dog', 'NN')]
quick brown lazy
这是不正确的。句子中的标签应该是:
('quick', 'JJ'), ('brown', 'JJ') , ('lazy', 'JJ')
通过他们的在线工具测试得出相同的结果;quick
,brown
和fox
应该是形容词而不是名词。
解决方案 1:
简而言之:
NLTK 并不完美。事实上,没有一个模型是完美的。
笔记:
从 NLTK 3.1 版开始,默认pos_tag
函数不再是旧的 MaxEnt English pickle。
它现在是来自@Honnibal 实现的感知器标记器,请参阅nltk.tag.pos_tag
>>> import inspect
>>> print inspect.getsource(pos_tag)
def pos_tag(tokens, tagset=None):
tagger = PerceptronTagger()
return _pos_tag(tokens, tagset, tagger)
它仍然更好但并不完美:
>>> from nltk import pos_tag
>>> pos_tag("The quick brown fox jumps over the lazy dog".split())
[('The', 'DT'), ('quick', 'JJ'), ('brown', 'NN'), ('fox', 'NN'), ('jumps', 'VBZ'), ('over', 'IN'), ('the', 'DT'), ('lazy', 'JJ'), ('dog', 'NN')]
在某些时候,如果有人想要TL;DR
解决方案,请参阅https://github.com/alvations/nltk_cli
长话短说:
尝试使用其他标记器(参见https://github.com/nltk/nltk/tree/develop/nltk/tag),例如:
亨普斯
斯坦福POS
塞纳
使用 NLTK 的默认 MaxEnt POS 标记器,即nltk.pos_tag
:
>>> from nltk import word_tokenize, pos_tag
>>> text = "The quick brown fox jumps over the lazy dog"
>>> pos_tag(word_tokenize(text))
[('The', 'DT'), ('quick', 'NN'), ('brown', 'NN'), ('fox', 'NN'), ('jumps', 'NNS'), ('over', 'IN'), ('the', 'DT'), ('lazy', 'NN'), ('dog', 'NN')]
使用斯坦福 POS 标记器:
$ cd ~
$ wget http://nlp.stanford.edu/software/stanford-postagger-2015-04-20.zip
$ unzip stanford-postagger-2015-04-20.zip
$ mv stanford-postagger-2015-04-20 stanford-postagger
$ python
>>> from os.path import expanduser
>>> home = expanduser("~")
>>> from nltk.tag.stanford import POSTagger
>>> _path_to_model = home + '/stanford-postagger/models/english-bidirectional-distsim.tagger'
>>> _path_to_jar = home + '/stanford-postagger/stanford-postagger.jar'
>>> st = POSTagger(path_to_model=_path_to_model, path_to_jar=_path_to_jar)
>>> text = "The quick brown fox jumps over the lazy dog"
>>> st.tag(text.split())
[(u'The', u'DT'), (u'quick', u'JJ'), (u'brown', u'JJ'), (u'fox', u'NN'), (u'jumps', u'VBZ'), (u'over', u'IN'), (u'the', u'DT'), (u'lazy', u'JJ'), (u'dog', u'NN')]
使用 HunPOS(注意:默认编码是 ISO-8859-1 而不是 UTF8):
$ cd ~
$ wget https://hunpos.googlecode.com/files/hunpos-1.0-linux.tgz
$ tar zxvf hunpos-1.0-linux.tgz
$ wget https://hunpos.googlecode.com/files/en_wsj.model.gz
$ gzip -d en_wsj.model.gz
$ mv en_wsj.model hunpos-1.0-linux/
$ python
>>> from os.path import expanduser
>>> home = expanduser("~")
>>> from nltk.tag.hunpos import HunposTagger
>>> _path_to_bin = home + '/hunpos-1.0-linux/hunpos-tag'
>>> _path_to_model = home + '/hunpos-1.0-linux/en_wsj.model'
>>> ht = HunposTagger(path_to_model=_path_to_model, path_to_bin=_path_to_bin)
>>> text = "The quick brown fox jumps over the lazy dog"
>>> ht.tag(text.split())
[('The', 'DT'), ('quick', 'JJ'), ('brown', 'JJ'), ('fox', 'NN'), ('jumps', 'NNS'), ('over', 'IN'), ('the', 'DT'), ('lazy', 'JJ'), ('dog', 'NN')]
使用 Senna(确保您拥有最新版本的 NLTK,API 有一些更改):
$ cd ~
$ wget http://ronan.collobert.com/senna/senna-v3.0.tgz
$ tar zxvf senna-v3.0.tgz
$ python
>>> from os.path import expanduser
>>> home = expanduser("~")
>>> from nltk.tag.senna import SennaTagger
>>> st = SennaTagger(home+'/senna')
>>> text = "The quick brown fox jumps over the lazy dog"
>>> st.tag(text.split())
[('The', u'DT'), ('quick', u'JJ'), ('brown', u'JJ'), ('fox', u'NN'), ('jumps', u'VBZ'), ('over', u'IN'), ('the', u'DT'), ('lazy', u'JJ'), ('dog', u'NN')]
或者尝试构建一个更好的 POS 标记器:
Ngram 标记器:http://streamhacker.com/2008/11/03/part-of-speech-tagging-with-nltk-part-1/
词缀/正则表达式标记器:http ://streamhacker.com/2008/11/10/part-of-speech-tagging-with-nltk-part-2/
构建您自己的 Brill(阅读代码,这是一个非常有趣的标记器,http://www.nltk.org/_modules/nltk/tag/brill.html),请参阅http://streamhacker.com/2008/12/03/part-of-speech-tagging-with-nltk-part-3/
LDA 标记器: http: //scm.io/blog/hack/2015/02/lda-intentions/
pos_tag
关于stackoverflow 上准确性的抱怨包括:
POS 标记 - NLTK 认为名词是形容词
python NLTK POS 标记器未按预期运行
如何使用 NLTK pos 标签获得更好的结果
NLTK 中的 pos_tag 无法正确标记句子
有关 NLTK HunPos 的问题包括:
如何在 nltk 中使用 hunpos 标记文本文件?
有人知道如何在 nltk 上配置 hunpos 包装器类吗?
NLTK 和斯坦福 POS 标记器的问题包括:
将 stanford pos tagger 导入 nltk 时遇到问题
Java 命令在 NLTK Stanford POS 标记器中失败
在 NLTK Python 中使用 Stanford POS Tagger 时出错
如何使用 Stanford NLP Tagger 和 NLTK 提高速度
Nltk stanford pos 标记器错误:Java 命令失败
在 NLTK 中实例化和使用 StanfordTagger
在 NLTK 中运行斯坦福 POS 标记器会导致 Windows 上出现“不是有效的 Win32 应用程序”
解决方案 2:
诸如更改为 Stanford 或 Senna 或 HunPOS 标记器之类的解决方案肯定会产生结果,但这里有一种更简单的方法来尝试 NLTK 中包含的不同标记器。
NTLK 中当前的默认 POS 标注器是平均感知器标注器。下面是一个将选择使用 Maxent Treebank 标注器的函数:
def treebankTag(text)
words = nltk.word_tokenize(text)
treebankTagger = nltk.data.load('taggers/maxent_treebank_pos_tagger/english.pickle')
return treebankTagger.tag(words)
我发现 NLTK 中的平均感知器预训练标记器倾向于将一些形容词视为名词,如您的示例所示。树库标记器为我正确识别了更多形容词。
解决方案 3:
def tagPOS(textcontent, taggedtextcontent, defined_tags):
# Write your code here
token = nltk.word_tokenize(textcontent)
nltk_pos_tags = nltk.pos_tag(token)
unigram_pos_tag = nltk.UnigramTagger(model=defined_tags).tag(token)
tagged_pos_tag = [ nltk.tag.str2tuple(word) for word in taggedtextcontent.split() ]
return (nltk_pos_tags,tagged_pos_tag,unigram_pos_tag)