【问题标题】:Python NLTK pos_tag not returning the correct part-of-speech tagPython NLTK pos_tag 未返回正确的词性标记
【发布时间】:2015-08-29 12:47:47
【问题描述】:

有这个:

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')

通过他们的online tool 进行测试会得到相同的结果; quickbrownfox 应该是形容词而不是名词。

【问题讨论】:

  • 使用他们的例句“约翰的大创意并没有那么糟糕。”位于此处:nltk.org/api/nltk.tag.html 我发现它做得很好并找到了形容词,这是为什么呢?您建议在哪里寻找其他标记器?
  • 这些是明确的词,应该被正确标记。尝试使用其他标记器以获得更好的结果。
  • @faceoff 我不知道这个任务的任何标记器,但我只是建议在 Doc 中寻找一个!
  • 您可以在 NLTK 中使用 HMM 标记器。我有一个 HMM 标记器的自我实现,它正确地预测了你的例句的标记。我想它也应该对你有用。

标签: python machine-learning nlp nltk pos-tagger


【解决方案1】:

简而言之

NLTK 并不完美。事实上,没有完美的模型。

注意:

从 NLTK 3.1 版开始,默认的 pos_tag 函数不再是 old MaxEnt English pickle

现在是来自@Honnibal's implementation感知器标记器,参见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),例如

  • HunPos
  • 斯坦福 POS
  • 塞纳

使用来自 NLTK 的默认 MaxEnt 词性标注器,即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')]

使用斯坦福词性标注器

$ 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_tag 在 stackoverflow 上的准确性包括

关于 NLTK HunPos 的问题包括

NLTK 和斯坦福词性标注器的问题包括

【讨论】:

  • 是的,没有模型是完美的,但这个例子非常令人失望。考虑到这个“推荐”标记器中包含的所有技术,期待更多并非没有道理。
  • 不错的替代方案演示。
  • 模型更新已经 3 年了,可能我们应该将它提升到 nltk-dev google group: github.com/arne-cl/nltk-maxent-pos-tagger。而且模型是7年前创建的=(github.com/nltk/nltk/blob/develop/nltk/tag/__init__.py#L84
  • 是的,stanford 和 senna 标记器更复杂,两个团队都投入了大量精力来构建工具。
  • @alvas 感谢您的精彩回答!它在 2017 年仍然(可悲)非常相关,因为我在过去几个月一直在与 NLTK 合作
【解决方案2】:

更改为 Stanford、Senna 或 HunPOS 标记器等解决方案肯定会产生结果,但这里有一个更简单的方法来试验也包含在 NLTK 中的不同标记器。

目前 NTLK 中的默认词性标注器是平均感知器标注器。这是一个选择使用 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)

【讨论】:

    猜你喜欢
    • 2012-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-22
    • 1970-01-01
    相关资源
    最近更新 更多