From 88a8a89b8b35bab34e1ac9533647f2b905162040 Mon Sep 17 00:00:00 2001 From: wizardforcel <562826179@qq.com> Date: Tue, 29 Dec 2020 14:11:21 +0800 Subject: [PATCH] 2020-12-29 14:11:21 --- 0.md | 26 ++++++++-------- 1.md | 96 +++++++++++++++++++++++++++++------------------------------ 11.md | 2 +- 2.md | 14 ++++----- 3.md | 22 +++++++------- 4.md | 6 ++-- 5.md | 4 +-- 6.md | 2 +- 8.md | 2 +- 9 files changed, 87 insertions(+), 87 deletions(-) diff --git a/0.md b/0.md index 289a266..06ceb9c 100644 --- a/0.md +++ b/0.md @@ -6,7 +6,7 @@ 这本书提供自然语言处理领域非常方便的入门指南。它可以用来自学,也可以作为自然语言处理或计算语言学课程的教科书,或是人工智能、文本挖掘、语料库语言学课程的补充读物。本书的实践性很强,包括几百个实际可用的例子和分级练习。 -本书基于 Python 编程语言及其上的一个名为*自然语言工具包*(Natural Language Toolkit ,简称 NLTK)的开源库。NLTK 包含大量的软件、数据和文档,所有这些都可以从`http://nltk.org/` 免费下载。NLTK 的发行版本支持 Windows、Macintosh 和 Unix 平台。我们强烈建议你下载 Python 和 NLTk,与我们一起尝试书中的例子和练习。 +本书基于 Python 编程语言及其上的一个名为*自然语言工具包*(Natural Language Toolkit ,简称 NLTK)的开源库。NLTK 包含大量的软件、数据和文档,所有这些都可以从`http://nltk.org/`免费下载。NLTK 的发行版本支持 Windows、Macintosh 和 Unix 平台。我们强烈建议你下载 Python 和 NLTk,与我们一起尝试书中的例子和练习。 ## 读者 @@ -21,41 +21,41 @@ NLP 是科学、经济、社会和文化的一个重要因素。NLP 正在迅速 ... print(word) ``` -这段程序演示了 Python 的一些主要特征。首先,使用空格*缩进*代码,从而使`if`后面的代码都在前面一行`for`语句的范围之内;这保证了检查单词是否以`ing`结尾的测试对所有单词都进行。第二,Python 是*面向对象*语言;每一个变量都是包含特定属性和方法的对象。例如,变量`line` 的值不仅仅是一个字符串序列。它是一个`string`对象,包含一个用来把字符串分割成词的`split()` 方法(或叫操作)。我们在对象名称后面写上一个点再写上方法名称就可以调用对象的一个方法,例如`line.split()`。第三,方法的*参数*写在括号内。例如,上面的例子中的`word.endswith('ing')`具有一个参数`'ing'` 表示我们需要找的是`ing`结尾的词而不是别的结尾的词。最后也是最重要的,Python 的可读性如此之强以至于可以相当容易的猜出程序的功能,即使你以前从未写过一行代码。 +这段程序演示了 Python 的一些主要特征。首先,使用空格*缩进*代码,从而使`if`后面的代码都在前面一行`for`语句的范围之内;这保证了检查单词是否以`ing`结尾的测试对所有单词都进行。第二,Python 是*面向对象*语言;每一个变量都是包含特定属性和方法的对象。例如,变量`line`的值不仅仅是一个字符串序列。它是一个`string`对象,包含一个用来把字符串分割成词的`split()`方法(或叫操作)。我们在对象名称后面写上一个点再写上方法名称就可以调用对象的一个方法,例如`line.split()`。第三,方法的*参数*写在括号内。例如,上面的例子中的`word.endswith('ing')`具有一个参数`'ing'`表示我们需要找的是`ing`结尾的词而不是别的结尾的词。最后也是最重要的,Python 的可读性如此之强以至于可以相当容易的猜出程序的功能,即使你以前从未写过一行代码。 我们选择 Python 是因为它的学习曲线比较平缓,文法和语义都很清晰,具有良好的处理字符串的功能。作为解释性语言,Python 便于交互式编程。作为面向对象语言,Python 允许数据和方法被方便的封装和重用。作为动态语言,Python 允许属性等到程序运行时才被添加到对象,允许变量自动类型转换,提高开发效率。Python 自带强大的标准库,包括图形编程、数值处理和网络连接等组件。 -Python 在世界各地的工业、科研、教育领域应用广泛。它因为提高了软件的生产效率、质量和可维护性而备受称赞。`http://python.org/about/success/` 中列举了许多成功使用 Python 的故事。 +Python 在世界各地的工业、科研、教育领域应用广泛。它因为提高了软件的生产效率、质量和可维护性而备受称赞。`http://python.org/about/success/`中列举了许多成功使用 Python 的故事。 NLTK 定义了一个使用 Python 进行 NLP 编程的基础工具。它提供重新表示自然语言处理相关数据的基本类,词性标注、文法分析、文本分类等任务的标准接口以及这些任务的标准实现,可以组合起来解决复杂的问题。 -NLTK 自带大量文档。作为本书的补充,`http://nltk.org/` 网站提供的 API 文档涵盖工具包中每一个模块、类和函数,详细说明了各种参数,还给出了用法示例。 +NLTK 自带大量文档。作为本书的补充,`http://nltk.org/`网站提供的 API 文档涵盖工具包中每一个模块、类和函数,详细说明了各种参数,还给出了用法示例。 ## Python 3 和 NLTK 3 本书的这个版本已更新并支持 Python 3 和 NLTK 3。Python 3 包括一些重大的变化︰ -* `print` 语句现在是函数,因此需要括号; +* `print`语句现在是函数,因此需要括号; * 许多函数现在返回迭代器而不是列表 (以节省内存使用); * 整数除法返回一个浮点数 * 所有文本现在都是 Unicode 编码 -* 字符串的格式化使用`format` 方法 +* 字符串的格式化使用`format`方法 -这些变化的更多细节请参见`https://docs.python.org/dev/whatsnew/3.0.html`.。有一个`2to3.py` 工具可以将 Python 2 代码转换为 Python 3;关详细信息请参阅`https://docs.python.org/2/library/2to3.html`。 +这些变化的更多细节请参见`https://docs.python.org/dev/whatsnew/3.0.html`.。有一个`2to3.py`工具可以将 Python 2 代码转换为 Python 3;关详细信息请参阅`https://docs.python.org/2/library/2to3.html`。 NLTK 同样很多地方都有更改︰ -* 许多类型使用`fromstring()` 方法从字符串初始化 +* 许多类型使用`fromstring()`方法从字符串初始化 * 许多函数现在返回迭代器而不是列表 -* `ContextFreeGrammar` 现在叫做`CFG`,`WeightedGrammar` 现在叫做`PCFG` -* `batch_tokenize()` 现在叫做`tokenize_sents()`;对应的标记器, 解析器和分类器都有变化 +* `ContextFreeGrammar`现在叫做`CFG`,`WeightedGrammar`现在叫做`PCFG` +* `batch_tokenize()`现在叫做`tokenize_sents()`;对应的标记器, 解析器和分类器都有变化 * 有些实现已删除以支持外部包,或因为不能充分维护 更详细的变更列表请参见`https://github.com/nltk/nltk/wiki/Porting-your-code-to-NLTK-3.0`。 ## 软件安装需求 -为了充分利用好本书,你应该安装一些免费的软件包。`http://nltk.org/` 上有这些软件包当前的下载链接和安装说明。 +为了充分利用好本书,你应该安装一些免费的软件包。`http://nltk.org/`上有这些软件包当前的下载链接和安装说明。 | Python: | 本书中例子假定你正在使用 Python 3.2 或更高版本。(注,NLTK 3.0 也适用于 Python 2.6 和 2.7)。 | | --- | --- | @@ -163,7 +163,7 @@ NLTK 设计中的四个主要目标: ## 致谢 -作者感激为本书早期手稿提供反馈意见的人,他们是:Doug Arnold, Michaela Atterer, Greg Aumann, Kenneth Beesley, Steven Bethard, Ondrej Bojar, Chris Cieri, Robin Cooper, Grev Corbett, James Curran, Dan Garrette, Jean Mark Gawron, Doug Hellmann, Nitin Indurkhya, Mark Liberman, Peter Ljunglöf, Stefan Müller, Robin Munn, Joel Nothman, Adam Przepiorkowski, Brandon Rhodes, Stuart Robinson, Jussi Salmela, Kyle Schlansker, Rob Speer 和 Richard Sproat。感谢许许多多的学生和同事,他们关于课堂材料的意见演化成本书的这些章节,其中包括巴西,印度和美国的 NLP 与语言学暑期学校的参加者。没有`nltk-dev` 开发社区的成员们的努力这本书也不会存在,他们为建设和壮大 NLTK 无私奉献他们的时间和专业知识,他们的名字都记录在 NLTK 网站上。 +作者感激为本书早期手稿提供反馈意见的人,他们是:Doug Arnold, Michaela Atterer, Greg Aumann, Kenneth Beesley, Steven Bethard, Ondrej Bojar, Chris Cieri, Robin Cooper, Grev Corbett, James Curran, Dan Garrette, Jean Mark Gawron, Doug Hellmann, Nitin Indurkhya, Mark Liberman, Peter Ljunglöf, Stefan Müller, Robin Munn, Joel Nothman, Adam Przepiorkowski, Brandon Rhodes, Stuart Robinson, Jussi Salmela, Kyle Schlansker, Rob Speer 和 Richard Sproat。感谢许许多多的学生和同事,他们关于课堂材料的意见演化成本书的这些章节,其中包括巴西,印度和美国的 NLP 与语言学暑期学校的参加者。没有`nltk-dev`开发社区的成员们的努力这本书也不会存在,他们为建设和壮大 NLTK 无私奉献他们的时间和专业知识,他们的名字都记录在 NLTK 网站上。 非常感谢美国国家科学基金会、语言数据联盟、Edward Clarence Dyason 奖学金、宾州大学、爱丁堡大学和墨尔本大学对我们在本书相关的工作上的支持。 @@ -179,7 +179,7 @@ NLTK 设计中的四个主要目标: **Ewan Klein**是英国爱丁堡大学信息学院语言技术教授。于 1978 年在剑桥大学完成形式语义学博士学位。在苏塞克斯和纽卡斯尔大学工作多年后,参加了在爱丁堡的教学岗位。他于 1993 年参与了爱丁堡语言科技集团的建立,并一直与之密切联系。从 2000 到 2002,他离开大学作为圣克拉拉的埃迪法公司的总部在爱丁堡的自然语言的研究小组的研发经理,负责处理口语对话。Ewan 是计算语言学协会欧洲分会(European Chapter of the Association for Computational Linguistics)前任主席,并且是人类语言技术(ELSNET)欧洲卓越网络的创始成员和协调员。 -**Edward Loper** 最近完成了宾夕法尼亚大学自然语言处理的机器学习博士学位。Edward 是 Steven 在 2000 年秋季计算语言学研究生课程的学生,也是教师助手和 NLTK 开发的成员。除了 NLTK,他帮助开发了用于文档化和测试 Python 软件的两个包:`epydoc` 和`doctest`。 +**Edward Loper** 最近完成了宾夕法尼亚大学自然语言处理的机器学习博士学位。Edward 是 Steven 在 2000 年秋季计算语言学研究生课程的学生,也是教师助手和 NLTK 开发的成员。除了 NLTK,他帮助开发了用于文档化和测试 Python 软件的两个包:`epydoc`和`doctest`。 ## 版税 diff --git a/1.md b/1.md index 7053d1e..3bfcb95 100644 --- a/1.md +++ b/1.md @@ -26,9 +26,9 @@ Type "help", "copyright", "credits" or "license" for more information. 注 -如果你无法运行 Python 解释器可能是因为没有正确安装 Python。请访问`http://python.org/`查阅详细操作说明。NLTK 3.0 在 Python 2.6 和 2.7 上同样可以工作。如果你使用的是这些较旧的版本,注意`/` 运算符会向下舍入小数(所以`1/3` 会得到`0`)。为了得到预期的除法行为,你需要输入︰`from __future__ import division` +如果你无法运行 Python 解释器可能是因为没有正确安装 Python。请访问`http://python.org/`查阅详细操作说明。NLTK 3.0 在 Python 2.6 和 2.7 上同样可以工作。如果你使用的是这些较旧的版本,注意`/`运算符会向下舍入小数(所以`1/3`会得到`0`)。为了得到预期的除法行为,你需要输入︰`from __future__ import division` -`>>>` 提示符表示 Python 解释器正在等待输入。复制这本书的例子时,自己不要键入"`>>>`"。现在,让我们开始把 Python 当作计算器使用: +`>>>`提示符表示 Python 解释器正在等待输入。复制这本书的例子时,自己不要键入"`>>>`"。现在,让我们开始把 Python 当作计算器使用: ```py >>> 1 + 5 * 2 - 3 @@ -59,7 +59,7 @@ SyntaxError: invalid syntax ## 1.2 NLTK 入门 -在进一步深入之前,应先安装 NLTK 3.0,可以从`http://nltk.org/` 免费下载。按照说明下载适合你的操作系统的版本。 +在进一步深入之前,应先安装 NLTK 3.0,可以从`http://nltk.org/`免费下载。按照说明下载适合你的操作系统的版本。 安装完 NLTK 之后,像前面那样启动 Python 解释器,在 Python 提示符后面输入下面两个命令来安装本书所需的数据,然后选择`book`集合,如[1.1](http://www.nltk.org/book/ch01.html#fig-nltk-downloader)所示。 @@ -70,9 +70,9 @@ SyntaxError: invalid syntax ![Images/nltk-downloader.png](Images/7f27bfe5324e4d9573ddd210531a8126.jpg) -图 1.1:下载 NLTK Book 集:使用`nltk.download()` 浏览可用的软件包.下载器上**Collections** 选项卡显示软件包如何被打包分组,选择**book** 标记所在行,可以获取本书的例子和练习所需的全部数据。这些数据包括约 30 个压缩文件,需要 100MB 硬盘空间。完整的数据集(即下载器中的**all**)在本书写作期间大约是这个大小的 10 倍,还在不断扩充。 +图 1.1:下载 NLTK Book 集:使用`nltk.download()`浏览可用的软件包.下载器上`Collections`选项卡显示软件包如何被打包分组,选择`book`标记所在行,可以获取本书的例子和练习所需的全部数据。这些数据包括约 30 个压缩文件,需要 100MB 硬盘空间。完整的数据集(即下载器中的`all`)在本书写作期间大约是这个大小的 10 倍,还在不断扩充。 -一旦数据被下载到你的机器,你就可以使用 Python 解释器加载其中一些。第一步是在 Python 提示符后输入一个特殊的命令,告诉解释器去加载一些我们要用的文本:`from nltk.book import *` 。这条语句是说“从 NLTK 的`book` 模块加载所有的东西”。这个`book` 模块包含你阅读本章所需的所有数据。。在输出欢迎信息之后,将会加载几本书的文本(这将需要几秒钟)。下面连同你将看到的输出一起再次列出这条命令。注意拼写和标点符号的正确性,记住不要输入`>>>`。 +一旦数据被下载到你的机器,你就可以使用 Python 解释器加载其中一些。第一步是在 Python 提示符后输入一个特殊的命令,告诉解释器去加载一些我们要用的文本:`from nltk.book import *` 。这条语句是说“从 NLTK 的`book`模块加载所有的东西”。这个`book`模块包含你阅读本章所需的所有数据。。在输出欢迎信息之后,将会加载几本书的文本(这将需要几秒钟)。下面连同你将看到的输出一起再次列出这条命令。注意拼写和标点符号的正确性,记住不要输入`>>>`。 ```py >>> from nltk.book import * @@ -106,7 +106,7 @@ text9: The Man Who Was Thursday by G . K . Chesterton 1908 ## 1.3 搜索文本 -除了阅读文本之外,还有很多方法可以用来研究文本内容。词语索引视角显示一个指定单词的每一次出现,连同一些上下文一起显示。下面我们输入`text1` 后面跟一个点,再输入函数名`concordance`,然后将`"monstrous"` 放在括号里,来查一下 *Moby Dick*《白鲸记》中的词 monstrous: +除了阅读文本之外,还有很多方法可以用来研究文本内容。词语索引视角显示一个指定单词的每一次出现,连同一些上下文一起显示。下面我们输入`text1`后面跟一个点,再输入函数名`concordance`,然后将`"monstrous"`放在括号里,来查一下 *Moby Dick*《白鲸记》中的词 monstrous: ```py >>> text1.concordance("monstrous") @@ -129,7 +129,7 @@ of Whale - Bones ; for Whales of a monstrous size are oftentimes cast up dead u 注意 -**轮到你来:** 尝试搜索其他词;为了方便重复输入,你也许会用到上箭头,Ctrl-上箭头或者 Alt-p 获取之前输入的命令,然后修改要搜索的词。你也可以在我们包含的其他文本上搜索。例如, 使用`text2.concordance("affection")`,搜索 *Sense and Sensibility*《理智与情感》中的 affection。使用`text3.concordance("lived")` 搜索 Genesis《创世纪》找出某人活了多久。你也可以看看`text4`,_Inaugural Address Corpus_《就职演说语料》,回到 1789 年看看那时英语的例子,搜索如 nation, terror,god 这样的词,看看随着时间推移这些词的使用如何不同。我们也包括了`text5`,_NPS Chat Corpus_《NPS 聊天语料库》:你可以在里面搜索一些网络词,如 im ur,lol。(注意这个语料库未经审查!) +**轮到你来:** 尝试搜索其他词;为了方便重复输入,你也许会用到上箭头,Ctrl-上箭头或者 Alt-p 获取之前输入的命令,然后修改要搜索的词。你也可以在我们包含的其他文本上搜索。例如, 使用`text2.concordance("affection")`,搜索 *Sense and Sensibility*《理智与情感》中的 affection。使用`text3.concordance("lived")`搜索 Genesis《创世纪》找出某人活了多久。你也可以看看`text4`,_Inaugural Address Corpus_《就职演说语料》,回到 1789 年看看那时英语的例子,搜索如 nation, terror,god 这样的词,看看随着时间推移这些词的使用如何不同。我们也包括了`text5`,_NPS Chat Corpus_《NPS 聊天语料库》:你可以在里面搜索一些网络词,如 im ur,lol。(注意这个语料库未经审查!) 在你花了一小会儿研究这些文本之后,我们希望你对语言的丰富性和多样性有一个新的认识。在下一章中,你将学习获取更广泛的文本,包括英语以外其他语言的文本。 @@ -158,7 +158,7 @@ a_pretty is_pretty am_glad be_glad a_lucky 注意 -**轮到你来:** 挑选另一对词,使用`similar()` 和`common_contexts()` 函数比较它们在两个不同文本中的用法。 +**轮到你来:** 挑选另一对词,使用`similar()`和`common_contexts()`函数比较它们在两个不同文本中的用法。 自动检测出现在文本中的特定的词,并显示同样上下文中出现的一些词,这只是一个方面。我们也可以判断词在文本中的*位置*:从文本开头算起在它前面有多少词。这个位置信息可以用离散图表示。每一个竖线代表一个单词,每一行代表整个文本。在[1.2](http://www.nltk.org/book/ch01.html#fig-inaugural) 中,我们看到在过去 220 年中的一些显著的词语用法模式(在一个由就职演说语料首尾相连的人为组合的文本中)。可以用下面的方法画出这幅图。你也许会想尝试更多的词(如,liberty,constitution)和不同的文本。你能在看到这幅图之前预测一个词的分布吗?跟以前一样,请保证引号、逗号、中括号及小括号的使用完全正确。 @@ -173,11 +173,11 @@ a_pretty is_pretty am_glad be_glad a_lucky 注意 -**重要事项:** 为了画出这本书中用到的图形,你需要安装 Python 的 NumPy 和 Matplotlib 包。请参阅`http://nltk.org/` 上的安装说明。 +**重要事项:** 为了画出这本书中用到的图形,你需要安装 Python 的 NumPy 和 Matplotlib 包。请参阅`http://nltk.org/`上的安装说明。 注意 -你还可以使用`https://books.google.com/ngrams` 画出词汇随着时间的使用频率。 +你还可以使用`https://books.google.com/ngrams`画出词汇随着时间的使用频率。 现在轻松一下,让我们尝试产生一些刚才看到的不同风格的随机文本。要做到这一点,我们需要输入文本的名字后面跟函数名`generate`。(需要带括号,但括号里没有也什么。) @@ -194,7 +194,7 @@ first born , and Phichol the chief butler unto his son Isaac , she Note -`generate()` 方法在 NLTK 3.0 中不可用,但会在后续版本中恢复。 +`generate()`方法在 NLTK 3.0 中不可用,但会在后续版本中恢复。 ## 1.4 词汇计数 @@ -208,7 +208,7 @@ Note >>> ``` -《创世纪》有 44764 个词和标点符号或者叫“词符”。词符 表示一个我们想要整体对待的字符序列 —— 例如`hairy`,`his` 或 `:)`。当我们计数文本如 to be or not to be 这个短语中词符的个数时,我们计数这些序列出现的次数。因此,我们的例句中出现了 to 和 be 各两次,or 和 not 各一次。然而在例句中只有 4 个不同的词。《创世纪》中有多少不同的词?要用 Python 来回答这个问题,我们处理问题的方法将稍有改变。一个文本词汇表只是它用到的词符的*集合*,因为在集合中所有重复的元素都只算一个。Python 中我们可以使用命令:`set(text3)` 获得`text3` 的词汇表。当你这样做时,屏幕上的很多词会掠过。现在尝试以下操作: +《创世纪》有 44764 个词和标点符号或者叫“词符”。词符 表示一个我们想要整体对待的字符序列 —— 例如`hairy`,`his`或`:)`。当我们计数文本如 to be or not to be 这个短语中词符的个数时,我们计数这些序列出现的次数。因此,我们的例句中出现了 to 和 be 各两次,or 和 not 各一次。然而在例句中只有 4 个不同的词。《创世纪》中有多少不同的词?要用 Python 来回答这个问题,我们处理问题的方法将稍有改变。一个文本词汇表只是它用到的词符的*集合*,因为在集合中所有重复的元素都只算一个。Python 中我们可以使用命令:`set(text3)`获得`text3`的词汇表。当你这样做时,屏幕上的很多词会掠过。现在尝试以下操作: ```py >>> sorted(set(text3)) ❶ @@ -220,7 +220,7 @@ Note >>> ``` -用`sorted()` 包裹起 Python 表达式`set(text3)` [❶](http://www.nltk.org/book/ch01.html#sorted-set),我们得到一个词汇项的排序表,这个表以各种标点符号开始,然后是以 A 开头的词汇。大写单词排在小写单词前面。我们通过求集合中元素的个数间接获得词汇表的大小,再次使用`len`来获得这个数值[❷](http://www.nltk.org/book/ch01.html#len-set)。尽管小说中有 44,764 个词符,但只有 2,789 个不同的单词或“词类型”。一个词类型是指一个词在一个文本中独一无二的出现形式或拼写 —— 也就是说,这个词在词汇表中是唯一的。我们计数的 2,789 个元素中包括标点符号,所以我们把这些叫做唯一元素类型而不是词类型。 +用`sorted()`包裹起 Python 表达式`set(text3)` [❶](http://www.nltk.org/book/ch01.html#sorted-set),我们得到一个词汇项的排序表,这个表以各种标点符号开始,然后是以 A 开头的词汇。大写单词排在小写单词前面。我们通过求集合中元素的个数间接获得词汇表的大小,再次使用`len`来获得这个数值[❷](http://www.nltk.org/book/ch01.html#len-set)。尽管小说中有 44,764 个词符,但只有 2,789 个不同的单词或“词类型”。一个词类型是指一个词在一个文本中独一无二的出现形式或拼写 —— 也就是说,这个词在词汇表中是唯一的。我们计数的 2,789 个元素中包括标点符号,所以我们把这些叫做唯一元素类型而不是词类型。 现在,让我们对文本词汇丰富度进行测量。下一个例子向我们展示,不同的单词数目只是单词总数的 6%,或者每个单词平均被使用了 16 次(记住,如果你使用的是 Python 2,请在开始输入`from __future__ import division`)。 @@ -242,9 +242,9 @@ Note 注 -**轮到你来:** `text5` 中 lol 出现了多少次?它占文本全部词数的百分比是多少? +**轮到你来:** `text5`中 lol 出现了多少次?它占文本全部词数的百分比是多少? -你也许想要对几个文本重复这些计算,但重新输入公式是乏味的。你可以自己命名一个任务,如“lexical_diversity”或“percentage”,然后用一个代码块关联它。现在,你只需输入一个很短的名字就可以代替一行或多行 Python 代码,而且你想用多少次就用多少次。执行一个任务的代码段叫做一个函数,我们使用关键字`def` 给函数定义一个简短的名字。下面的例子演示如何定义两个新的函数,`lexical_diversity()` 和`percentage()`: +你也许想要对几个文本重复这些计算,但重新输入公式是乏味的。你可以自己命名一个任务,如“lexical_diversity”或“percentage”,然后用一个代码块关联它。现在,你只需输入一个很短的名字就可以代替一行或多行 Python 代码,而且你想用多少次就用多少次。执行一个任务的代码段叫做一个函数,我们使用关键字`def`给函数定义一个简短的名字。下面的例子演示如何定义两个新的函数,`lexical_diversity()`和`percentage()`: ```py >>> def lexical_diversity(text): ❶ @@ -257,11 +257,11 @@ Note 小心! -当遇到第一行末尾的冒号后,Python 解释器提示符由`>>>` 变为`...` 。`...`提示符表示 Python 期望在后面是一个缩进代码块 。缩进是输入四个空格还是敲击 Tab 键,这由你决定。要结束一个缩进代码段,只需输入一个空行。 +当遇到第一行末尾的冒号后,Python 解释器提示符由`>>>`变为`...` 。`...`提示符表示 Python 期望在后面是一个缩进代码块 。缩进是输入四个空格还是敲击 Tab 键,这由你决定。要结束一个缩进代码段,只需输入一个空行。 -`lexical_diversity()` [❶](http://www.nltk.org/book/ch01.html#fun-parameter1)的定义中,我们指定了一个`text` 参数。这个参数是我们想要计算词汇多样性的实际文本的一个“占位符”,并在用到这个函数的时候出现在将要运行的代码块中 [❷](http://www.nltk.org/book/ch01.html#locvar)。类似地,`percentage()` 定义了两个参数,`count` 和`total` [❸](http://www.nltk.org/book/ch01.html#fun-parameter2)。 +`lexical_diversity()` [❶](http://www.nltk.org/book/ch01.html#fun-parameter1)的定义中,我们指定了一个`text`参数。这个参数是我们想要计算词汇多样性的实际文本的一个“占位符”,并在用到这个函数的时候出现在将要运行的代码块中 [❷](http://www.nltk.org/book/ch01.html#locvar)。类似地,`percentage()`定义了两个参数,`count`和`total` [❸](http://www.nltk.org/book/ch01.html#fun-parameter2)。 -只要 Python 知道了`lexical_diversity()` 和`percentage()` 是指定代码段的名字,我们就可以继续使用这些函数: +只要 Python 知道了`lexical_diversity()`和`percentage()`是指定代码段的名字,我们就可以继续使用这些函数: ```py >>> lexical_diversity(text3) @@ -275,9 +275,9 @@ Note >>> ``` -扼要重述一下,我们使用或调用一个如`lexical_diversity()` 这样的函数,只要输入它的名字后面跟一个左括号,再输入文本名字,然后是右括号。这些括号经常出现,它们的作用是分割任务名—— 如`lexical_diversity()`,与任务将要处理的数据 ——如`text3`。调用函数时放在参数位置的数据值叫做函数的实参。 +扼要重述一下,我们使用或调用一个如`lexical_diversity()`这样的函数,只要输入它的名字后面跟一个左括号,再输入文本名字,然后是右括号。这些括号经常出现,它们的作用是分割任务名—— 如`lexical_diversity()`,与任务将要处理的数据 ——如`text3`。调用函数时放在参数位置的数据值叫做函数的实参。 -在本章中你已经遇到了几个函数,如`len()`, `set()` 和`sorted()`。通常我们会在函数名后面加一对空括号,像`len()`中的那样,这只是为了表明这是一个函数而不是其他的 Python 表达式。函数是编程中的一个重要概念,我们在一开始提到它们,是为了让新同学体会编程的强大和富有创造力。如果你现在觉得有点混乱,请不要担心。 +在本章中你已经遇到了几个函数,如`len()`, `set()`和`sorted()`。通常我们会在函数名后面加一对空括号,像`len()`中的那样,这只是为了表明这是一个函数而不是其他的 Python 表达式。函数是编程中的一个重要概念,我们在一开始提到它们,是为了让新同学体会编程的强大和富有创造力。如果你现在觉得有点混乱,请不要担心。 稍后我们将看到如何使用函数列表显示数据,像表[1.1](http://www.nltk.org/book/ch01.html#tab-brown-types)显示的那样。表的每一行将包含不同数据的相同的计算,我们用函数来做这种重复性的工作。 @@ -302,7 +302,7 @@ Note >>> ``` -还定义了其它几个列表,分别对应每个文本开始的句子,`sent2` … `sent9`。在这里我们检查其中的两个;你可以自己在 Python 解释器中尝试其余的(如果你得到一个错误说`sent2` 没有定义,你需要先输入`from nltk.book import *`)。 +还定义了其它几个列表,分别对应每个文本开始的句子,`sent2` … `sent9`。在这里我们检查其中的两个;你可以自己在 Python 解释器中尝试其余的(如果你得到一个错误说`sent2`没有定义,你需要先输入`from nltk.book import *`)。 ```py >>> sent2 @@ -350,7 +350,7 @@ Note ## 2.2 索引列表 -正如我们已经看到的,Python 中的一个文本是一个单词的列表,用括号和引号的组合来表示。就像处理一页普通的文本,我们可以使用`len(text1)` 计算`text1`的词数,使用`text1.count('heaven')`计算一个文本中出现的特定的词,如`'heaven'`。 +正如我们已经看到的,Python 中的一个文本是一个单词的列表,用括号和引号的组合来表示。就像处理一页普通的文本,我们可以使用`len(text1)`计算`text1`的词数,使用`text1.count('heaven')`计算一个文本中出现的特定的词,如`'heaven'`。 稍微花些耐心,我们可以挑选出打印出来的文本中的第 1 个、第 173 个或第 14278 个词。类似的,我们也可以通过它在列表中出现的次序找出一个 Python 列表的元素。表示这个位置的数字叫做这个元素的索引。在文本名称后面的方括号里写下索引,Python 就会表示出文本中这个索引处如`173`的元素: @@ -394,7 +394,7 @@ Note >>> ``` -请注意,索引从零开始:`sent` 第 0 个元素写作`sent[0]`,是第一个单词`'word1'`,而`sent` 的第 9 个元素是`'word10'`。原因很简单:Python 从计算机内存中的列表获取内容的时候,它已经位于第一个元素;我们要告诉它向前多少个元素。因此,向前 0 个元素使它留在第一个元素上。 +请注意,索引从零开始:`sent`第 0 个元素写作`sent[0]`,是第一个单词`'word1'`,而`sent`的第 9 个元素是`'word10'`。原因很简单:Python 从计算机内存中的列表获取内容的时候,它已经位于第一个元素;我们要告诉它向前多少个元素。因此,向前 0 个元素使它留在第一个元素上。 注意 @@ -410,9 +410,9 @@ IndexError: list index out of range >>> ``` -这次不是一个语法错误,因为程序片段在语法上是正确的。相反,它是一个运行时错误,它会产生一个`回溯`消息显示错误的上下文、错误的名称:`IndexError` 以及简要的解释说明。 +这次不是一个语法错误,因为程序片段在语法上是正确的。相反,它是一个运行时错误,它会产生一个`回溯`消息显示错误的上下文、错误的名称:`IndexError`以及简要的解释说明。 -让我们再次使用构造的句子仔细看看切片。这里我们发现切片`5:8` 包含`sent` 中索引为 5,6 和 7 的元素: +让我们再次使用构造的句子仔细看看切片。这里我们发现切片`5:8`包含`sent`中索引为 5,6 和 7 的元素: ```py >>> sent[5:8] @@ -426,7 +426,7 @@ IndexError: list index out of range >>> ``` -按照惯例,`m:n` 表示元素 m…n-1。正如下一个例子显示的那样,如果切片从列表第一个元素开始,我们可以省略第一个数字[❶](http://www.nltk.org/book/ch01.html#slice2), 如果切片到列表最后一个元素处结尾,我们可以省略第二个数字 [❷](http://www.nltk.org/book/ch01.html#slice3): +按照惯例,`m:n`表示元素 m…n-1。正如下一个例子显示的那样,如果切片从列表第一个元素开始,我们可以省略第一个数字[❶](http://www.nltk.org/book/ch01.html#slice2), 如果切片到列表最后一个元素处结尾,我们可以省略第二个数字 [❷](http://www.nltk.org/book/ch01.html#slice3): ```py >>> sent[:3] ❶ @@ -441,7 +441,7 @@ IndexError: list index out of range >>> ``` -我们可以通过赋值给它的索引值来修改列表中的元素。在接下来的例子中,我们把`sent[0]` 放在等号左侧[❶](http://www.nltk.org/book/ch01.html#list-assignment)。我们也可以用新内容替换掉一整个片段[❷](http://www.nltk.org/book/ch01.html#slice-assignment)。最后一个尝试报错的原因是这个链表只有四个元素而要获取其后面的元素就产生了错误[❸](http://www.nltk.org/book/ch01.html#list-error)。 +我们可以通过赋值给它的索引值来修改列表中的元素。在接下来的例子中,我们把`sent[0]`放在等号左侧[❶](http://www.nltk.org/book/ch01.html#list-assignment)。我们也可以用新内容替换掉一整个片段[❷](http://www.nltk.org/book/ch01.html#slice-assignment)。最后一个尝试报错的原因是这个链表只有四个元素而要获取其后面的元素就产生了错误[❸](http://www.nltk.org/book/ch01.html#list-error)。 ```py >>> sent[0] = 'First' ❶ @@ -464,7 +464,7 @@ IndexError: list index out of range ## 2.3 变量 -从第 1 节一开始,你已经访问过名为`text1`, `text2` 等的文本。像这样只输入简短的名字来引用一本 250,000 字的书节省了很多打字时间。一般情况下,我们可以对任何我们关心的计算命名。我们在前面的小节中已经这样做了,例如定义一个变量变量 `sent1`,如下所示: +从第 1 节一开始,你已经访问过名为`text1`, `text2`等的文本。像这样只输入简短的名字来引用一本 250,000 字的书节省了很多打字时间。一般情况下,我们可以对任何我们关心的计算命名。我们在前面的小节中已经这样做了,例如定义一个变量变量`sent1`,如下所示: ```py >>> sent1 = ['Call', 'me', 'Ishmael', '.'] @@ -489,9 +489,9 @@ IndexError: list index out of range 注意 -请注意,在前面的例子中,我们将`my_sent` 的定义分成两行。Python 表达式可以被分割成多行,只要它出现在任何一种括号内。Python 使用"`...`"提示符表示期望更多的输入。在这些连续的行中有多少缩进都没有关系,只是加入缩进通常会便于阅读。 +请注意,在前面的例子中,我们将`my_sent`的定义分成两行。Python 表达式可以被分割成多行,只要它出现在任何一种括号内。Python 使用"`...`"提示符表示期望更多的输入。在这些连续的行中有多少缩进都没有关系,只是加入缩进通常会便于阅读。 -最好是选择有意义的变量名,它能提醒你代码的含义,也帮助别人读懂你的 Python 代码。Python 并不会理解这些名称的意义;它只是盲目的服从你的指令,如果你输入一些令人困惑的代码,例如`one = 'two'` 或`two = 3`,它也不会反对。唯一的限制是变量名不能是 Python 的保留字,如`def`, `if`, `not`, 和`import`。如果你使用了保留字,Python 会产生一个语法错误: +最好是选择有意义的变量名,它能提醒你代码的含义,也帮助别人读懂你的 Python 代码。Python 并不会理解这些名称的意义;它只是盲目的服从你的指令,如果你输入一些令人困惑的代码,例如`one = 'two'`或`two = 3`,它也不会反对。唯一的限制是变量名不能是 Python 的保留字,如`def`, `if`, `not`, 和`import`。如果你使用了保留字,Python 会产生一个语法错误: ```py >>> not = 'Camelot' @@ -502,7 +502,7 @@ SyntaxError: invalid syntax >>> ``` -我们将经常使用变量来保存计算的中间步骤,尤其是当这样做使代码更容易读懂时。因此,`len(set(text1))` 也可以写作: +我们将经常使用变量来保存计算的中间步骤,尤其是当这样做使代码更容易读懂时。因此,`len(set(text1))`也可以写作: ```py >>> vocab = set(text1) @@ -514,7 +514,7 @@ SyntaxError: invalid syntax 小心! -为 Python 变量选择名称(标识符)时请注意。首先,应该以字母开始,后面跟数字(`0` 到`9`)或字母。因此,`abc23` 是好的,但是`23abc` 会导致一个语法错误。名称是大小写敏感的,这意味着`myVar` 和`myvar` 是不同的变量。变量名不能包含空格,但可以用下划线把单词分开,例如`my_var`。注意不要插入连字符来代替下划线:`my-var` 不对,因为 Python 会把"`-`"解释为减号。 +为 Python 变量选择名称(标识符)时请注意。首先,应该以字母开始,后面跟数字(`0`到`9`)或字母。因此,`abc23`是好的,但是`23abc`会导致一个语法错误。名称是大小写敏感的,这意味着`myVar`和`myvar`是不同的变量。变量名不能包含空格,但可以用下划线把单词分开,例如`my_var`。注意不要插入连字符来代替下划线:`my-var`不对,因为 Python 会把"`-`"解释为减号。 ## 2.4 字符串 @@ -577,7 +577,7 @@ what output do you expect here? 图 3.1:计数一个文本中出现的词(频率分布) -图[3.1](http://www.nltk.org/book/ch01.html#fig-tally) 中的表被称为频率分布,它告诉我们在文本中的每一个词项的频率。(一般情况下,它能计数任何观察得到的事件。)这是一个“分布”因为它告诉我们文本中单词词符的总数是如何分布在词项中的。因为我们经常需要在语言处理中使用频率分布,NLTK 中内置了它们。让我们使用`FreqDist` 寻找《白鲸记》中最常见的 50 个词: +图[3.1](http://www.nltk.org/book/ch01.html#fig-tally) 中的表被称为频率分布,它告诉我们在文本中的每一个词项的频率。(一般情况下,它能计数任何观察得到的事件。)这是一个“分布”因为它告诉我们文本中单词词符的总数是如何分布在词项中的。因为我们经常需要在语言处理中使用频率分布,NLTK 中内置了它们。让我们使用`FreqDist`寻找《白鲸记》中最常见的 50 个词: ```py >>> fdist1 = FreqDist(text1) ❶ @@ -599,19 +599,19 @@ what output do you expect here? >>> ``` -第一次调用`FreqDist`时,传递文本的名称作为参数[❶](http://www.nltk.org/book/ch01.html#freq-dist-call)。我们可以看到已经被计算出来的《白鲸记》中的总的词数(“outcomes”)—— 260,819[❷](http://www.nltk.org/book/ch01.html#freq-dist-inspect)。表达式`most_common(50)` 给出文本中 50 个出现频率最高的单词类型[❸](http://www.nltk.org/book/ch01.html#freq-dist-most-common)。 +第一次调用`FreqDist`时,传递文本的名称作为参数[❶](http://www.nltk.org/book/ch01.html#freq-dist-call)。我们可以看到已经被计算出来的《白鲸记》中的总的词数(“outcomes”)—— 260,819[❷](http://www.nltk.org/book/ch01.html#freq-dist-inspect)。表达式`most_common(50)`给出文本中 50 个出现频率最高的单词类型[❸](http://www.nltk.org/book/ch01.html#freq-dist-most-common)。 注意 **轮到你来:**使用`text2`尝试前面的频率分布的例子。注意正确使用括号和大写字母。如果你得到一个错误消息`NameError: name 'FreqDist' is not defined`,你需要在一开始输入`from nltk.book import *` -上一个例子中是否有什么词有助于我们把握这个文本的主题或风格呢?只有一个词,whale,稍微有些信息量!它出现了超过 900 次。其余的词没有告诉我们关于文本的信息;它们只是“管道”英语。这些词在文本中占多少比例?我们可以产生一个这些词汇的累积频率图,使用`fdist1.plot(50, cumulative=True)` 来生成[3.2](http://www.nltk.org/book/ch01.html#fig-fdist-moby) 中的图。这 50 个词占了书的将近一半! +上一个例子中是否有什么词有助于我们把握这个文本的主题或风格呢?只有一个词,whale,稍微有些信息量!它出现了超过 900 次。其余的词没有告诉我们关于文本的信息;它们只是“管道”英语。这些词在文本中占多少比例?我们可以产生一个这些词汇的累积频率图,使用`fdist1.plot(50, cumulative=True)`来生成[3.2](http://www.nltk.org/book/ch01.html#fig-fdist-moby) 中的图。这 50 个词占了书的将近一半! ![Images/fdist-moby.png](Images/513df73dfd52feca2c96a86dcc261c8b.jpg) 图 3.2:《白鲸记》中 50 个最常用词的累积频率图:这些词占了所有词符的将近一半。 -如果高频词对我们没有帮助,那些只出现了一次的词(所谓的 hapaxes)又如何呢?输入`fdist1.hapaxes()` 来查看它们。这个列表包含 lexicographer, cetological, contraband, expostulations 以及其他 9,000 多个。看来低频词太多了,没看到上下文我们很可能有一半的 hapaxes 猜不出它们的意义!既然高频词和低频词都没有帮助,我们需要尝试其他的办法。 +如果高频词对我们没有帮助,那些只出现了一次的词(所谓的 hapaxes)又如何呢?输入`fdist1.hapaxes()`来查看它们。这个列表包含 lexicographer, cetological, contraband, expostulations 以及其他 9,000 多个。看来低频词太多了,没看到上下文我们很可能有一半的 hapaxes 猜不出它们的意义!既然高频词和低频词都没有帮助,我们需要尝试其他的办法。 ## 3.2 细粒度的选择词 @@ -630,13 +630,13 @@ what output do you expect here? >>> ``` -对于词汇表`V` 中的每一个词`w`,我们检查`len(w)` 是否大于 15;所有其他词汇将被忽略。我们将在后面更仔细的讨论这里的语法。 +对于词汇表`V`中的每一个词`w`,我们检查`len(w)`是否大于 15;所有其他词汇将被忽略。我们将在后面更仔细的讨论这里的语法。 注意 **轮到你来:** 在 Python 解释器中尝试上面的表达式,改变文本和长度条件做一些实验。如果改变变量名,你的结果会产生什么变化吗,如使用`[word for word in vocab if ...]`? -让我们回到寻找文本特征词汇的任务上来。请注意,`text4` 中的长词反映国家主题 — constitutionally, transcontinental — 而`text5` 中的长词反映的不是真正的内容 boooooooooooglyyyyyy 和 yuuuuuuuuuuuummmmmmmmmmmm。我们是否已经成功的自动提取出文本的特征词汇呢?好的,这些很长的词通常是 hapaxes(即唯一的),也许找出*频繁出现的*长词会更好。这样看起来更有前途,因为这样忽略了短高频词(如 the)和长低频词(如 antiphilosophists)。以下是聊天语料库中所有长度超过 7 个字符,且出现次数超过 7 次的词: +让我们回到寻找文本特征词汇的任务上来。请注意,`text4`中的长词反映国家主题 — constitutionally, transcontinental — 而`text5`中的长词反映的不是真正的内容 boooooooooooglyyyyyy 和 yuuuuuuuuuuuummmmmmmmmmmm。我们是否已经成功的自动提取出文本的特征词汇呢?好的,这些很长的词通常是 hapaxes(即唯一的),也许找出*频繁出现的*长词会更好。这样看起来更有前途,因为这样忽略了短高频词(如 the)和长低频词(如 antiphilosophists)。以下是聊天语料库中所有长度超过 7 个字符,且出现次数超过 7 次的词: ```py >>> fdist5 = FreqDist(text5) @@ -648,7 +648,7 @@ what output do you expect here? >>> ``` -注意我们是如何使用两个条件:`len(w) > 7` 保证词长都超过七个字母,`fdist5[w] > 7` 保证这些词出现超过 7 次。最后,我们已成功地自动识别出与文本内容相关的高频词。这很小的一步却是一个重要的里程碑:一小块代码,处理数以万计的词,产生一些有信息量的输出。 +注意我们是如何使用两个条件:`len(w) > 7`保证词长都超过七个字母,`fdist5[w] > 7`保证这些词出现超过 7 次。最后,我们已成功地自动识别出与文本内容相关的高频词。这很小的一步却是一个重要的里程碑:一小块代码,处理数以万计的词,产生一些有信息量的输出。 ## 3.3 词语搭配和双连词 @@ -664,9 +664,9 @@ what output do you expect here? 注意 -如果上面省掉`list()`,只输入`bigrams(['more', ...])`,你将看到`` 的输出形式。这是 Python 的方式表示它已经准备好要计算一个序列,在这里是双连词。现在,你只需要知道告诉 Python 使用`list()`将它转换成一个列表。 +如果上面省掉`list()`,只输入`bigrams(['more', ...])`,你将看到``的输出形式。这是 Python 的方式表示它已经准备好要计算一个序列,在这里是双连词。现在,你只需要知道告诉 Python 使用`list()`将它转换成一个列表。 -在这里我们看到词对 than-done 是一个双连词,在 Python 中写成`('than', 'done')`。现在,搭配基本上就是频繁的双连词,除非我们更加注重包含不常见词的的情况。特别的,我们希望找到比我们基于单个词的频率预期得到的更频繁出现的双连词。`collocations()` 函数为我们做这些。我们将在以后看到它是如何工作。 +在这里我们看到词对 than-done 是一个双连词,在 Python 中写成`('than', 'done')`。现在,搭配基本上就是频繁的双连词,除非我们更加注重包含不常见词的的情况。特别的,我们希望找到比我们基于单个词的频率预期得到的更频繁出现的双连词。`collocations()`函数为我们做这些。我们将在以后看到它是如何工作。 ```py >>> text4.collocations() @@ -702,7 +702,7 @@ FreqDist({3: 50223, 1: 47933, 4: 42345, 2: 38513, 5: 26597, 6: 17111, 7: 14399, >>> ``` -我们以导出`text1` 中每个词的长度的列表开始[❶](http://www.nltk.org/book/ch01.html#word-lengths),然后`FreqDist` 计数列表中每个数字出现的次数[❷](http://www.nltk.org/book/ch01.html#freq-word-lengths)。结果[❸](http://www.nltk.org/book/ch01.html#freq-word-lengths-size) 是一个包含 25 万左右个元素的分布,每一个元素是一个数字,对应文本中一个词标识符。但是只有 20 个不同的元素,从 1 到 20,因为只有 20 个不同的词长。也就是说,有由 1 个字符,2 个字符,...,20 个字符组成的词,而没有由 21 个或更多字符组成的词。有人可能会问不同长度的词的频率是多少?(例如,文本中有多少长度为 4 的词?长度为 5 的词是否比长度为 4 的词多?等等)。下面我们回答这个问题: +我们以导出`text1`中每个词的长度的列表开始[❶](http://www.nltk.org/book/ch01.html#word-lengths),然后`FreqDist`计数列表中每个数字出现的次数[❷](http://www.nltk.org/book/ch01.html#freq-word-lengths)。结果[❸](http://www.nltk.org/book/ch01.html#freq-word-lengths-size) 是一个包含 25 万左右个元素的分布,每一个元素是一个数字,对应文本中一个词标识符。但是只有 20 个不同的元素,从 1 到 20,因为只有 20 个不同的词长。也就是说,有由 1 个字符,2 个字符,...,20 个字符组成的词,而没有由 21 个或更多字符组成的词。有人可能会问不同长度的词的频率是多少?(例如,文本中有多少长度为 4 的词?长度为 5 的词是否比长度为 4 的词多?等等)。下面我们回答这个问题: ```py >>> fdist.most_common() @@ -785,7 +785,7 @@ NLTK 频率分布类中定义的函数 >>> ``` -这些表达式形式为`[f(w) for ...]` 或`[w.f() for ...]`,其中`f` 是一个函数,用来计算词长,或把字母转换为大写。现阶段你还不需要理解两种表示方法:`f(w)` 和`w.f()`。而只需学习对列表上的所有元素执行相同的操作的这种 Python 习惯用法。在前面的例子中,遍历`text1`中的每一个词,一个接一个的赋值给变量`w` 并在变量上执行指定的操作。 +这些表达式形式为`[f(w) for ...]`或`[w.f() for ...]`,其中`f`是一个函数,用来计算词长,或把字母转换为大写。现阶段你还不需要理解两种表示方法:`f(w)`和`w.f()`。而只需学习对列表上的所有元素执行相同的操作的这种 Python 习惯用法。在前面的例子中,遍历`text1`中的每一个词,一个接一个的赋值给变量`w`并在变量上执行指定的操作。 注意 @@ -817,7 +817,7 @@ NLTK 频率分布类中定义的函数 ## 4.3 嵌套代码块 -大多数编程语言允许我们在条件表达式或者`if`语句条件满足时执行代码块。我们在`[w for w in sent7 if len(w) < 4]` 这样的代码中已经看到条件测试的例子。在下面的程序中,我们创建一个叫`word`的变量包含字符串值`'cat'`。`if` 语句中检查`len(word) < 5` 是否为真。它确实为真,所以`if` 语句的代码块被调用,`print` 语句被执行,向用户显示一条消息。别忘了要缩进,在`print`语句前输入四个空格。 +大多数编程语言允许我们在条件表达式或者`if`语句条件满足时执行代码块。我们在`[w for w in sent7 if len(w) < 4]`这样的代码中已经看到条件测试的例子。在下面的程序中,我们创建一个叫`word`的变量包含字符串值`'cat'`。`if`语句中检查`len(word) < 5`是否为真。它确实为真,所以`if`语句的代码块被调用,`print`语句被执行,向用户显示一条消息。别忘了要缩进,在`print`语句前输入四个空格。 ```py >>> word = 'cat' @@ -860,7 +860,7 @@ Ishmael >>> ``` -这叫做循环,因为 Python 以循环的方式执行里面的代码。它以`word = 'Call'`赋值开始,使用变量`word` 命名列表的第一个元素。然后,显示`word`的值给用户。接下来它回到`for`语句,执行`word = 'me'`赋值,然后显示这个新值给用户,以此类推。它以这种方式不断运行,直到列表中所有项都被处理完。 +这叫做循环,因为 Python 以循环的方式执行里面的代码。它以`word = 'Call'`赋值开始,使用变量`word`命名列表的第一个元素。然后,显示`word`的值给用户。接下来它回到`for`语句,执行`word = 'me'`赋值,然后显示这个新值给用户,以此类推。它以这种方式不断运行,直到列表中所有项都被处理完。 ## 4.4 条件循环 @@ -877,7 +877,7 @@ Ishmael >>> ``` -你会发现在`if` 和`for`语句所在行末尾——缩进开始之前——有一个冒号。事实上,所有的 Python 控制结构都以冒号结尾。冒号表示当前语句与后面的缩进块有关联。 +你会发现在`if`和`for`语句所在行末尾——缩进开始之前——有一个冒号。事实上,所有的 Python 控制结构都以冒号结尾。冒号表示当前语句与后面的缩进块有关联。 我们也可以指定当`if`语句的条件不满足时采取的行动。在这里,我们看到`elif`(else if)语句和`else`语句。请注意,这些在缩进代码前也有冒号。 @@ -929,7 +929,7 @@ conscientious conscientiously deceitful deceive ... >>> sorted(w.lower() for w in set(text1)) ``` -* ◑ 下面两个测试的差异是什么:`w.isupper()` 和`not w.islower()`? +* ◑ 下面两个测试的差异是什么:`w.isupper()`和`not w.islower()`? * ◑ 写一个切片表达式提取`text2`中最后两个词。 @@ -945,7 +945,7 @@ conscientious conscientiously deceitful deceive ... 4. 除了首字母外是全部小写字母的词(即`titlecase`)* ◑ 定义`sent`为一个单词列表:`['she', 'sells', 'sea', 'shells', 'by', 'the', 'sea', 'shore']`。编写代码执行以下任务: 1. 输出所有 sh 开头的单词 - 2. 输出所有长度超过 4 个字符的词* ◑ 下面的 Python 代码是做什么的?`sum(len(w) for w in text1)` 你可以用它来算出一个文本的平均字长吗? + 2. 输出所有长度超过 4 个字符的词* ◑ 下面的 Python 代码是做什么的?`sum(len(w) for w in text1)`你可以用它来算出一个文本的平均字长吗? * ◑ 定义一个名为`vocab_size(text)`的函数,以文本作为唯一的参数,返回文本的词汇量。 diff --git a/11.md b/11.md index 0a6a2b1..b7c0057 100644 --- a/11.md +++ b/11.md @@ -372,7 +372,7 @@ sleep: wake Python 的 ElementTree 模块提供了一种方便的方式访问存储在 XML 文件中的数据。ElementTree 是 Python 标准库(自从 Python 2.5)的一部分,也作为 NLTK 的一部分提供,以防你在使用 Python 2.4。 -我们将使用 XML 格式的莎士比亚戏剧集来说明 ElementTree 的使用方法。让我们加载 XML 文件并检查原始数据,首先在文件的顶部[❶](./ch11.html#top-of-file),在那里我们看到一些 XML 头和一个名为`play.dtd`的模式,接着是根元素 `PLAY`。我们从 Act 1[❷](./ch11.html#start-act-one)再次获得数据。(输出中省略了一些空白行。) +我们将使用 XML 格式的莎士比亚戏剧集来说明 ElementTree 的使用方法。让我们加载 XML 文件并检查原始数据,首先在文件的顶部[❶](./ch11.html#top-of-file),在那里我们看到一些 XML 头和一个名为`play.dtd`的模式,接着是根元素`PLAY`。我们从 Act 1[❷](./ch11.html#start-act-one)再次获得数据。(输出中省略了一些空白行。) ```py >>> merchant_file = nltk.data.find('corpora/shakespeare/merchant.xml') diff --git a/2.md b/2.md index 00876fa..4601471 100644 --- a/2.md +++ b/2.md @@ -170,7 +170,7 @@ can: 94 could: 87 may: 93 might: 38 must: 53 will: 389 注意 -我们需要包包含`结束 = ' '` 以让 print 函数将其输出放在单独的一行。 +我们需要包包含`结束 = ' '`以让 print 函数将其输出放在单独的一行。 注意 @@ -253,7 +253,7 @@ science_fiction 16 49 4 12 8 16 请注意,每个文本的年代都出现在它的文件名中。要从文件名中获得年代,我们使用`fileid[:4]`提取前四个字符。 -让我们来看看词汇 America 和 citizen 随时间推移的使用情况。下面的代码使用`w.lower()` [❶](./ch02.html#lowercase-startswith)将就职演说语料库中的词汇转换成小写,然后用`startswith()` [❶](./ch02.html#lowercase-startswith)检查它们是否以“目标”词汇`america` 或`citizen`开始。因此,它会计算如 American's 和 Citizens 等词。我们将在第 2 节学习条件频率分布,现在只考虑输出,如图[1.1](./ch02.html#fig-inaugural2)所示。 +让我们来看看词汇 America 和 citizen 随时间推移的使用情况。下面的代码使用`w.lower()` [❶](./ch02.html#lowercase-startswith)将就职演说语料库中的词汇转换成小写,然后用`startswith()` [❶](./ch02.html#lowercase-startswith)检查它们是否以“目标”词汇`america`或`citizen`开始。因此,它会计算如 American's 和 Citizens 等词。我们将在第 2 节学习条件频率分布,现在只考虑输出,如图[1.1](./ch02.html#fig-inaugural2)所示。 ```py >>> cfd = nltk.ConditionalFreqDist( @@ -267,7 +267,7 @@ science_fiction 16 49 4 12 8 16 ![Images/4cdc400cf76b0354304e01aeb894877b.jpg](Images/4cdc400cf76b0354304e01aeb894877b.jpg) -图 1.1:条件频率分布图:计数就职演说语料库中所有以`america` 或`citizen`开始的词;每个演讲单独计数;这样就能观察出随时间变化用法上的演变趋势;计数没有与文档长度进行归一化处理。 +图 1.1:条件频率分布图:计数就职演说语料库中所有以`america`或`citizen`开始的词;每个演讲单独计数;这样就能观察出随时间变化用法上的演变趋势;计数没有与文档长度进行归一化处理。 ## 1.6 标注文本语料库 @@ -398,7 +398,7 @@ NLTK 中定义的基本语料库函数:使用`help(nltk.corpus.reader)`可以 ## 2.2 按文体计数词汇 -在[1](./ch02.html#sec-extracting-text-from-corpora)中,我们看到一个条件频率分布,其中条件为布朗语料库的每一节,并对每节计数词汇。`FreqDist()`以一个简单的列表作为输入,`ConditionalFreqDist()` 以一个配对列表作为输入。 +在[1](./ch02.html#sec-extracting-text-from-corpora)中,我们看到一个条件频率分布,其中条件为布朗语料库的每一节,并对每节计数词汇。`FreqDist()`以一个简单的列表作为输入,`ConditionalFreqDist()`以一个配对列表作为输入。 ```py >>> from nltk.corpus import brown @@ -536,7 +536,7 @@ print('Monty Python') 你也可以输入`from monty import *`,它将做同样的事情。 -从现在起,你可以选择使用交互式解释器或文本编辑器来创建你的程序。使用解释器测试你的想法往往比较方便,修改一行代码直到达到你期望的效果。测试好之后,你就可以将代码粘贴到文本编辑器(去除所有`>>>` 和`...`提示符),继续扩展它。给文件一个小而准确的名字,使用所有的小写字母,用下划线分割词汇,使用`.py`文件名后缀,例如`monty_python.py`。 +从现在起,你可以选择使用交互式解释器或文本编辑器来创建你的程序。使用解释器测试你的想法往往比较方便,修改一行代码直到达到你期望的效果。测试好之后,你就可以将代码粘贴到文本编辑器(去除所有`>>>`和`...`提示符),继续扩展它。给文件一个小而准确的名字,使用所有的小写字母,用下划线分割词汇,使用`.py`文件名后缀,例如`monty_python.py`。 注意 @@ -863,7 +863,7 @@ KeyError: 'blog' 'few', 'other', 'one', 'two', 'three', 'four', 'five', 'big', 'long', 'wide', ...] ``` -我们可以通过在`entries()` 方法中指定一个语言列表来访问多语言中的同源词。更进一步,我们可以把它转换成一个简单的词典(我们将在[3](./ch05.html#sec-dictionaries)学到`dict()`函数)。 +我们可以通过在`entries()`方法中指定一个语言列表来访问多语言中的同源词。更进一步,我们可以把它转换成一个简单的词典(我们将在[3](./ch05.html#sec-dictionaries)学到`dict()`函数)。 ```py >>> fr2en = swadesh.entries(['fr', 'en']) @@ -1190,7 +1190,7 @@ WordNet 同义词集的集合上定义的相似度能够包括上面的概念。 用于创建标注的文本语料库的好工具叫做 Brat,可从`http://brat.nlplab.org/`访问。 -这些语料库和许多其他语言资源使用 OLAC 元数据格式存档,可以通过 `http://www.language-archives.org/`上的 OLAC 主页搜索到。Corpora List 是一个讨论语料库内容的邮件列表,你可以通过搜索列表档案来找到资源或发布资源到列表中。*Ethnologue* 是最完整的世界上的语言的清单,`http://www.ethnologue.com/`。7000 种语言中只有几十中有大量适合 NLP 使用的数字资源。 +这些语料库和许多其他语言资源使用 OLAC 元数据格式存档,可以通过`http://www.language-archives.org/`上的 OLAC 主页搜索到。Corpora List 是一个讨论语料库内容的邮件列表,你可以通过搜索列表档案来找到资源或发布资源到列表中。*Ethnologue* 是最完整的世界上的语言的清单,`http://www.ethnologue.com/`。7000 种语言中只有几十中有大量适合 NLP 使用的数字资源。 本章触及语料库语言学领域。在这一领域的其他有用的书籍包括[(Biber, Conrad, & Reppen, 1998)](./bibliography.html#biber1998), [(McEnery, 2006)](./bibliography.html#mcenery2006), [(Meyer, 2002)](./bibliography.html#meyer2002), [(Sampson & McCarthy, 2005)](./bibliography.html#sampson2005), [(Scott & Tribble, 2006)](./bibliography.html#scott2006)。在语言学中海量数据分析的深入阅读材料有:[(Baayen, 2008)](./bibliography.html#baayen2008), [(Gries, 2009)](./bibliography.html#gries2009), [(Woods, Fletcher, & Hughes, 1986)](./bibliography.html#woods1986)。 diff --git a/3.md b/3.md index 9e3f999..825d40f 100644 --- a/3.md +++ b/3.md @@ -110,7 +110,7 @@ Project Gutenberg; Dmitri Prokofitch; Andrey Semyonovitch; Hay Market 你可以输入`print(html)`来查看 HTML 的全部内容,包括 meta 元标签、图像标签、map 标签、JavaScript、表单和表格。 -要得到 HTML 的文本,我们将使用一个名为 *BeautifulSoup* 的 Python 库,可从 `http://www.crummy.com/software/BeautifulSoup/` 访问︰ +要得到 HTML 的文本,我们将使用一个名为 *BeautifulSoup* 的 Python 库,可从`http://www.crummy.com/software/BeautifulSoup/`访问︰ ```py >>> from bs4 import BeautifulSoup @@ -584,7 +584,7 @@ Unicode 支持超过一百万种字符。每个字符分配一个编号,称为 >>> path = nltk.data.find('corpora/unicode_samples/polish-lat2.txt') ``` -Python 的`open()`函数可以读取编码的数据为 Unicode 字符串,并写出 Unicode 字符串的编码形式。它采用一个参数来指定正在读取或写入的文件的编码。因此,让我们使用编码 `'latin2'`打开我们波兰语文件,并检查该文件的内容︰ +Python 的`open()`函数可以读取编码的数据为 Unicode 字符串,并写出 Unicode 字符串的编码形式。它采用一个参数来指定正在读取或写入的文件的编码。因此,让我们使用编码`'latin2'`打开我们波兰语文件,并检查该文件的内容︰ ```py >>> f = open(path, encoding='latin2') @@ -599,7 +599,7 @@ Jagiellońskiej w Krakowie, obejmują ponad 500 tys. zabytkowych archiwaliów, m.in. manuskrypty Goethego, Mozarta, Beethovena, Bacha. ``` -如果这不能在你的终端正确显示,或者我们想要看到字符的底层数值(或"代码点"),那么我们可以将所有的非 ASCII 字符转换成它们两位数`\x`*XX* 和四位数 `\u`*XXXX* 表示法︰ +如果这不能在你的终端正确显示,或者我们想要看到字符的底层数值(或"代码点"),那么我们可以将所有的非 ASCII 字符转换成它们两位数`\x`*XX* 和四位数`\u`*XXXX* 表示法︰ ```py >>> f = open(path, encoding='latin2') @@ -623,7 +623,7 @@ b'archiwali\\xf3w, m.in. manuskrypty Goethego, Mozarta, Beethovena, Bacha.' 324 ``` -324 的 4 位十六进制数字的形式是 0144(输入 `hex(324)` 可以发现这点),我们可以定义一个具有适当转义序列的字符串。 +324 的 4 位十六进制数字的形式是 0144(输入`hex(324)`可以发现这点),我们可以定义一个具有适当转义序列的字符串。 ```py >>> nacute = '\u0144' @@ -666,7 +666,7 @@ b'\xc5\x82' U+0142 LATIN SMALL LETTER L WITH STROKE 另外,根据你的系统的具体情况,你可能需要用`'latin2'`替换示例中的编码`'utf8'`。 -下一个例子展示 Python 字符串函数和`re`模块是如何能够与 Unicode 字符一起工作的。(我们会在下面一节中仔细看看`re` 模块。`\w`匹配一个"单词字符",参见[3.4](./ch03.html#tab-re-symbols))。 +下一个例子展示 Python 字符串函数和`re`模块是如何能够与 Unicode 字符一起工作的。(我们会在下面一节中仔细看看`re`模块。`\w`匹配一个"单词字符",参见[3.4](./ch03.html#tab-re-symbols))。 ```py >>> line.find('zosta\u0142y') @@ -795,7 +795,7 @@ T9 系统用于在手机上输入文本(见[3.5](./ch03.html#fig-t9)))。两 注意 -**轮到你来:** 研究前面的例子,在你继续阅读之前尝试弄清楚`\`, `{}`, `()`和`|` 这些符号的功能。 +**轮到你来:** 研究前面的例子,在你继续阅读之前尝试弄清楚`\`, `{}`, `()`和`|`这些符号的功能。 你可能已经知道反斜杠表示其后面的字母不再有特殊的含义而是按照字面的表示匹配词中特定的字符。因此,虽然`.`很特别,但是`\.`只匹配一个句号。大括号表达式,如`{3,5}`, 表示前面的项目重复指定次数。管道字符表示从其左边的内容和右边的内容中选择一个。圆括号表示一个操作符的范围,它们可以与管道(或叫析取)符号一起使用,如«`w(i|e|ai|oo)t`»,匹配 wit, wet, wait 和 woot。你可以省略这个例子里的最后一个表达式中的括号,使用«`ed|ing @@ -1501,7 +1501,7 @@ romance 74 193 11 51 45 43 humor 16 30 8 8 9 13 ``` -回想一下[3.6](./ch03.html#code-stemmer-indexing)中的列表, 我们使用格式字符串`'{:{width}}'`并绑定一个值给 `format()`中的`width`参数。这我们使用变量知道字段的宽度。 +回想一下[3.6](./ch03.html#code-stemmer-indexing)中的列表, 我们使用格式字符串`'{:{width}}'`并绑定一个值给`format()`中的`width`参数。这我们使用变量知道字段的宽度。 ```py >>> '{:{width}}' % ("Monty Python", width=15) @@ -1567,7 +1567,7 @@ After (5), all (3), is (2), said (4), and (3), done (4), , (1), more * 在本书中,我们将文本作为一个单词列表。“原始文本”是一个潜在的长字符串,其中包含文字和用于设置格式的空白字符,也是我们通常存储和可视化文本的方式。 * 在 Python 中指定一个字符串使用单引号或双引号:`'Monty Python'`,`"Monty Python"`。 * 字符串中的字符是使用索引来访问的,索引从零计数:`'Monty Python'[0]`给出的值是`M`。字符串的长度使用`len()`得到。 -* 子字符串使用切片符号来访问: `'Monty Python'[1:5]` 给出的值是`onty`。如果省略起始索引,子字符串从字符串的开始处开始;如果省略结尾索引,切片会一直到字符串的结尾处结束。 +* 子字符串使用切片符号来访问: `'Monty Python'[1:5]`给出的值是`onty`。如果省略起始索引,子字符串从字符串的开始处开始;如果省略结尾索引,切片会一直到字符串的结尾处结束。 * 字符串可以被分割成列表:`'Monty Python'.split()`给出`['Monty', 'Python']`。列表可以连接成字符串:`'/'.join(['Monty', 'Python'])`给出`'Monty/Python'`。 * 我们可以使用`text = open('input.txt').read()`从一个文件`input.txt`读取文本。可以使用`text = request.urlopen(url).read().decode('utf8')`从一个`url`读取文本。我们可以使用`for line in open(f)`遍历一个文本文件的每一行。 * 我们可以通过打开一个用于写入的文件`output_file = open('output.txt', 'w')`来向文件写入文本,然后添加内容到文件中`print("Monty Python", file=output_file)`。 @@ -1676,7 +1676,7 @@ SIGHAN,ACL 中文语言处理特别兴趣小组`http://sighan.org/`,重点 21. ◑ 写一个函数`unknown()`,以一个 URL 为参数,返回一个那个网页出现的未知词列表。为了做到这一点,请提取所有由小写字母组成的子字符串(使用`re.findall()`),并去除所有在 Words 语料库(`nltk.corpus.words`)中出现的项目。尝试手动分类这些词,并讨论你的发现。 -22. ◑ 使用上面建议的正则表达式处理网址 `http://news.bbc.co.uk/`,检查处理结果。你会看到那里仍然有相当数量的非文本数据,特别是 JavaScript 命令。你可能还会发现句子分割没有被妥善保留。定义更深入的正则表达式,改善此网页文本的提取。 +22. ◑ 使用上面建议的正则表达式处理网址`http://news.bbc.co.uk/`,检查处理结果。你会看到那里仍然有相当数量的非文本数据,特别是 JavaScript 命令。你可能还会发现句子分割没有被妥善保留。定义更深入的正则表达式,改善此网页文本的提取。 23. ◑ 你能写一个正则表达式以这样的方式来分词吗,将词 don't 分为 do 和 n't?解释为什么这个正则表达式无法正常工作:«`n't|\w+`»。 @@ -1693,11 +1693,11 @@ SIGHAN,ACL 中文语言处理特别兴趣小组`http://sighan.org/`,重点 28. ◑ 考虑下面的摘自 MedLine 语料库的句子中的数字表达式:The corresponding free cortisol fractions in these sera were 4.53 +/- 0.15% and 8.16 +/- 0.23%, respectively.我们应该说数字表达式 4.53 +/- 0.15%是三个词吗?或者我们应该说它是一个单独的复合词?或者我们应该说它实际上是*九*个词,因为它读作“four point five three,plus or minus fifteen percent”?或者我们应该说这不是一个“真正的”词,因为它不会出现在任何词典中?讨论这些不同的可能性。你能想出产生这些答案中至少两个以上可能性的应用领域吗? -29. ◑ 可读性测量用于为一个文本的阅读难度打分,给语言学习者挑选适当难度的文本。在一个给定的文本中,让我们定义μ<sub>w</sub>为每个词的平均字母数,μ<sub>s</sub>为每个句子的平均词数。文本自动可读性指数(ARI)被定义为: `4.71` μ<sub>w</sub> `+ 0.5` μ<sub>s</sub> `- 21.43`。计算布朗语料库各部分的 ARI 得分,包括 `f`(lore)和`j`(learned)部分。利用`nltk.corpus.brown.words()`产生一个词汇序列,`nltk.corpus.brown.sents()`产生一个句子的序列的事实。 +29. ◑ 可读性测量用于为一个文本的阅读难度打分,给语言学习者挑选适当难度的文本。在一个给定的文本中,让我们定义μ<sub>w</sub>为每个词的平均字母数,μ<sub>s</sub>为每个句子的平均词数。文本自动可读性指数(ARI)被定义为: `4.71` μ<sub>w</sub> `+ 0.5` μ<sub>s</sub> `- 21.43`。计算布朗语料库各部分的 ARI 得分,包括`f`(lore)和`j`(learned)部分。利用`nltk.corpus.brown.words()`产生一个词汇序列,`nltk.corpus.brown.sents()`产生一个句子的序列的事实。 30. ◑ 使用 Porter 词干提取器规范化一些已标注的文本,对每个词调用提取词干器。用 Lancaster 词干提取器做同样的事情,看看你是否能观察到一些差别。 -31. ◑ 定义变量`saying`包含列表`['After', 'all', 'is', 'said', 'and', 'done', ',', 'more', 'is', 'said', 'than', 'done', '.']`。使用`for`循环处理这个列表,并将结果存储在一个新的链表`lengths` 中。提示:使用`lengths = []`,从分配一个空列表给`lengths`开始。然后每次循环中用`append()`添加另一个长度值到列表中。现在使用列表推导做同样的事情。 +31. ◑ 定义变量`saying`包含列表`['After', 'all', 'is', 'said', 'and', 'done', ',', 'more', 'is', 'said', 'than', 'done', '.']`。使用`for`循环处理这个列表,并将结果存储在一个新的链表`lengths`中。提示:使用`lengths = []`,从分配一个空列表给`lengths`开始。然后每次循环中用`append()`添加另一个长度值到列表中。现在使用列表推导做同样的事情。 32. ◑ 定义一个变量`silly`包含字符串:`'newly formed bland ideas are inexpressible in an infuriating way'`。(这碰巧是合法的解释,讲英语西班牙语双语者可以适用于乔姆斯基著名的无意义短语,colorless green ideas sleep furiously,来自维基百科)。编写代码执行以下任务: diff --git a/4.md b/4.md index 2345e7e..38f8a2d 100644 --- a/4.md +++ b/4.md @@ -463,7 +463,7 @@ True [set(), set(), set(), set(), set(), {'Alice'}, set()]] ``` -请看循环变量`i`和`j`在产生对象过程中没有用到,它们只是需要一个语法正确的`for` 语句。这种用法的另一个例子,请看表达式`['very' for i in range(3)]`产生一个包含三个`'very'`实例的列表,没有整数。 +请看循环变量`i`和`j`在产生对象过程中没有用到,它们只是需要一个语法正确的`for`语句。这种用法的另一个例子,请看表达式`['very' for i in range(3)]`产生一个包含三个`'very'`实例的列表,没有整数。 请注意,由于我们前面所讨论的有关对象复制的原因,使用乘法做这项工作是不正确的。 @@ -831,7 +831,7 @@ Python 提供一些具有函数式编程语言如 Haskell 标准特征的高阶 21.75081116158339 ``` -在上面的例子中,我们指定了一个用户定义的函数`is_content_word()` 和一个内置函数`len()`。我们还可以提供一个 lambda 表达式。这里是两个等效的例子,计数每个词中的元音的数量。 +在上面的例子中,我们指定了一个用户定义的函数`is_content_word()`和一个内置函数`len()`。我们还可以提供一个 lambda 表达式。这里是两个等效的例子,计数每个词中的元音的数量。 ```py >>> list(map(lambda w: len(filter(lambda c: c.lower() in "aeiou", w)), sent)) @@ -1027,7 +1027,7 @@ Python 提供了一个调试器,它允许你监视程序的执行,指定程 它会给出一个提示`(Pdb)`,你可以在那里输入指令给调试器。输入`help`来查看命令的完整列表。输入`step`(或只输入`s`)将执行当前行然后停止。如果当前行调用一个函数,它将进入这个函数并停止在第一行。输入`next`(或只输入`n`)是类似的,但它会在当前函数中的下一行停止执行。`break`(或`b`)命令可用于创建或列出断点。输入`continue`(或`c`)会继续执行直到遇到下一个断点。输入任何变量的名称可以检查它的值。 -我们可以使用 Python 调试器来查找`find_words()` 函数的问题。请记住问题是在第二次调用函数时产生的。我们一开始将不使用调试器而调用该函数[first-run_](./ch04.html#id9),使用可能的最小输入。第二次我们使用调试器调用它[second-run_](./ch04.html#id11)。.. doctest-ignore: +我们可以使用 Python 调试器来查找`find_words()`函数的问题。请记住问题是在第二次调用函数时产生的。我们一开始将不使用调试器而调用该函数[first-run_](./ch04.html#id9),使用可能的最小输入。第二次我们使用调试器调用它[second-run_](./ch04.html#id11)。.. doctest-ignore: ```py >>> import pdb diff --git a/5.md b/5.md index 5bad9bd..eb1ecc0 100644 --- a/5.md +++ b/5.md @@ -439,7 +439,7 @@ KeyError: 'green' 这就提出了一个重要的问题。与列表和字符串不同,我们可以用`len()`算出哪些整数是合法索引,我们如何算出一个字典的合法键?如果字典不是太大,我们可以简单地通过查看变量`pos`检查它的内容。正如在前面([❷](./ch05.html#pos-inspect)行)所看到,这为我们提供了键-值对。请注意它们的顺序与最初放入它们的顺序不同;这是因为字典不是序列而是映射(参见[3.2](./ch05.html#fig-maps02)),键没有固定地排序。 -换种方式,要找到键,我们可以将字典转换成一个列表[❶](./ch05.html#dict-to-list)——要么在期望列表的上下文中使用字典,如作为`sorted()`的参数[❷](./ch05.html#dict-sorted),要么在`for` 循环中[❸](./ch05.html#dict-for-loop)。 +换种方式,要找到键,我们可以将字典转换成一个列表[❶](./ch05.html#dict-to-list)——要么在期望列表的上下文中使用字典,如作为`sorted()`的参数[❷](./ch05.html#dict-sorted),要么在`for`循环中[❸](./ch05.html#dict-for-loop)。 ```py >>> list(pos) ❶ @@ -1173,7 +1173,7 @@ Statement User121 18/m pm me if u tryin to chat 3. 布朗语料库中这些有歧义的词的*词符*的百分比是多少? 19. ◑ `evaluate()`方法算出一个文本上运行的标注器的精度。例如,如果提供的已标注文本是`[('the', 'DT'), ('dog', 'NN')]`,标注器产生的输出是`[('the', 'NN'), ('dog', 'NN')]`,那么得分为`0.5`。让我们尝试找出评价方法是如何工作的: 1. 一个标注器`t`将一个词汇列表作为输入,产生一个已标注词列表作为输出。然而,`t.evaluate()`只以一个正确标注的文本作为唯一的参数。执行标注之前必须对输入做些什么? - 2. 一旦标注器创建了新标注的文本,`evaluate()` 方法可能如何比较它与原来标注的文本,计算准确性得分? + 2. 一旦标注器创建了新标注的文本,`evaluate()`方法可能如何比较它与原来标注的文本,计算准确性得分? 3. 现在,检查源代码来看看这个方法是如何实现的。检查`nltk.tag.api.__file__`找到源代码的位置,使用编辑器打开这个文件(一定要使用文件`api.py`,而不是编译过的二进制文件`api.pyc`)。 20. ◑ 编写代码,搜索布朗语料库,根据标记查找特定的词和短语,回答下列问题: 1. 产生一个标注为`MD`的不同的词的按字母顺序排序的列表。 diff --git a/6.md b/6.md index 8a0c935..10dd91b 100644 --- a/6.md +++ b/6.md @@ -325,7 +325,7 @@ if endswith(,) == False: if endswith(.) == False: return 'NN' ``` -在这里,我们可以看到分类器一开始检查一个词是否以逗号结尾——如果是,它会得到一个特别的标记`","`。接下来,分类器检查词是否以`"the"`尾,这种情况它几乎肯定是一个限定词。这个“后缀”被决策树早早使用是因为词"the"太常见。分类器继续检查词是否以"s"结尾。如果是,那么它极有可能得到动词标记`VBZ`(除非它是这个词"is",它有特殊标记`BEZ`),如果不是,那么它往往是名词(除非它是标点符号“.”)。实际的分类器包含这里显示的 if-then 语句下面进一步的嵌套,参数`depth=4` 只显示决策树的顶端部分。 +在这里,我们可以看到分类器一开始检查一个词是否以逗号结尾——如果是,它会得到一个特别的标记`","`。接下来,分类器检查词是否以`"the"`尾,这种情况它几乎肯定是一个限定词。这个“后缀”被决策树早早使用是因为词"the"太常见。分类器继续检查词是否以"s"结尾。如果是,那么它极有可能得到动词标记`VBZ`(除非它是这个词"is",它有特殊标记`BEZ`),如果不是,那么它往往是名词(除非它是标点符号“.”)。实际的分类器包含这里显示的 if-then 语句下面进一步的嵌套,参数`depth=4`只显示决策树的顶端部分。 ## 1.5 探索上下文语境 diff --git a/8.md b/8.md index b286d7d..2266f3b 100644 --- a/8.md +++ b/8.md @@ -224,7 +224,7 @@ WFST 1 2 3 4 5 6 7 回到我们的表格表示,假设对于词 an 我们有`Det`在(2, 3)单元,对以词 elephant 有`N`在(3, 4)单元,对于 an elephant 我们应该在(2, 4)放入什么?我们需要找到一个形如 *A* → `Det N`的产生式。查询了文法,我们知道我们可以输入(0, 2)单元的`NP`。 -更一般的,我们可以在(i, j)输入 *A*,如果有一个产生式 *A* → *B* *C*,并且我们在(i, k)中找到非终结符 *B*,在(k, j)中找到非终结符 *C*。[4.4](./ch08.html#code-wfst)中的程序使用此规则完成 WFST。通过调用函数`complete_wfst()`时设置 `trace`为`True`,我们看到了显示 WFST 正在被创建的跟踪输出: +更一般的,我们可以在(i, j)输入 *A*,如果有一个产生式 *A* → *B* *C*,并且我们在(i, k)中找到非终结符 *B*,在(k, j)中找到非终结符 *C*。[4.4](./ch08.html#code-wfst)中的程序使用此规则完成 WFST。通过调用函数`complete_wfst()`时设置`trace`为`True`,我们看到了显示 WFST 正在被创建的跟踪输出: ```py >>> wfst1 = complete_wfst(wfst0, tokens, groucho_grammar, trace=True) -- GitLab