Nltk контекстная Свободная грамматика
Я работаю над неанглийским синтаксическим анализатором с символами Юникода. Для этого я решил использовать NLTK.
но для этого требуется предопределенная контекстно-свободная грамматика, как показано ниже:
S -> NP VP
VP -> V NP | V NP PP
PP -> P NP
V -> "saw" | "ate" | "walked"
NP -> "John" | "Mary" | "Bob" | Det N | Det N PP
Det -> "a" | "an" | "the" | "my"
N -> "man" | "dog" | "cat" | "telescope" | "park"
P -> "in" | "on" | "by" | "with"
в моем приложении я должен минимизировать жесткое кодирование с использованием грамматики на основе правил. Например, я могу предположить любое слово, заканчивающееся на - ed или - ing как глагол. Поэтому он должен работать для любого контекста.
Как я могу кормить такие правила грамматики В nltk? Или генерировать их динамически, используя конечную машину?
4 ответов
может быть, вы ищете CFG.fromstring()
(ранее parse_cfg()
)?
С Глава 7 из книги NLTK (обновлено до nltk 3.0):
> grammar = nltk.CFG.fromstring("""
S -> NP VP
VP -> V NP | V NP PP
V -> "saw" | "ate"
NP -> "John" | "Mary" | "Bob" | Det N | Det N PP
Det -> "a" | "an" | "the" | "my"
N -> "dog" | "cat" | "cookie" | "park"
PP -> P NP
P -> "in" | "on" | "by" | "with"
""")
> sent = "Mary saw Bob".split()
> rd_parser = nltk.RecursiveDescentParser(grammar)
> for p in rd_parser.parse(sent):
print p
(S (NP Mary) (VP (V saw) (NP Bob)))
Если вы создаете парсер, то вы есть чтобы добавить шаг pos-тегов перед фактическим разбором - нет способа успешно определить POS-тег слова из контекста. Например, "закрыто" может быть прилагательным или глаголом; POS-tagger узнает правильный тег для вас из контекста слова. Затем вы можете использовать вывод POS-tagger для создания CFG.
вы можете использовать один из многих существующих POS-тегов. В NLTK вы можете просто сделайте что-нибудь вроде:
import nltk
input_sentence = "Dogs chase cats"
text = nltk.word_tokenize(input_sentence)
list_of_tokens = nltk.pos_tag(text)
print list_of_tokens
выход будет:
[('Dogs', 'NN'), ('chase', 'VB'), ('cats', 'NN')]
который вы можете использовать для создания строки грамматики и подачи ее в nltk.parse_cfg()
.
вы можете использовать NLTK RegexTagger которые имеют возможность регулярного выражения токена decide. Это именно то, что вам нужно в вашем случае. Как токен, заканчивающийся на 'ing', будет помечен как gerunds, а токен, заканчивающийся на' ed', будет помечен глаголом past. см. пример ниже.
patterns = [
(r'.*ing$', 'VBG'), # gerunds
(r'.*ed$', 'VBD'), # simple past
(r'.*es$', 'VBZ'), # 3rd singular present
(r'.*ould$', 'MD'), # modals
(r'.*\'s$', 'NN$'), # possessive nouns
(r'.*s$', 'NNS') # plural nouns
]
обратите внимание, что они обрабатываются по порядку, и применяется первый, который соответствует. Сейчас мы можем настроить tagger и использовать его для пометки предложения. После этого шага, правильно о ля в пятый раз.
regexp_tagger = nltk.RegexpTagger(patterns)
regexp_tagger.tag(your_sent)
можно использовать Объединение Райтеров для коллективного использования нескольких тегов в последовательности.
вы не можете написать такие правила в нлтк прямо сейчас без каких-либо усилий, но вы можете сделать некоторые трюки.
например, записать фразу в каком-то слове-информационных этикеток и писать соответственно правилам грамматики.
например (используя тег POS в качестве метки):
Dogs eat bones.
будет:
NN V NN.
и пример правил грамматики терминала:
V -> 'V'
Если этого недостаточно, вы должны искать более гибкий реализация формализма.