POS маркировка - NLTK считает существительное прилагательным

В следующем коде почему nltk считает "рыба" прилагательным, а не существительным?

>>> import nltk
>>> s = "a woman needs a man like a fish needs a bicycle"
>>> nltk.pos_tag(s.split())
[('a', 'DT'), ('woman', 'NN'), ('needs', 'VBZ'), ('a', 'DT'), ('man', 'NN'), ('like', 'IN'), ('a', 'DT'), ('fish', 'JJ'), ('needs', 'NNS'), ('a', 'DT'), ('bicycle', 'NN')]

5 ответов

Я не уверен, что такое обходной путь, но вы можете проверить источник здесь https://nltk.googlecode.com/svn/trunk/nltk/nltk/tag/

Тем временем я попробовал ваше предложение с немного другим подходом.

>>> s = "a woman needs a man. A fish needs a bicycle"
>>> nltk.pos_tag(s.split())
[('a', 'DT'), ('woman', 'NN'), ('needs', 'VBZ'), ('a', 'DT'), ('man.', NP'), ('A','NNP'),   ('fish', 'NN'), ('needs', 'VBZ'), ('a', 'DT'), ('bicycle', 'NN')]

что привело к рыбе как "NN".

Если бы вы сначала использовали Lookup Tagger, как описано в книге NLTK, глава 5 (например, используя WordNet в качестве справочной информации), ваш tagger уже "знал", что fish не может быть прилагательным. Для всех слов с несколькими возможными тегами POS вы можете использовать статистический тег в качестве тега возврата.

Это потому что ты хочешь a woman needs a man like a fish needs a bicycle получить POS-теги для такого "разбора":

[ [[a woman] needs [a man]] like [[a fish] needs [a bicycle]] ]

но вместо этого pos-тегер по умолчанию NLTK недостаточно умен и дал вам POS-тег для такого анализа:

[ [[a woman] needs [a man]] like [a fish needs] [a bicycle] ]

Это зависит от того, как вводится тег POS. Например, для предложения: "женщине нужен мужчина, как рыбе нужен велосипед"

Если вы используете токенайзер nltk word по умолчанию и токенайзер регулярных выражений, значения будут другими.

import nltk 
from nltk.tokenize import RegexpTokenizer

TOKENIZER = RegexpTokenizer('(?u)\W+|\$[\d\.]+|\S+')

s = "a woman needs a man like a fish needs a bicycle"

regex_tokenize = TOKENIZER.tokenize(s)
default_tokenize = nltk.word_tokenize(s)

regex_tag = nltk.pos_tag(regex_tokenize)
default_tag = nltk.pos_tag(default_tokenize)

print regex_tag
print "\n"
print default_tag

Вывод следующий:

  Regex Tokenizer: 

[('a', 'DT'), (' ', 'NN'), ('woman', 'NN'), (' ', ':'), ('needs', 'NNS'), (' ', 'VBP'), ('a', 'DT'), (' ', 'NN'), ('man', 'NN'), (' ', ':'), ('like', 'IN'), (' ', 'NN'), ('a', 'DT'), (' ', 'NN'), ('fish', 'NN'), (' ', ':'), ('needs', 'VBZ'), (' ', ':'), ('a', 'DT'), (' ', 'NN'), ('bicycle', 'NN')]

 Default Tokenizer: 

[('a', 'DT'), ('woman', 'NN'), ('needs', 'VBZ'), ('a', 'DT'), ('man', 'NN'), ('like', 'IN'), ('a', 'DT'), ('fish', 'JJ'), ('needs', 'NNS'), ('a', 'DT'), ('bicycle', 'NN')]

В Regex Tokenizer fish - это существительное, тогда как в стандартном tokenizer fish - это прилагательное. В зависимости от используемого токенизатора разбор отличается, что приводит к разной структуре дерева разбора.

Если вы используете Stanford POS tagger (3.5.1), фраза будет помечена правильно:

from nltk.tag.stanford import POSTagger
st = POSTagger("/.../stanford-postagger-full-2015-01-30/models/english-left3words-distsim.tagger",
               "/.../stanford-postagger-full-2015-01-30/stanford-postagger.jar")
st.tag("a woman needs a man like a fish needs a bicycle".split())

выходы:

[('a', 'DT'),
 ('woman', 'NN'),
 ('needs', 'VBZ'),
 ('a', 'DT'),
 ('man', 'NN'),
 ('like', 'IN'),
 ('a', 'DT'),
 ('fish', 'NN'),
 ('needs', 'VBZ'),
 ('a', 'DT'),
 ('bicycle', 'NN')]
Другие вопросы по тегам