- 9 练习
9 练习
☼ 你能想出符合语法的却可能之前从来没有被说出的句子吗?(与伙伴轮流进行。)这告诉你关于人类语言的什么?
☼ 回想一下 Strunk 和 White 的禁止在句子开头使用 however 表示“although”的意思。在网上搜索句子开头使用的 however。这个成分使用的有多广泛?
☼ 思考句子<cite>Kim arrived or Dana left and everyone cheered</cite>。用括号的形式表示 and 和 or 的相对范围。产生这两种解释对应的树结构。
☼
Tree
类实现了各种其他有用的方法。请看Tree
帮助文档查阅更多细节(如导入 Tree 类,然后输入help(Tree)
)。☼ 在本练习中,你将手动构造一些分析树。
- 编写代码产生两棵树,对应短语 old men and women 的不同读法
- 将本章中表示的任一一颗树编码为加标签的括号括起的形式,使用
nltk.Tree()
检查它是否符合语法。使用draw()
显示树。 - 如(a) 中那样,为 The woman saw a man last Thursday 画一棵树。
☼ 写一个递归函数,遍历一颗树,返回树的深度,一颗只有一个节点的树的深度应为 0。(提示:子树的深度是其子女的最大深度加 1。)
☼ 分析 A.A. Milne 关于 Piglet 的句子,为它包含的所有句子画下划线,然后用
S
替换这些(如第一句话变为S
<cite>when</cite>:lx`S
)。为这种“压缩”的句子画一个树形结构。用于建立这样一个长句的主要的句法结构是什么?☼ 在递归下降分析器的演示中,通过选择 Edit 菜单上的 Edit Text 改变实验句子。
☼
grammar1
中的语法能被用来描述长度超过 20 词的句子吗?☼ 使用图形化图表分析器接口,尝试不同的规则调用策略做实验。拿出你自己的可以使用图形界面手动执行的策略。描述步骤,并报告它的任何效率的提高(例如用结果图表示大小)。这些改进取决于语法结构吗?你觉得一个更聪明的规则调用策略能显著提升性能吗?
☼ 对于一个你已经见过的或一个你自己设计的 CFG,用笔和纸手动跟踪递归下降分析器和移位-规约分析器的执行。
☼ 我们已经看到图表分析器增加边而从来不从图表中删除的边。为什么?
☼ 思考词序列:Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo。如
http://en.wikipedia.org/wiki/Buffalo_buffalo_Buffalo_buffalo_buffalo_buffalo_Buffalo_buffalo
解释的,这是一个语法正确的句子。思考此维基百科页面上表示的树形图,写一个合适的语法。正常情况下是小写,模拟听到这句话时听者会遇到的问题。你能为这句话找到其他的解析吗?当句子变长时分析树的数量如何增长?(这些句子的更多的例子可以在http://en.wikipedia.org/wiki/List_of_homophonous_phrases
找到。)◑ 你可以通过选择 Edit 菜单上的 Edit Grammar 修改递归下降分析器演示程序。改变第二次扩充产生式,即
NP -> Det N PP
为NP -> NP PP
。使用 Step 按钮,尝试建立一个分析树。发生了什么?◑ 扩展
grammar2
中的语法,将产生式中的介词扩展为不及物的,及物的和需要PP
补语的。基于这些产生式,使用前面练习中的方法为句子 Lee ran away home 画一棵树。◑ 挑选一些常用动词,完成以下任务:
- 写一个程序在 PP 附着语料库
nltk.corpus.ppattach
找到那些动词。找出任何这样的情况,相同的动词有两种不同的附着,其中第一个是名词,或者第二个是名词,或者介词保持不变(正如我们在2句法歧义中讨论过的)。 - 制定 CFG 语法产生式涵盖其中一些情况。
- 写一个程序在 PP 附着语料库
◑ 写一个程序,比较自上而下的图表分析器与递归下降分析器的效率(4)。使用相同的语法和输入的句子。使用
timeit
模块比较它们的性能(见4.7,如何做到这一点的一个例子)。比较自上而下、自下而上和左角落分析器的性能,使用相同的语法和 3 个符合语法的测试句子。使用
timeit
记录每个分析器在同一个句子上花费的时间。写一个函数,在这三句话上运行这三个分析器,输出 3×3 格的时间,以及行和列的总计。讨论你的发现。◑ 阅读“garden path”的句子。一个分析器的计算工作与人类处理这些句子的困难性有什么关系?
http://en.wikipedia.org/wiki/Garden_path_sentence
◑ 若要在一个窗口比较多个树,我们可以使用
draw_trees()
方法。定义一些树,尝试一下:>>> from nltk.draw.tree import draw_trees
>>> draw_trees(tree1, tree2, tree3)
◑ 使用树中的位置,列出宾州树库前 100 个句子的主语;为了使结果更容易查看,限制从高度最高为 2 的子树提取主语。
◑ 查看 PP 附着语料库,尝试提出一些影响
PP
附着的因素。◑ 在本节中,我们说过简单的用术语 n-grams 不能描述所有语言学规律。思考下面的句子,尤其是短语 in his turn 的位置。这是基于 n-grams 的方法的一个问题吗?
> <cite>What was more, the in his turn somewhat youngish Nikolay Parfenovich also turned out to be the only person in the entire world to acquire a sincere liking to our “discriminated-against” public procurator.</cite> (Dostoevsky: The Brothers Karamazov)
◑ 编写一个递归函数产生嵌套的括号括起的形式的一棵树,显示去掉叶节点之后的子树的非终结符。于是上面的关于 Pierre Vinken 的例子会产生:
[[[NNP NNP]NP , [ADJP [CD NNS]NP JJ]ADJP ,]NP-SBJ MD [VB [DT NN]NP [IN [DT JJ NN]NP]PP-CLR [NNP CD]NP-TMP]VP .]S
。连续的类别应用空格分隔。◑ 从古登堡工程下载一些电子图书。写一个程序扫描这些文本中任何极长的句子。你能找到的最长的句子是什么?这么长的句子的句法结构是什么?
◑ 修改函数
init_wfst()
和complete_wfst()
,使 WFST 中每个单元的内容是一组非终端符而不是一个单独的非终结符。◑ 思考4.4中的算法。你能解释为什么分析上下文无关语法是与<cite>n</cite><sup>3</sup>成正比的,其中 n 是输入句子的长度。
◑ 处理宾州树库语料库样本
nltk.corpus.treebank
中的每棵树,在Tree.productions()
的帮助下提取产生式。丢弃只出现一次的产生式。具有相同的左侧和类似的右侧的产生式可以被折叠,产生一个等价的却更紧凑的规则集。编写代码输出一个紧凑的语法。★ 英语中定义句子
S
的主语的一种常见的方法是作为S
的名词短语孩子 和VP
的 兄弟 。写一个函数,以一句话的树为参数,返回句子主语对应的子树。如果传递给这个函数的树的根节点不是S
或它缺少一个主语,应该怎么做?★ 写一个函数,以一个语法(如3.1定义的语法)为参数,返回由这个语法随机产生的一个句子。(使用
grammar.start()
找出语法的开始符号;grammar.productions(lhs)
得到具有指定左侧的语法的产生式的列表;production.rhs()
得到一个产生式的右侧。)★ 使用回溯实现移位-规约分析器的一个版本,使它找出一个句子所有可能的解析,它可以被称为“递归上升分析器”。咨询维基百科关于回溯的条目
http://en.wikipedia.org/wiki/Backtracking
★ 正如我们在7.中所看到的,可以将词块表示成它们的词块标签。当我们为包含 gave 的句子做这个的时候,我们发现如以下模式:
gave NP
gave up NP in NP
gave NP up
gave NP NP
gave NP to NP