1  语言处理与python

本章待解决问题:

a)将简单的程序与大量的文本结合起来,我们可以实现什么?

b)如何能自动提取概括文本风格和内容的关键词及短语?

c)Python 编程语言为上述工作提供了哪些工具和技术支持?

d)自然语言处理中的有哪些充满趣味的挑战?

1.1  语言计算:文本和单词

对于文本我们都很熟悉,因为我们每天都在进行大量的书写。我们将文本视为编写程序的原始数据,并通过一系列充满趣味的方式来操纵、分析这些文本。但在此之前,我们必须从Python解释器开始。

1.1.1  Python入门

Python 解释器具有良好的交互性。用户可以在解释器中输入命令,并执行相应的操作。

1.1.2 NLTK入门

a)nltk安装

在联网的环境下,打开Python解释器并输入以下两条命令,在弹出的NLTK Downloader窗口选择book,点击Download按钮,即可下载所需的nltk图书集。

>>> import nltk

>>> nltk.download()

在数据下载完成后,我们可以使用以下命令在解释器中加载我们所需文本。

>>> from nltk.book import *

*** Introductory Examples for the NLTK Book ***

Loading text1, ..., text9 and sent1, ..., sent9

Type the name of the text or sentence to view it.

Type: 'texts()' or 'sents()' to list the materials.

text1: Moby Dick by Herman Melville 1851

text2: Sense and Sensibility by Jane Austen 1811

text3: The Book of Genesis

text4: Inaugural Address Corpus

text5: Chat Corpus

text6: Monty Python and the Holy Grail

text7: Wall Street Journal

text8: Personals Corpus

text9: The Man Who Was Thursday by G . K . Chesterton 1908

>>>

1.1.3  文本检索

除阅读文本之外,还有很多研究文本内容的方式。

a)词语索引视图可以展示该词在文本中的每一次出现,并显示其上下文。

☞ 函数:concordance(parm),如:

>>> text2.concordance("mysterious") #词语索引

Displaying 1 of 1 matches:

be carried on in so doubtful , so mysterious a manner ! I long to inquire ; an #词语索引

b)获取文本中与指定词上下文相似的单词。

☞ 函数:silimar(parm),如:

>>> text1.similar('happy')

通过对比同一词语在不同时期、不同作家的作品中的使用,我们可以观察到不同时代该词在含义和用法上及不同作家的写作风格上的差异。 

c)研究两个及两个以上单词的公共上下文。

☞ 函数:common_contexts([parm,parm…]),如:

>>>text2.common_contexts(["monstrous", "very"]) 

d)判断单词在文本中的位置,并用离散图表示。

☞ 函数:dispersion_plot([parm,parm,parm…]),如:

>>> text2.dispersion_plot(['happy','angery','mistake','sense'])

注:需安装matplotlib模块

1.1.4  词汇计数

a)文本长度计数

☞ 函数:len(parm),如

>>> len(text1)

>>> len('hello')

b)获取文本词汇表

☞ 函数:set(parm),如

>>> set(text1)

d)词汇表排序

☞ 函数:sorted(expression),如

>>>sorted(set(text1))

e)统计一个词在文本中出现的次数

☞ 函数:count(parm),如

>>> text1.count('as')

 

图1.1 单词位置分布图

1.2  近距离观察Python:将文本视为单词链表

略。

1.3  计算语言:简单的统计

1.3.1  频率分布

a)统计文本中每个单词的出现频率

☞ 函数:FreqDist (parm),如

>>> fdist1 = FreqDist(text1)

注:在使用FreqDist函数前,需通过from nltk.probability import *导入模块。

b)统计文本中最频繁出现的n个词语

☞ 函数:most_common (n),如

>>> fdist1.most_common (text1)

c)生成高频单词在文中出现的频率图

☞ 函数:plot(50, cumulative=True),如

>>> fdist1 = FreqDist(text2)

>>>fdist1.plot(50, cumulative=True)

 

图1.2 高频单词频率图

1.3.2  细粒度的选择词

a)表达式:

(1){w | w ∈ V & P(w)}

(2)[w for w in V if p(w)]

b)Python代码:

>>>v = set(text1)

>>>long_words = [w for w in v if len(w) > 15]

>>>sorted(long_words)

筛选出语料库中长度大于7且出现7次以上的词语:

>>>fdist5 = Fredist(text5)

>>>sorted(w for w in V if len(w) > 7 and fdist5[w] > 7)

注:len(w) > 7确保单词长度大于7;fdist5[w] > 7保障了单词出现品路大于7次。

1.3.3  词语搭配和双连词

词语搭配是指经常出现在一起的一组序列词,一个搭配中的词语不能被其他同义词所替换。我们可以通过提取文本中的词对获取文本中的搭配。

a)提取文本中的词对

☞ 函数:bigrams ([parm,parm,parm…]),如

>>> list(bigrams(['more','than','respect','to']))

[('more', 'than'), ('than', 'respect'), ('respect', 'to')]    #提取出的词对

b)获取高频双连词

☞ 函数:collocations (),如

>>> text1.collocations()

Sperm Whale; Moby Dick; White Whale; old man; Captain Ahab; sperm

whale; Right Whale; Captain Peleg; New Bedford; Cape Horn; cried Ahab;

years ago; lower jaw; never mind; Father Mapple; cried Stubb; chief

mate; white whale; ivory leg; one hand

collocations()函数能为我们找到比基于单个词的频率预期更频繁出现的双连词。

1.3.4  计数其他东西

a)除了单词计数也可以为其他东西计数对文本进行研究。如,可以通过创表示单词长度的链表生成频率词典,从而关注文本中长词的分布:

>>> fdist = FreqDist([len(w) for w in text1])

>>> fdist

FreqDist({3: 50223, 1: 47933, 4: 42345, 2: 38513, 5: 26597, 6: 17111, 7: 14399,

8: 9966, 9: 6428, 10: 3528, ...})

>>> fdist.keys()

dict_keys([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20])

>>> fdist.items

<built-in method items of FreqDist object at 0x00000000023A7A98>

>>> fdist.items()

dict_items([(1, 47933), (2, 38513), (3, 50223), (4, 42345), (5, 26597), (6, 1711

1), (7, 14399), (8, 9966), (9, 6428), (10, 3528), (11, 1873), (12, 1053), (13, 5

67), (14, 177), (15, 70), (16, 22), (17, 12), (18, 1), (20, 1)])

>>> fdist.max()

3

>>> fdist[3]

50223

>>> fdist.freq(3)

0.19255882431878046

表1.1 NLTK 频率分布类中定义的函数

方法

描述

fdist = FreqDist(samples)

创建包含给定样本的频率分布

fdist[sample] += 1

增加样本数量

fdist['monstrous']

统计给定样本出现的次数

fdist.freq('monstrous')

给定样本的频率

fdist.N()

样本总数

fdist.most_common(n)

最频繁出现的n个样本

for sample in fdist:

遍历样本

fdist.max()

数值最大的样本

fdist.tabulate()

绘制频率分布表

fdist.plot()

绘制频率分布图

fdist.plot(cumulative=True)

绘制累积频率分布图

fdist1 |= fdist2

用fdist2的计数更新fdist1

fdist1 < fdist2

测试样本在fdist1 中出现的频率是否小于fdist2

1.4 回归 Python:决策与控制

1.4.1  条件

a)表达式:[w for w in text if condition]

其中,condition为python中的一个条件,表示真或假的条件表达式。我们也可以使用表1.2中的函数来测试词汇的各种属性,不同条件可以用and或or连接。 如:

>>> sorted([w for w in set(text1) if w.endswith('ableness')])

>>> sorted([term for term in set(text4) if 'gnt' in term])

>>> sorted([item for item in set(sent7) if item.isdigit()])

>>> sorted([item for item in set(sent7) if item.startswidth(‘a’) and item in sent1])

表1.2 比较运算函数

函数

描述

s.startswith(t)

测试s是否以t开头

s.endswith(t)

测试s是否以t结尾

t in s

测试t是否是s的子串

s.islower()

测试字符串s中所有字符是否均小写

s.isupper()

测试字符串s中所有字符是否均大写

s.isalpha()

测试s中是否无空格且字符均为字母

s.isalnum()

测试s中是否所有字符均是字母或数字

s.isdigit()

测试s中是否无空格且字符均为数字

s.istitle()

测试s中所有的词都首字母大写)

b)表达式:[f(w) for ...]或[w.f() for ...]

其中f()为一个函数,如:

>>> [len(w) for w in text1]

>>> [w.upper() for w in text1]

1.4.2  控制结构

a)if 语句

表达式:if condition:

 elif condition

b)for循环

表达式:for condition:

如:>>> for word in ['Call', 'me', 'Ishmael', '.']:

print word

c)条件循环

将if语句与for语句结合形成条件循环。

>>> sent1 = ['Call', 'me', 'Ishmael', '.']

>>> for w in sent1:

if w.endswith('l'):

 print w

所有的Python 控制结构均以冒号结尾。冒号表示当前语句与后面的缩进块有关联。

1.5 自动理解自然语言

我们一直通过文本和Python的对语言自底向上的探索,然而,我们也对探索语言知识并通过语言技术建立估算产生了浓厚的兴趣。为了描绘出自然语言处理的蓝图,我们先从代码的细节中退出来。

纯粹的从应用层面上说,我们需要锁定网络中的文本来探索信息的奥秘。搜索引擎在网络的发展和普及方面起到了决定性的作用,然而也它着一定的缺陷。它需要技巧、知识和一点运气,才能从这类问题中找寻到答案,如:“有限的预算能参观费城和匹兹堡的哪些景点?”,“专家们怎么评论数码单反相机?”,“过去的一周里评论员对钢材市场做了哪些预测?”。让计算机来自动回答这些问题,涉及包括信息提取、推理与总结在内的广泛的语言处理任务,将需要在一个更大规模更稳健的层面实施,这超出了我们当前的能力。

哲学层面,构建智能机器是人工智能长久以来的挑战,语言理解是智能行为的重要组成部分。这一目标是多年来的难题。然而,随着NLP 技术日趋成熟,分析非结构化文本的方法越来越健壮,应用越来越广泛,对自然语言理解的期望变成一个合理的目标再次浮现。

在本节中,我们将描述一些语言理解技术,给你一种有趣的挑战正在等着你的感觉。

1.5.1  相关技术

a)词义消歧:一个词语往往有多重含义,而在具体的语句里只有一个准确的词义。词义消歧就是根据上下文内容,确定一词多义的词语在文中的准确含义。

b)指代消解:检测句中的主语和宾语,并确定语句中代词的正确指代。

c)生成语言:在解决语言理解上问题的基础上,继续语言自动生成的任务。如自动问答、机器翻译。根据用户提出的问题,在理解的基础上提供可行的解决的方案,并生成语言反馈给用户。

d)机器翻译:长期以来,机器翻译一直是语言理解的圣杯,我们一直在寻找一个从本质上可以提供高品质的、符合语言习惯的任意两种语言间的翻译。机器翻译可追溯到冷战初期,其广阔的前景使得政府提供了大量的赞助,这也是自然语言处理的起源。

而今指定语言之间的互译工具已然存在,有些已经集成到网络搜索引擎。然而,这些工具还存在着严重的缺陷,如:

0> how long before the next flight to Alice Springs?

1> wie lang vor dem folgenden Flug zu Alice Springs?

2> how long before the following flight to Alice jump?

3> wie lang vor dem folgenden Flug zu Alice springen Sie?

4> how long before the following flight to Alice do you jump?

5> wie lang, bevor der folgende Flug zu Alice tun, Sie springen?

6> how long, before the following flight to Alice does, do you jump?

7> wie lang bevor der folgende Flug zu Alice tut, tun Sie springen?

8> how long before the following flight to Alice does, do you jump?

9> wie lang, bevor der folgende Flug zu Alice tut, tun Sie springen?

10> how long, before the following flight does to Alice, do do you jump?

11> wie lang bevor der folgende Flug zu Alice tut, Sie tun Sprung?

12> how long before the following flight does leap to Alice, does you?

机器翻译的困难主要是在于:不同语言语法上的差异,导致翻译过程中必须调整语序;其次,词义消歧技术尚不成熟。

e)人机对话:人工智能的历史上主要的智能测试是一个语言学测试——图灵测试。即“一个响应用户文本输入的对话系统能否表现的自然到我们无法区分它是人工生成的响应”。

可通过在python上运行“nltk.chat.chatbots()”调出一个原始对话系统。简单

语言对话系统的流程框架如图1.3所示

 

图1.3 简单语言对话系统的流程框架图

从分析语音输入、识别单词、文法分析和在上下文中解释、应用相关的具体操作、响应规划、实现文法结构,然后是适当的词形变化,最后到语音输出。处理的每个过程都蕴含不同类型的语言学知识。

f)文本含义识别:文本含义识别(Recognizing Textual Entailment 简称RTE)其基本情形很简单,如我们想搜集证据支持“Sandra Goudie 被Max Purnell 击败”的假设。现在有段文字似乎相关:“Sandra Goudie 在2002 年国会选举首次当选,通过击败工党候选人Max Purnell 将现执政党下院议员Jeanette Fitzsimons 推到第三位,以微弱优势赢得了Coromandel 席位”。我们很容易就可以得到该文本并不支持我们假设的结论,而自动方法却很难做出这样的决策。RTE 挑战为参赛者开发他们的系统提供数据,但这些数据对“蛮力”机器学习技术来说远远不够,语言学分析在开发过程中至关重要。从上述例子中,最重要的一点是让系统明确Sandra Goudie 是被击败的人,而不击败别人的人。

1.5.1  自然语言处理的局限性

尽管在很多如RTE 这样的任务中研究取得了进展,但在现实世界的应用中已经部署的语言理解系统仍不能进行常识推理或以一种一般的、可靠的方式来描绘这个世界的知识。

我们在等待这些困难的人工智能问题得到解决的同时,接受一些在推理和知识能力上存在严重限制的自然语言系统是有必要的。因此,自然语言处理研究的一个重要目标一直是使用浅显但强大的技术代替无边无际的知识和推理能力,促进构建“语言理解”技术的艰巨任务的不断取得进展。

1.6 小结

a)在Python 中文本用链表来表示:['Monty', 'Python']。我们可以使用索引、分片和len()等函数对链表进行操作。

b)词“token”(标识符)是指文本中词汇表中词语的一次出现;词“type”(类型)则是指词作为一个特定序列字母的唯一形式。我们使用len(text)计数词的标识符,使用len(set(text))计数词的类型。

c)我们使用sorted(set(t))获得文本t的词汇表。

d)我们使用[f(x) for x in text]对文本的每一个标识符进行操作。

e)为了获得没有大小写区分和忽略标点符号的词汇表,我们可以使用set([w.lower() for w in text if w.isalpha()])。

f)我们使用for 语句对文本中的每个词进行处理,例如for w in t:或者for word in text:。后面必须跟冒号和一块在每次循环被执行的缩进的代码。

g)我们使用if 语句测试一个条件:if len(word)<5:。后面必须跟冒号和一块仅当条件为真时执行的缩进的代码。

h)频率分布是词语及其的频率计数的集合(例如:一个文本中的词与它们出现的频率)。

g)函数是指定了名字并且可以重用的代码块。函数通过def 关键字定义,例如在def mult(x, y)中x 和y 是函数的参数,起到实际数据值的占位符的作用。

1.7 练习

1.尝试使用Python 解释器作为一个计算器,输入表达式,如12/(4+1)。

答:

>>> 12/(4+1)

2.4

2. 26 个字母可以组成26 的10 次方或者26**10 个10 字母长的字符串。也就是141167095653376L(结尾处的L 只是表示这是Python 长数字格式)。100 个字母长度的字符串可能有多少个?

答:

>>>26**100

3142930641582938830174357788501626427282669988762475256374173175398995908420104023465432599069702289330964075081611719197835869803511992549376

3. Python 乘法运算可应用于链表。当你输入['Monty', 'Python'] * 20 或者3 * sent1 会发生什么?

答:

将得到一个由20个指定链表中的元素组成的一个链表,如:

>>> ['Monty', 'Python'] * 20

['Monty', 'Python', 'Monty', 'Python', 'Monty', 'Python', 'Monty', 'Python', 'Mo

nty', 'Python', 'Monty', 'Python', 'Monty', 'Python', 'Monty', 'Python', 'Monty'

, 'Python', 'Monty', 'Python', 'Monty', 'Python', 'Monty', 'Python', 'Monty', 'P

ython', 'Monty', 'Python', 'Monty', 'Python', 'Monty', 'Python', 'Monty', 'Pytho

n', 'Monty', 'Python', 'Monty', 'Python', 'Monty', 'Python']

4. 复习1.1 节关于语言计算的内容。在text2 中有多少个词?有多少个不同的词?

答:

>>> len(text2)

141576

>>> len(set(text2))

6833

5. 比较表格1-1 中幽默和言情小说的词汇多样性得分,哪一个文体中词汇更丰富?

6. 制作《理智与情感》中四个主角:Elinor,Marianne,Edward 和Willoughby 的分布图。在这部小说中关于男性和女性所扮演的不同角色,你能观察到什么?你能找出一对夫妻吗?

答: 

>>>text2.dispersion_plot(['Elinor','Marianne','Edward','Willoughby']),分布图如图1.4所示。

 

图1.4 人名分布图

根据人名在文中位置的分布,可以初步得出以下结论:

a)Elinor在文中出现最为频繁,贯穿文章始终,其次Marianne出现也相当频繁,且二人常常同时出现,由此推断应该两人相识且关系密切,是推动故事情节的发展的主线人物。

b)Edwardhe和Willoughby往往错开出现,推断二人并不熟识。

7. 查找text5 中的搭配。

答:

>>> text5.collocations()

wanna chat; PART JOIN; MODE #14-19teens; JOIN PART; PART PART;

cute.-ass MP3; MP3 player; JOIN JOIN; times .. .; ACTION watches; guys

wanna; song lasts; last night; ACTION sits; -...)...- S.M.R.; Lime

Player; Player 12%; dont know; lez gurls; long time

8. 思考下面的Python 表达式:len(set(text4))。说明这个表达式的用途。描述在执行此计算中涉及的两个步骤。

答:

a)用途:用来计算文本中词的类型数目。

b)步骤:

步骤一:set(text4)获取text4中的词汇表。

步骤二:通过len()函数,计算词汇表的长度。

9. 复习1.2 节关于链表和字符串的内容。

a. 定义一个字符串,并且将它分配给一个变量,如:my_string = 'My String'(在字符串中放一些更有趣的东西)。用两种方法输出这个变量的内容,一种是通过简单地输入变量的名称,然后按回车;另一种是通过使用print 语句。

b. 尝试使用my_string+ my_string 或者用它乘以一个数将字符串添加到它自身,例如:my_string* 3。请注意,连接在一起的字符串之间没有空格。怎样能解决这个问题?

答:

a)

>>> my_string = "Louie_Wang fight"

>>> my_string

'Louie_Wang fight'

>>> print(my_string)

Louie_Wang fight

b)

>>> my_string+" "+my_string

'Louie_Wang fight Louie_Wang fight'

>>>

10. 使用的语法my_sent = ["My", "sent"],定义一个词链表变量my_sent(用你自己的词或喜欢的话)。

a. 使用' '.join(my_sent)将其转换成一个字符串。

b. 使用split()在你指定的地方将字符串分割回链表。

答:

a)

>>> my_sent = ['hello',',','louie']

>>> ' '.join(my_sent)

'hello , louie'

>>>

b)

>>> 'hello , louie'.split()

['hello', ',', 'louie']

11. 定义几个包含词链表的变量,例如:phrase1,phrase2 等。将它们连接在一起组成不同的组合(使用加法运算符),最终形成完整的句子。len(phrase1 + phrase2)与len(phrase1) + len(phrase2)之间的关系是什么?

答:

>>> phrase1 = ['hello','louie']

>>> phrase2 = ['i','am','jack']

>>> phrase1 + phrase2

['hello', 'louie', 'i', 'am', 'jack']

>>> phrase2 + phrase1

['i', 'am', 'jack', 'hello', 'louie']

>>> len(phrase2 + phrase1)

5

>>> len(phrase1) + len(phrase2)

5

关系:len(phrase1 + phrase2)=len(phrase1) + len(phrase2)

12. 考虑下面两个具有相同值的表达式。哪一个在NLP 中更常用?为什么?

a. "Monty Python"[6:12]

b. ["Monty", "Python"][1]

答:

NLP中通过b(链表索引访问)方式更常用,因为自然语言处理的单位是单词而非字母。

13. 我们已经看到如何用词链表表示一个句子,其中每个词是一个字符序列。sent1[2][2]代表什么意思?为什么?请用其他的索引值做实验。

答:

表示链表sent1中第三个字符串的第三个字符。

>>> phrase1 = ['hello',',','louie']

>>> phrase1[2][2]

'u'

>>>

14. 在变量sent3 中保存的是text3 的第一句话。在sent3 中the 的索引值是1,因为sent3[1]的值是“the”。sent3 中“the”的其它出现的索引值是多少?

答:

[i for i,j in enumerate(sent3) if j=='the']

15. 复习1.4 节讨论的条件语句。在聊天语料库(text5)中查找所有以字母b 开头的词。按字母顺序显示出来。

答:

>>> sorted([item for item in set(text5) if item.startswith('b')])

16. 在Python 解释器提示符下输入表达式range(10)。再尝试range(10, 20),range(10, 20, 2)和range(20, 10, -2)。在后续章节中我们将看到这个内置函数的多用用途。

答:

a)

>>> range(10)

range(0, 10)

>>> range(10,20)

range(10, 20)

>>> range(10,20,2)

range(10, 20, 2)

>>> range(20,10,2)

range(20, 10, 2)

>>>

17. 使用text9.index()查找词sunset 的索引值。你需要将这个词作为一个参数插入到圆括号之间。通过尝试和出错的过程中,找到完整的句子中包含这个词的切片。

18. 使用链表加法、set 和sorted 操作,计算句子sent1...sent8 的词汇表。

答:

>>> sorted(set(sent1+sent2+sent3+sent4+sent5+sent6+sent7+sent8))

['!', ',', '-', '.', '1', '25', '29', '61', ':', 'ARTHUR', 'Call', 'Citizens', 'Dashwood', 'Fellow', 'God', 'House', 'I', 'In', 'Ishmael', 'JOIN', 'KING', 'MALE', 'Nov.', 'PMing', 'Pierre', 'Representatives', 'SCENE', 'SEXY', 'Senate', 'Sussex', 'The', 'Vinken', 'Whoa', '[', ']', 'a', 'and', 'as', 'attrac', 'been', 'beginning', 'board', 'clop', 'created', 'director', 'discreet', 'earth', 'encounters', 'family', 'for', 'had', 'have', 'heaven', 'in', 'join', 'lady', 'lol', 'long', 'me', 'nonexecutive', 'of', 'old', 'older', 'people', 'problem', 'seeks', 's

ettled', 'single', 'the', 'there', 'to', 'will', 'wind', 'with', 'years']

>>>

19. 下面两行之间的差异是什么?哪一个的值比较大?其他文本也是同样情况吗?

>>> sorted(set([w.lower() for w in text1]))

>>> sorted([w.lower() for w in set(text1)])

答:

>>> len(sorted(set([w.lower() for w in text1])))

17231

>>> len(sorted([w.lower() for w in set(text1)]))

19317

>>>

明显,后者值较大,因后者先取词汇表后转换小写,使得类似“Hello”,“hello”的词在词汇表中出现两次;然而,前者先转换小写,再取词汇表可以过滤拼写相同而大小写不同的词语。

20.  w.isupper()和not w.islower()这两个测试之间的差异是什么?

答:

前者判断w中的字符是否全部大写,后者判断w中的字符是否全部小写。

21. 写一个切片表达式提取text2 中最后两个词。

答:

>>> text2[-2:]

['THE', 'END']

>>>

22. 找出聊天语料库(text5)中所有四个字母的词。使用频率分布函数(FreqDist),以频率从高到低显示这些词。

答:

>>> fdist = FreqDist([w for w in text5 if len(w)==4])

>>> fdist.most_common()

23. 复习1.4 节中条件循环的讨论。使用for 和if 语句组合循环遍历《巨蟒和圣杯》(text6)的电影剧本中的词,输出所有的大写词,每行输出一个。

答:

>>> for word in text5:

...     if word.isupper():

...             print(word)

24. 写表达式找出text6 中所有符合下列条件的词。结果应该是词链表的形式:['word1', 'word2', ...]。

a. 以ize 结尾

b. 包含字母z

c. 包含字母序列pt

d. 除了首字母外是全部小写字母的词(即istitle)

答:

a)>>> [w for w in text6 if w.endswith('ize')]

[]

b)>>> [w for w in text6 if 'z' in w]

['zone', 'amazes', 'Fetchez', 'Fetchez', 'zoop', 'zoo', 'zhiv', 'frozen', 'zoosh']

c)>>> [w for w in text6 if 'pt' in w]

['empty', 'aptly', 'Thpppppt', 'Thppt', 'Thppt', 'empty', 'Thppppt', 'temptress'

, 'temptation', 'ptoo', 'Chapter', 'excepting', 'Thpppt']

d)>>> [w for w in text6 if w.istitle()]

25. 定义sent 为词链表['she', 'sells', 'sea', 'shells', 'by', 'the', 'sea', 'shore']。

编写代码执行以下任务:

a. 输出所有sh 开头的单词

b. 输出所有长度超过4 个字符的词

答:

a)>>> [w for w in sent if w.startswith('sh')]

['she', 'shells', 'shore']

b)>>> [w for w in sent if len(w) > 4]

['sells', 'shells', 'shore']

26. 下面的Python 代码是做什么的?sum([len(w) for w in text1]),你可以用它来算出一个文本的平均字长吗?

答:

a)计算text1文本中的字符总长度。

b)>>> sum([len(w) for w in text1])/(len(text1))

3.830411128023649

27. 定义一个名为vocab_size(text)的函数,以文本作为唯一的参数,返回文本的词汇量。

答:

>>> def vocab_size(text):

...     return len(set(text))

...

>>> print(vocab_size(text1))

19317

>>>

28. 定义一个函数percent(word, text),计算一个给定的词在文本中出现的频率,结果以百分比表示。

答:

>>> def percent(word,text):

...      return str(FreqDist(text)[word]/len(text)*100) +'%'

>>> print(percent('as',text1))

0.6211203938363387%

29. 我们一直在使用集合存储词汇表。试试下面的Python 表达式:set(sent3) < set(text1)。实验在set()中使用不同的参数。它是做什么用的?你能想到一个实际的应用吗?

答:

a)>>> set(sent3)<set(text4) #

True

b)>>> set('hello') #参数为字符串,返回出现的字符的集合

{'o', 'e', 'l', 'h'}

>>> set(['hello','Louie']) #参数为列表,返回单词的集合

{'hello', 'Louie'}

>>> set({'hi':1,'louie':2}) #参数为字典,返回字典中key的集合

{'hi', 'louie'}

>>> set({'hi','louie','i','am','louie','too'})#参数为集合,返回集合中不同元素

{'too', 'am', 'louie', 'i', 'hi'}

实际应用:

a)配合len()函数 ,统计字符串中字母的不同字母的个数

b)统计文本的词汇量、测试文本词汇的多样性。