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'

Если этого недостаточно, вы должны искать более гибкий реализация формализма.