提交 4ba2e36e 编写于 作者: W wizardforcel

2020-12-29 18:18:39

上级 89d09671
......@@ -15,7 +15,7 @@
## 1.1 Python 入门
Python 对用户友好的一个方式是你可以交互式地直接打字给解释器 —— 将要运行你的 Python 代码的程序。你可以通过一个简单的叫做交互式开发环境(Interactive DeveLopment Environment,简称 IDLE)的图形接口来访问 Python 解释器。在 Mac 上,你可以在*应用程序 → MacPython* 中找到;在 Windows 中,你可以在*程序 → Python* 中找到。在 Unix 下,你可以在 shell 输入`idle`来运行 Python(如果没有安装,尝试输入`python`)。解释器将会输出关于你的 Python 的版本简介,请检查你运行的是否是 Python 3.2 更高的版本(这里是 3.4.2):
Python 对用户友好的一个方式是你可以交互式地直接打字给解释器 —— 将要运行你的 Python 代码的程序。你可以通过一个简单的叫做交互式开发环境(Interactive DeveLopment Environment,简称 IDLE)的图形接口来访问 Python 解释器。在 Mac 上,你可以在“应用程序 → MacPython”中找到;在 Windows 中,你可以在“程序 → Python”中找到。在 Unix 下,你可以在 shell 输入`idle`来运行 Python(如果没有安装,尝试输入`python`)。解释器将会输出关于你的 Python 的版本简介,请检查你运行的是否是 Python 3.2 更高的版本(这里是 3.4.2):
```py
Python 3.4.2 (default, Oct 15 2014, 22:01:37)
......@@ -471,7 +471,7 @@ IndexError: list index out of range
>>>
```
这样的语句形式是:*变量 = 表达式*。Python 将计算右边的表达式把结果保存在变量中。这个过程叫做赋值。它并不产生任何输出,你必须在新的一行输入变量的名字来检查它的内容。等号可能会有些误解,因为信息是从右边流到左边的。你把它想象成一个左箭头可能会有帮助。变量的名字可以是任何你喜欢的名字,如`my_sent`, `sentence`, `xyzzy`。变量必须以字母开头,可以包含数字和下划线。下面是变量和赋值的一些例子:
这样的语句形式是:`变量 = 表达式`。Python 将计算右边的表达式把结果保存在变量中。这个过程叫做赋值。它并不产生任何输出,你必须在新的一行输入变量的名字来检查它的内容。等号可能会有些误解,因为信息是从右边流到左边的。你把它想象成一个左箭头可能会有帮助。变量的名字可以是任何你喜欢的名字,如`my_sent`, `sentence`, `xyzzy`。变量必须以字母开头,可以包含数字和下划线。下面是变量和赋值的一些例子:
```py
>>> my_sent = ['Bravely', 'bold', 'Sir', 'Robin', ',', 'rode',
......
......@@ -343,7 +343,7 @@ True
True
```
在这里`evaluate()``True`,因为`dom`中有某些 *u* 通过绑定`x`*u* 的赋值满足(`(25)` )。事实上,`o`是这样一个 *u*
在这里`evaluate()``True`,因为`dom`中有某些`u`通过绑定`x``u`的赋值满足(`(25)` )。事实上,`o`是这样一个`u`
```py
>>> m.evaluate('girl(x) & walk(x)', g.add('x', 'o'))
......@@ -371,7 +371,7 @@ NLTK 中提供了一个有用的工具是`satisfiers()`方法。它返回满足
True
```
换句话说,一个全称量化公式∀x.φ关于`g`为真,只有对每一个 *u*,φ关于`g[u/x]`为真。
换句话说,一个全称量化公式`∀x.φ`关于`g`为真,只有对每一个`u``φ`关于`g[u/x]`为真。
注意
......@@ -443,7 +443,7 @@ True
False
```
我们也可以使用模型建立器作为定理证明器的辅助。假设我们正试图证明`S``g`,即`g`是假设`S = [s1, s2, ..., sn]`的逻辑派生。我们可以同样的输入提供给 Mace4,模型建立器将尝试找出一个反例,就是要表明`g`*不*遵循从`S`。因此,给定此输入,Mace4 将尝试为假设`S`连同`g`的否定找到一个模型,即列表`S' = [s1, s2, ..., sn, -g]`。如果`g``S`不能证明出来,那么 Mace4 会返回一个反例,比 Prover9 更快的得出结论:无法找到所需的证明。相反,如果`g``S`是可以证明出来,Mace4 可能要花很长时间不能成功地找到一个反例模型,最终会放弃。
我们也可以使用模型建立器作为定理证明器的辅助。假设我们正试图证明`Sg`,即`g`是假设`S = [s1, s2, ..., sn]`的逻辑派生。我们可以同样的输入提供给 Mace4,模型建立器将尝试找出一个反例,就是要表明`g`*不*遵循从`S`。因此,给定此输入,Mace4 将尝试为假设`S`连同`g`的否定找到一个模型,即列表`S' = [s1, s2, ..., sn, -g]`。如果`g``S`不能证明出来,那么 Mace4 会返回一个反例,比 Prover9 更快的得出结论:无法找到所需的证明。相反,如果`g``S`是可以证明出来,Mace4 可能要花很长时间不能成功地找到一个反例模型,最终会放弃。
让我们思考一个具体的方案。我们的假设是列表`[There is a woman that every man loves, Adam is a man, Eve is a woman]`。我们的结论是`Adam loves Eve`。Mace4 能找到使假设为真而结论为假的模型吗?在下面的代码中,我们使用`MaceCommand()`检查已建立的模型。
......@@ -538,7 +538,7 @@ set()
(dog(cyril) & own(angus,cyril))
```
我们所有的λ-抽象到目前为止只涉及熟悉的一阶变量:`x``y`等——类型 *e* 的变量。但假设我们要处理一个抽象,例如`\x.walk(x)`作为另一个λ-抽象的参数?我们不妨试试这个:
我们所有的λ-抽象到目前为止只涉及熟悉的一阶变量:`x``y`等——类型`e`的变量。但假设我们要处理一个抽象,例如`\x.walk(x)`作为另一个λ-抽象的参数?我们不妨试试这个:
```py
\y.y(angus)(\x.walk(x))
......@@ -612,7 +612,7 @@ NLTK 提供一些实用工具使获得和检查的语义解释更容易。函数
(N[NUM='sg', SEM=<\x.ankle(x)>] ankle)))))
```
现在我们已经看到了英文句子如何转换成逻辑形式,前面我们看到了在模型中如何检查逻辑形式的真假。把这两个映射放在一起,我们可以检查一个给定的模型中的英语句子的真值。让我们看看前面定义的模型`m`。工具`evaluate_sents()`类似于`interpret_sents()`,除了我们需要传递一个模型和一个变量赋值作为参数。输出是三元组(_synrep_, *semrep*, *value*),其中 *synrep**semrep* 和以前一样,*value* 是真值。为简单起见,下面的例子只处理一个简单的句子。
现在我们已经看到了英文句子如何转换成逻辑形式,前面我们看到了在模型中如何检查逻辑形式的真假。把这两个映射放在一起,我们可以检查一个给定的模型中的英语句子的真值。让我们看看前面定义的模型`m`。工具`evaluate_sents()`类似于`interpret_sents()`,除了我们需要传递一个模型和一个变量赋值作为参数。输出是三元组`(synrep, semrep, value)`,其中`synrep``semrep`和以前一样,`value`是真值。为简单起见,下面的例子只处理一个简单的句子。
```py
>>> v = """
......@@ -834,7 +834,7 @@ d1: ['s0-r1', 's1-r0'] : ([z12,z15],[boy(z12), (([x],[dog(x)]) ->
* 在将自然语言句子翻译成一阶逻辑的同时,我们可以通过检查一阶公式模型表述这些句子的真值条件。
* 为了构建成分组合的意思表示,我们为一阶逻辑补充了λ-演算。
* λ-演算中的β-约简在语义上与函数传递参数对应。句法上,它包括将被函数表达式中的λ绑定的变量替换为函数应用中表达式提供的参数。
* 构建模型的一个关键部分在于建立估值,为非逻辑常量分配解释。这些被解释为 *n* 元谓词或独立常量。
* 构建模型的一个关键部分在于建立估值,为非逻辑常量分配解释。这些被解释为`n`元谓词或独立常量。
* 一个开放表达式是一个包含一个或多个自由变量的表达式。开放表达式只在它的自由变量被赋值时被解释。
* 量词的解释是对于具有变量`x`的公式`φ[x]`,构建个体的集合,赋值`g`分配它们作为`x`的值使`φ[x]`为真。然后量词对这个集合加以约束。
* 一个封闭的表达式是一个没有自由变量的表达式;也就是,变量都被绑定。一个封闭的表达式是真是假取决于所有变量赋值。
......
......@@ -150,7 +150,7 @@ Kappa 系数`K`测量两个人判断类别和修正预期的期望一致性的
最简单的方法是获得出版的网页文本的文集。Web 语料库 ACL 特别兴趣组(SIGWAC)在`http://www.sigwac.org.uk/`维护一个资源列表。使用定义好的 Web 语料库的优点是它们有文档、稳定并允许重复性实验。
如果所需的内容在一个特定的网站,有许多实用程序能捕获网站的所有可访问内容,如 *GNU Wget* `http://www.gnu.org/software/wget/`。为了最大的灵活性和可控制,可以使用网络爬虫如 *Heritrix*`http://crawler.archive.org/`(Croft, Metzler, & Strohman, 2009)。例如:如果我们要编译双语文本集合,对应两种语言的文档对,爬虫需要检测站点的结构以提取文件之间的对应关系,它需要按照捕获的对应方式组织下载的页面。写你自己的网页爬虫可能使很有诱惑力的,但也有很多陷阱需要克服,如检测 MIME 类型、转换相对地址为绝对 URL、避免被困在循环链接结构、处理网络延迟、避免使站点超载或被禁止访问该网站等。
如果所需的内容在一个特定的网站,有许多实用程序能捕获网站的所有可访问内容,如 *GNU Wget*`http://www.gnu.org/software/wget/`。为了最大的灵活性和可控制,可以使用网络爬虫如 *Heritrix*`http://crawler.archive.org/`(Croft, Metzler, & Strohman, 2009)。例如:如果我们要编译双语文本集合,对应两种语言的文档对,爬虫需要检测站点的结构以提取文件之间的对应关系,它需要按照捕获的对应方式组织下载的页面。写你自己的网页爬虫可能使很有诱惑力的,但也有很多陷阱需要克服,如检测 MIME 类型、转换相对地址为绝对 URL、避免被困在循环链接结构、处理网络延迟、避免使站点超载或被禁止访问该网站等。
## 3.2 从字处理器文件获取数据
......
......@@ -69,7 +69,7 @@ g. There are two ways to do this, AFAIK :smile: (internet discussion archive)
这本书涵盖了自然语言处理领域的许多主题。大多数的例子都使用 Python 和英语。不过,如果读者得出的结论是 NLP 是有关如何编写 Python 程序操纵英文文本,或者更广泛的,关于如何编写程序(以任何一种编程语言)处理(任何一种自然语言)文本的,这将是不幸的。我们选择 Python 和英语是权宜之计,仅此而已。即使我们关注编程本身也只是一种解决问题的手段:作为一种了解表示和操纵语言标注文本的集合的数据结构和算法的方式,作为一种方法来建立新的语言技术,更好地服务于信息社会的需求,并最终作为对人类语言极度丰富性的更深的理解的方法。
*但是目前为止,happy hacking!*
*但是目前为止,快乐编程吧!*
## 关于本文档...
......
......@@ -418,7 +418,7 @@ NLTK 中定义的基本语料库函数:使用`help(nltk.corpus.reader)`可以
170576
```
因此,在下面的代码中我们可以看到,列表`genre_word`的前几个配对将是 (`'news'`, *word*) ❶的形式,而最后几个配对将是 (`'romance'`, *word*) ❷的形式。
因此,在下面的代码中我们可以看到,列表`genre_word`的前几个配对将是`('news', word)`❶的形式,而最后几个配对将是`('romance', word)`❷的形式。
```py
>>> genre_word[:4]
......@@ -876,7 +876,7 @@ KeyError: 'blog'
'throw'
```
通过添加其他源语言,我们可以让我们这个简单的翻译器更为有用。让我们使用`dict()`函数把德语-英语和西班牙语-英语对相互转换成一个词典,然后用这些添加的映射*更新*我们原来的`翻译`词典:
通过添加其他源语言,我们可以让我们这个简单的翻译器更为有用。让我们使用`dict()`函数把德语-英语和西班牙语-英语对相互转换成一个词典,然后用这些添加的映射*更新*我们原来的`translate`词典:
```py
>>> de2en = swadesh.entries(['de', 'en']) # German-English
......@@ -1222,11 +1222,11 @@ WordNet 原始描述是(Fellbaum, 1998)。虽然 WordNet 最初是为心理
20. ◑ 写一个函数`word_freq()`,用一个词和布朗语料库中的一个部分的名字作为参数,计算这部分语料中词的频率。
21. ◑ 写一个程序,估算一个文本中的音节数,利用 CMU 发音词典。
22. ◑ 定义一个函数`hedge(text)`,处理一个文本和产生一个新的版本在每三个词之间插入一个词`'like'`
23.**齐夫定律***f(w)* 是一个自由文本中的词`w`的频率。假设一个文本中的所有词都按照它们的频率排名,频率最高的在最前面。齐夫定律指出一个词类型的频率与它的排名成反比(即`f × r = k``k`是某个常数)。例如:最常见的第 50 个词类型出现的频率应该是最常见的第 150 个词型出现频率的 3 倍。
23.**齐夫定律**`f(w)`是一个自由文本中的词`w`的频率。假设一个文本中的所有词都按照它们的频率排名,频率最高的在最前面。齐夫定律指出一个词类型的频率与它的排名成反比(即`f × r = k``k`是某个常数)。例如:最常见的第 50 个词类型出现的频率应该是最常见的第 150 个词型出现频率的 3 倍。
1. 写一个函数来处理一个大文本,使用`pylab.plot`画出相对于词的排名的词的频率。你认可齐夫定律吗?(提示:使用对数刻度会有帮助。)所绘的线的极端情况是怎样的?
2. 随机生成文本,如使用`random.choice("abcdefg ")`,注意要包括空格字符。你需要事先`import random`。使用字符串连接操作将字符累积成一个很长的字符串。然后为这个字符串分词,产生前面的齐夫图,比较这两个图。此时你怎么看齐夫定律?
24. ★ 修改例 2.2 的文本生成程序,进一步完成下列任务:
1. 在一个列表`words`中存储 *n* 个最相似的词,使用`random.choice()`从列表中随机选取一个词。(你将需要事先`import random`。)
1. 在一个列表`words`中存储`n`个最相似的词,使用`random.choice()`从列表中随机选取一个词。(你将需要事先`import random`。)
2. 选择特定的文体,如布朗语料库中的一部分或者《创世纪》翻译或者古腾堡语料库中的文本或者一个网络文本。在此语料上训练一个模型,产生随机文本。你可能要实验不同的起始字。文本的可理解性如何?讨论这种方法产生随机文本的长处和短处。
3. 现在使用两种不同文体训练你的系统,使用混合文体文本做实验。讨论你的观察结果。
25. ★ 定义一个函数`find_language()`,用一个字符串作为其参数,返回包含这个字符串作为词汇的语言的列表。使用《世界人权宣言》`udhr`的语料,将你的搜索限制在 Latin-1 编码的文件中。
......
......@@ -204,7 +204,7 @@ IOError: [Errno 2] No such file or directory: 'document.txt'
'Time flies like an arrow.\nFruit flies like a banana.\n'
```
回想一`'\n'`字符是换行符;这相当于按键盘上的 *Enter* 开始一个新行。
回想一`'\n'`字符是换行符;这相当于按键盘上的`Enter`开始一个新行。
我们也可以使用一个`for`循环一次读文件中的一行:
......@@ -926,7 +926,7 @@ v 93 27 105 48 49
[('processe', 's')]
```
正则表达式错误地找到了后缀`-s`,而不是后缀`-es`。这表明另一个微妙之处:星号操作符是“贪婪的”,所以表达式的`.*`部分试图尽可能多的匹配输入的字符串。如果我们使用“非贪婪”版本的*”操作符,写成`*?`,我们就得到我们想要的:
正则表达式错误地找到了后缀`-s`,而不是后缀`-es`。这表明另一个微妙之处:星号操作符是“贪婪的”,所以表达式的`.*`部分试图尽可能多的匹配输入的字符串。如果我们使用“非贪婪”版本的`*`操作符,写成`*?`,我们就得到我们想要的:
```py
>>> re.findall(r'^(.*?)(ing|ly|ed|ious|ies|ive|es|s|ment)$', 'processes')
......@@ -1589,10 +1589,10 @@ After (5), all (3), is (2), said (4), and (3), done (4), , (1), more
网上有许多关于 Unicode 的资源。以下是与处理 Unicode 的 Python 的工具有关的有益的讨论:
* Ned Batchelder, *Pragmatic Unicode*, `http://nedbatchelder.com/text/unipain.html`
* *Unicode HOWTO*, Python Documentation, `http://docs.python.org/3/howto/unicode.html`
* David Beazley, Mastering Python 3 I/O, `http://pyvideo.org/video/289/pycon-2010--mastering-python-3-i-o`
* Joel Spolsky, *The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)*, `http://www.joelonsoftware.com/articles/Unicode.html`
+ `Ned Batchelder, Pragmatic Unicode, http://nedbatchelder.com/text/unipain.html`
+ `Unicode HOWTO, Python Documentation, http://docs.python.org/3/howto/unicode.html`
+ `David Beazley, Mastering Python 3 I/O, http://pyvideo.org/video/289/pycon-2010--mastering-python-3-i-o`
+ `Joel Spolsky, The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!), http://www.joelonsoftware.com/articles/Unicode.html`
SIGHAN,ACL 中文语言处理特别兴趣小组`http://sighan.org/`,重点关注中文文本分词的问题。我们分割英文文本的方法依据(Brent, 1995);这项工作属于语言获取领域(Niyogi, 2006)。
......@@ -1680,7 +1680,7 @@ SIGHAN,ACL 中文语言处理特别兴趣小组`http://sighan.org/`,重点
23. ◑ 你能写一个正则表达式以这样的方式来分词吗,将词`don't`分为`do``n't`?解释为什么这个正则表达式无法正常工作:`n't|\w+`
24. ◑ 尝试编写代码将文本转换成 *hAck3r*,使用正则表达式和替换,其中`e``3`, `i``1`, `o``0`, `l``|`, `s``5`, `.``5w33t!`, `ate``8`。在转换之前将文本规范化为小写。自己添加更多的替换。现在尝试将`s`映射到两个不同的值:词开头的`s`映射为`
24. ◑ 尝试编写代码将文本转换成`hAck3r`,使用正则表达式和替换,其中`e``3`, `i``1`, `o``0`, `l``|`, `s``5`, `.``5w33t!`, `ate``8`。在转换之前将文本规范化为小写。自己添加更多的替换。现在尝试将`s`映射到两个不同的值:词开头的`s`映射为`
25. ◑ *Pig Latin* 是英语文本的一个简单的变换。文本中每个词的按如下方式变换:将出现在词首的所有辅音(或辅音群)移到词尾,然后添加`ay`,例如`string → ingstray`, `idle → idleay`。`http://en.wikipedia.org/wiki/Pig_Latin`
......
......@@ -451,7 +451,7 @@ True
确保循环变量范围的正确相当棘手的。因为这是 NLP 中的常见操作,NLTK 提供了支持函数`bigrams(text)``trigrams(text)`和一个更通用的`ngrams(text, n)`
下面是我们如何使用循环变量构建多维结构的一个例子。例如,建立一个 *m**n* 列的数组,其中每个元素是一个集合,我们可以使用一个嵌套的列表推导:
下面是我们如何使用循环变量构建多维结构的一个例子。例如,建立一个`m``n`列的数组,其中每个元素是一个集合,我们可以使用一个嵌套的列表推导:
```py
>>> m, n = 3, 7
......@@ -1408,7 +1408,7 @@ Python 网站提供大量文档。理解内置的函数和标准类型是很重
1. 现在尝试同样的练习,但使用`sent2 = sent1[:]`赋值。再次修改`sent1`看看`sent2`会发生什么。解释。
2. 现在定义`text1`为一个字符串列表的列表(例如表示由多个句子组成的文本)。现在赋值`text2 = text1[:]`,分配一个新值给其中一个词,例如`text1[1][1] = 'Monty'`。检查这对`text2`做了什么。解释。
3. 导入 Python 的`deepcopy()`函数(即`from copy import deepcopy`),查询其文档,使用它生成任一对象的新副本。
12. ◑ 使用列表乘法初始化 *n*-by-*m* 的空字符串列表的咧表,例如`word_table = [[''] * n] * m`。当你设置其中一个值时会发生什么事,例如`word_table[1][2] = "hello"`?解释为什么会出现这种情况。现在写一个表达式,使用`range()`构造一个列表,表明它没有这个问题。
12. ◑ 使用列表乘法初始化`n x m`的空字符串列表的咧表,例如`word_table = [[''] * n] * m`。当你设置其中一个值时会发生什么事,例如`word_table[1][2] = "hello"`?解释为什么会出现这种情况。现在写一个表达式,使用`range()`构造一个列表,表明它没有这个问题。
13. ◑ 写代码初始化一个称为`word_vowels`的二维数组的集合,处理一个词列表,添加每个词到`word_vowels[l][v]`,其中`l`是词的长度,`v`是它包含的元音的数量。
......
......@@ -967,7 +967,7 @@ def display():
0.102063...
```
*n* 越大,上下文的特异性就会增加,我们要标注的数据中包含训练数据中不存在的上下文的几率也增大。这被称为*数据稀疏*问题,在 NLP 中是相当普遍的。因此,我们的研究结果的精度和覆盖范围之间需要有一个权衡(这与信息检索中的精度/召回权衡有关)。
`n`越大,上下文的特异性就会增加,我们要标注的数据中包含训练数据中不存在的上下文的几率也增大。这被称为*数据稀疏*问题,在 NLP 中是相当普遍的。因此,我们的研究结果的精度和覆盖范围之间需要有一个权衡(这与信息检索中的精度/召回权衡有关)。
小心!
......
......@@ -462,7 +462,7 @@ def segment_sentences(words):
## 2.2 识别对话行为类型
处理对话时,将对话看作说话者执行的*行为*是很有用的。对于表述行为的陈述句这种解释是最直白的,例如"I forgive you"或"I bet you can't climb that hill"。但是问候、问题、回答、断言和说明都可以被认为是基于语言的行为类型。识别对话中言语下的对话行为是理解谈话的重要的第一步。
处理对话时,将对话看作说话者执行的*行为*是很有用的。对于表述行为的陈述句这种解释是最直白的,例如`I forgive you``I bet you can't climb that hill`。但是问候、问题、回答、断言和说明都可以被认为是基于语言的行为类型。识别对话中言语下的对话行为是理解谈话的重要的第一步。
NPS 聊天语料库,在 1 中的展示过,包括超过 10,000 个来自即时消息会话的帖子。这些帖子都已经被贴上 15 种对话行为类型中的一种标签,例如“陈述”,“情感”,“是否问题”和“接续”。因此,我们可以利用这些数据建立一个分类器,识别新的即时消息帖子的对话行为类型。第一步是提取基本的消息数据。我们将调用`xml_posts()`来得到一个数据结构,表示每个帖子的 XML 注释:
......
......@@ -128,7 +128,7 @@ grammar2 = nltk.CFG.fromstring("""
一种简单的自下而上分析器是移进-归约分析器。与所有自下而上的分析器一样,移进-归约分析器尝试找到对应文法生产式*右侧*的词和短语的序列,用左侧的替换它们,直到整个句子归约为一个`S`
移位-规约分析器反复将下一个输入词推到堆栈`(4.1)`;这是移位操作。如果堆栈上的前 *n* 项,匹配一些产生式的右侧的`n`个项目,那么就把它们弹出栈,并把产生式左边的项目压入栈。这种替换前`n`项为一项的操作就是规约操作。此操作只适用于堆栈的顶部;规约栈中的项目必须在后面的项目被压入栈之前做。当所有的输入都使用过,堆栈中只剩余一个项目,也就是一颗分析树作为它的根的`S`节点时,分析器完成。移位-规约分析器通过上述过程建立一颗分析树。每次弹出堆栈`n`个项目,它就将它们组合成部分的分析树,然后将这压回推栈。我们可以使用图形化示范`nltk.app.srparser()`看到移位-规约分析算法步骤。执行此分析器的六个阶段,如 4.2 所示。
移位-规约分析器反复将下一个输入词推到堆栈`(4.1)`;这是移位操作。如果堆栈上的前`n`项,匹配一些产生式的右侧的`n`个项目,那么就把它们弹出栈,并把产生式左边的项目压入栈。这种替换前`n`项为一项的操作就是规约操作。此操作只适用于堆栈的顶部;规约栈中的项目必须在后面的项目被压入栈之前做。当所有的输入都使用过,堆栈中只剩余一个项目,也就是一颗分析树作为它的根的`S`节点时,分析器完成。移位-规约分析器通过上述过程建立一颗分析树。每次弹出堆栈`n`个项目,它就将它们组合成部分的分析树,然后将这压回推栈。我们可以使用图形化示范`nltk.app.srparser()`看到移位-规约分析算法步骤。执行此分析器的六个阶段,如 4.2 所示。
![Images/srparser1-6.png](Images/56cee123595482cf3edaef089cb9a6a7.jpg)
......@@ -465,7 +465,7 @@ grammar = nltk.PCFG.fromstring("""
* 句子都有内部组织结构,可以用一棵树表示。组成结构的显著特点是:递归、中心词、补语和修饰语。
* 语法是一个潜在的无限的句子集合的一个紧凑的特性;我们说,一棵树是符合语法规则的或语法树授权一棵树。
* 语法是用于描述一个给定的短语是否可以被分配一个特定的成分或依赖结构的一种形式化模型。
* 给定一组句法类别,上下文无关文法使用一组生产式表示某类型 *A* 的短语如何能够被分析成较小的序列`α[1] ... α[n]`
* 给定一组句法类别,上下文无关文法使用一组生产式表示某类型`A`的短语如何能够被分析成较小的序列`α[1] ... α[n]`
* 依存语法使用产生式指定给定的中心词的依赖是什么。
* 一个句子有一个以上的句法分析就产生句法歧义(如介词短语附着歧义)。
* 分析器是一个过程,为符合语法规则的句子寻找一个或多个相应的树。
......@@ -503,7 +503,7 @@ grammar = nltk.PCFG.fromstring("""
7. ☼ 分析 A.A. Milne 关于 Piglet 的句子,为它包含的所有句子画下划线,然后用`S`替换这些(如第一句话变为`S when:lx S`)。为这种“压缩”的句子画一个树形结构。用于建立这样一个长句的主要的句法结构是什么?
8. ☼ 在递归下降分析器的演示中,通过选择 *Edit* 菜单上的 *Edit Text* 改变实验句子。
8. ☼ 在递归下降分析器的演示中,通过选择`Edit`菜单上的`Edit Text`改变实验句子。
9.`grammar1`中的语法能被用来描述长度超过 20 词的句子吗?
......@@ -553,7 +553,7 @@ grammar = nltk.PCFG.fromstring("""
28. ◑ 处理宾州树库语料库样本`nltk.corpus.treebank`中的每棵树,在`Tree.productions()`的帮助下提取产生式。丢弃只出现一次的产生式。具有相同的左侧和类似的右侧的产生式可以被折叠,产生一个等价的却更紧凑的规则集。编写代码输出一个紧凑的语法。
29. ★ 英语中定义句子`S`的主语的一种常见的方法是作为`S`*的名词短语孩子*`VP`*兄弟*。写一个函数,以一句话的树为参数,返回句子主语对应的子树。如果传递给这个函数的树的根节点不是`S`或它缺少一个主语,应该怎么做?
29. ★ 英语中定义句子`S`的主语的一种常见的方法是作为`S`*孩子*`VP`*兄弟*的名词短语。写一个函数,以一句话的树为参数,返回句子主语对应的子树。如果传递给这个函数的树的根节点不是`S`或它缺少一个主语,应该怎么做?
30. ★ 写一个函数,以一个语法(如 3.1 定义的语法)为参数,返回由这个语法随机产生的一个句子。(使用`grammar.start()`找出语法的开始符号;`grammar.productions(lhs)`得到具有指定左侧的语法的产生式的列表;`production.rhs()`得到一个产生式的右侧。)
......
......@@ -56,7 +56,7 @@ PAT => l
... 'SRC': 'sbj', 'EXP': 'obj'}
```
特征结构是非常强大的,但我们操纵它们的方式是极其 *ad hoc*。我们本章接下来的任务是,显示上下文无关语法和分析如何能扩展到合适的特征结构,使我们可以一种更通用的和有原则的方式建立像这样的分析。我们将通过查看句法协议的现象作为开始;我们将展示如何使用特征典雅的表示协议约束,并在一个简单的语法中说明它们的用法。
特征结构是非常强大的,但我们操纵它们的方式是极其*特别的*。我们本章接下来的任务是,显示上下文无关语法和分析如何能扩展到合适的特征结构,使我们可以一种更通用的和有原则的方式建立像这样的分析。我们将通过查看句法协议的现象作为开始;我们将展示如何使用特征典雅的表示协议约束,并在一个简单的语法中说明它们的用法。
由于特征结构是表示任何形式的信息的通用的数据结构,我们将从更形式化的视点简要地看着它们,并演示 NLTK 提供的特征结构的支持。在本章的最后一部分,我们将表明,特征的额外表现力开辟了一个用于描述语言结构的复杂性的广泛的可能性。
......@@ -686,25 +686,26 @@ In the case of complex values, we say that feature structures are themselves typ
5. ◑ 扩展 3.2 中的德语语法,使它能处理所谓的动词第二顺位结构,如下所示:
| (58) | | Heute sieht der Hund die Katze. |
`Heute sieht der Hund die Katze. (58)`
6. ◑ 同义动词的句法属性看上去略有不同(Levin, 1993)。思考下面的动词`loaded``filled``dumped`的语法模式。你能写语法产生式处理这些数据吗?
| (59) | |
```py
&#124; a. &#124; &#124; The farmer *loaded* the cart with sand &#124;
(59)
&#124; b. &#124; &#124; The farmer *loaded* sand into the cart &#124;
a. The farmer *loaded* the cart with sand
&#124; c. &#124; &#124; The farmer *filled* the cart with sand &#124;
b. The farmer *loaded* sand into the cart
&#124; d. &#124; &#124; *The farmer *filled* sand into the cart &#124;
c. The farmer *filled* the cart with sand
&#124; e. &#124; &#124; *The farmer *dumped* the cart with sand &#124;
d. *The farmer *filled* sand into the cart
&#124; f. &#124; &#124; The farmer *dumped* sand into the cart &#124;
e. *The farmer *dumped* the cart with sand
|
f. The farmer *dumped* sand into the cart
```
7. ★ 形态范例很少是完全正规的,矩阵中的每个单元的意义有不同的实现。例如,词位`walk`的现在时态词性变化只有两种不同形式:第三人称单数的`walks`和所有其他人称和数量的组合的`walk`。一个成功的分析不应该额外要求 6 个可能的形态组合中有 5 个有相同的实现。设计和实施一个方法处理这个问题。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册