Python 如何使用NLTK从归纳语法生成句子?
我有一个(大的)已解析句子列表(使用斯坦福解析器解析),例如,“现在你可以娱乐”一句有以下树:Python 如何使用NLTK从归纳语法生成句子?,python,nlp,nltk,Python,Nlp,Nltk,我有一个(大的)已解析句子列表(使用斯坦福解析器解析),例如,“现在你可以娱乐”一句有以下树: (ROOT (S (ADVP (RB Now)) (, ,) (NP (PRP you)) (VP (MD can) (VP (VB be) (VP (VBN entertained)))) (. .))) 我正在使用一组句子树来归纳使用nltk的语法: import nltk # ... for each sentence
(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)
现在我想使用语法生成新的随机句子。我的希望是,由于语法是从一组特定的输入示例中学习的,因此生成的句子在语义上是相似的。我能用nltk做这个吗
如果我不能使用nltk来实现这一点,那么有没有其他工具可以使用(可能重新格式化的)语法生成句子?首先,如果生成随机句子,它们可能在语义上是正确的,但可能会失去意义
(对我来说,这听起来有点像麻省理工学院的学生用自动生成科学论文的方法所做的。顺便说一句,非常有趣。)
不管怎样,我自己从来没有这样做过,但是使用nltk.bigrams似乎是可能的,您可以通过使用bigrams生成随机文本
您也可以,我也不确定它是否是您想要的。对于nltk对象,您可以对其调用“generate()”,它将“打印使用三角语言模型生成的随机文本”。在nltk 2.0中,您可以使用nltk.parse.generate
生成所有可能的文本
此代码定义了一个函数,该函数应根据(p)CFG中的产生式规则生成一个句子
要利用PCFG中的权重,显然需要使用比choice()
更好的采样方法,该方法隐式假设当前节点的所有扩展都是等概率的。我的解决方案是从现有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) )
受上述启发,这里有一个使用迭代而不是递归的方法
import random
def rewrite_at(index, replacements, the_list):
del the_list[index]
the_list[index:index] = replacements
def generate_sentence(grammar):
sentence_list = [grammar.start()]
all_terminals = False
while not all_terminals:
all_terminals = True
for position, symbol in enumerate(sentence_list):
if symbol in grammar._lhs_index:
all_terminals = False
derivations = grammar._lhs_index[symbol]
derivation = random.choice(derivations) # or weighted_choice(derivations) if you have a function for that
rewrite_at(position, derivation.rhs(), sentence_list)
return sentence_list
或者如果你想要派生树,这个
from nltk.tree import Tree
def tree_from_production(production):
return Tree(production.lhs(), production.rhs())
def leaf_positions(the_tree):
return [the_tree.leaf_treeposition(i) for i in range(len(the_tree.leaves()))]
def generate_tree(grammar):
initial_derivations = grammar._lhs_index[grammar.start()]
initial_derivation = random.choice(initial_derivations) # or weighed_choice if you have that function
running_tree = tree_from_production(initial_derivation)
all_terminals = False
while not all_terminals:
all_terminals = True
for position in leaf_positions(running_tree):
node_label = running_tree[position]
if node_label in grammar._lhs_index:
all_terminals = False
derivations = grammar._lhs_index[node_label]
derivation = random.choice(derivations) # or weighed_choice if you have that function
running_tree[position] = tree_from_production(derivation)
return running_tree
以下是NLTK PCFG生产规则的加权_选择函数,用于上述操作,该函数根据Ned Batchelder对加权选择函数的一般回答改编:
def weighted_choice(productions):
prods_with_probs = [(prod, prod.prob()) for prod in productions]
total = sum(prob for prod, prob in prods_with_probs)
r = random.uniform(0, total)
upto = 0
for prod, prob in prods_with_probs:
if upto + prob >= r:
return prod
upto += prob
assert False, "Shouldn't get here"
在同一位置,请检查此线程,generate\u sample(d,frags)
行应为generate\u sample(grammar,d,frags)
。
def weighted_choice(productions):
prods_with_probs = [(prod, prod.prob()) for prod in productions]
total = sum(prob for prod, prob in prods_with_probs)
r = random.uniform(0, total)
upto = 0
for prod, prob in prods_with_probs:
if upto + prob >= r:
return prod
upto += prob
assert False, "Shouldn't get here"