Подтвердить что ты не робот

Как использовать NLTK для генерации предложений из индуцированной грамматики?

У меня есть (большой) список проанализированных предложений (которые были проанализированы с использованием парсер Stanford), например, предложение "Теперь вы можете развлекаться" имеет следующее дерево:

(ROOT
  (S
    (ADVP (RB Now))
    (, ,)
    (NP (PRP you))
    (VP (MD can)
      (VP (VB be)
        (VP (VBN entertained))))
    (. .)))

Я использую набор деревьев предложений для индукции грамматики с использованием nltk:

import nltk

# ... for each sentence tree t, add its production to allProductions
allProductions += t.productions()

# Induce the grammar
S = nltk.Nonterminal('S')
grammar = nltk.induce_pcfg(S, allProductions)

Теперь я хотел бы использовать grammar для генерации новых случайных предложений. Я надеюсь, что, поскольку грамматика была получена из определенного набора примеров ввода, то сгенерированные предложения будут семантически подобными. Могу ли я сделать это в nltk?

Если я не могу использовать nltk для этого, существуют ли какие-либо другие инструменты, которые могут принимать (возможно, отформатированные) grammar и генерировать предложения?

4b9b3361

Ответ 1

В NLTK 2.0 вы можете использовать nltk.parse.generate для генерации всех возможных предложений для данной грамматики.

Этот код определяет функцию, которая должна генерировать одно предложение, основанное на правилах производства в (P) CFG.

# This example uses choice to choose from possible expansions
from random import choice
# This function is based on _generate_all() in nltk.parse.generate
# It therefore assumes the same import environment otherwise.
def generate_sample(grammar, items=["S"]):
    frags = []
    if len(items) == 1:
        if isinstance(items[0], Nonterminal):
            for prod in grammar.productions(lhs=items[0]):
                frags.append(generate_sample(grammar, prod.rhs()))
        else:
            frags.append(items[0])
    else:
        # This is where we need to make our changes
        chosen_expansion = choice(items)
        frags.append(generate_sample,chosen_expansion)
    return frags

Чтобы использовать весы в вашем PCFG, вы, очевидно, захотите использовать лучший метод выборки, чем choice(), который подразумевает, что все расширения текущего node равновероятны.

Ответ 2

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

(Мне звучит немного похоже на то, что студенты MIT сделали со своей программой SCIgen, которая автоматически генерирует научную статью. Очень интересно кстати. )

В любом случае, я никогда не делал этого сам, но, возможно, с nltk.bigrams, вы можете посмотреть там в разделе Создание случайного текста с помощью Bigrams.

Вы также можете сгенерировать все поддеревья текущего дерева, я не уверен, что это то, что вы хотите.

Ответ 3

С объектом nltk Text вы можете вызвать 'generate()' на нем, который будет "Печатать случайный текст, сгенерированный с помощью триграммы языковой модели." http://nltk.org/_modules/nltk/text.html

Ответ 4

Мое решение создать случайное предложение из существующей грамматики nltk.CFG:

def generate_sample(grammar, prod, frags):        
    if prod in grammar._lhs_index: # Derivation
        derivations = grammar._lhs_index[prod]            
        derivation = random.choice(derivations)            
        for d in derivation._rhs:            
            generate_sample(grammar, d, frags)
    elif prod in grammar._rhs_index:
        # terminal
        frags.append(str(prod))

И теперь его можно использовать:

frags = []  
generate_sample(grammar, grammar.start(), frags)
print( ' '.join(frags) )