在我的上一篇文章中,我介绍了自然语言处理 (NLP) 和自然语言工具包 (NLTK),这是宾夕法尼亚大学创建的 NLP 工具包。我演示了如何在 Python 中解析文本和定义停用词,并介绍了语料库的概念,语料库是文本数据集,有助于使用现成的数据进行文本处理。在本文中,我将继续利用数据集来比较和分析自然语言。
本文涵盖的基本构建块包括
- WordNet 和同义词集 (synsets)
- 相似性比较
- 树和树库 (treebank)
- 命名实体识别
WordNet 和同义词集 (synsets)
WordNet 是 NLTK 中的大型词汇数据库语料库。WordNet 维护由名词、动词、形容词、副词、同义词、反义词等关联的词的认知同义词(通常称为同义词集)。
WordNet 是一个非常有用的文本分析工具。它适用于多种语言(中文、英语、日语、俄语、西班牙语等),并有多种许可证(从开源到商业许可证)。第一个 WordNet 由普林斯顿大学为英语创建,采用类似 MIT 的许可证。
一个词通常根据其含义和词性与多个同义词集相关联。每个同义词集通常提供以下属性
属性 | 定义 | 示例 |
---|---|---|
名称 | 同义词集的名称 | 示例:单词 “code” 有五个同义词集,名称为 code.n.01 、code.n.02 、code.n.03 、code.v.01 、code.v.02 |
POS | 此同义词集中单词的词性 | 单词 “code” 有三个名词形式的同义词集和两个动词形式的同义词集 |
定义 | 单词的定义(以 POS 形式) | 动词形式 “code” 的定义之一是:“(计算机科学)计算机程序中数据或指令的符号排列” |
示例 | 单词用法的示例 | “code” 的示例之一:“我们应该对消息进行编码以确保安全” |
词元 (Lemmas) | 与此单词 + POC 相关的其他单词同义词集(不完全是同义词,但可以认为是同义词);词元与词元相关,而不是直接与单词相关 | code.v.02 的词元(如 “将普通语言转换为代码” 中的 “code”)是 code.v.02.encipher 、code.v.02.cipher 、code.v.02.cypher 、code.v.02.encrypt 、code.v.02.inscribe 、code.v.02.write_in_code |
反义词 | 反义词 | 词元 encode.v.01.encode 的反义词是 decode.v.01.decode |
上位词 (Hypernym) | 其他词语所属的广泛类别 | code.v.01 的上位词(如 “用数字标记这些碎片,以便稍后识别它们”)是 tag.v.01 |
下位词 (Meronym) | 属于(或从属于)广泛类别的词 | “计算机” 的下位词是 “芯片” |
整体词 (Holonym) | 父词与其下属部分之间的关系 | “窗户” 的整体词是 “电脑屏幕” |
还有其他几个属性,您可以在 <您的 python 安装目录>/Lib/site-packages
中的 nltk/corpus/reader/wordnet.py
源文件中找到。
一些代码可能有助于更好地理解。
这个辅助函数
def synset_info(synset):
print("Name", synset.name())
print("POS:", synset.pos())
print("Definition:", synset.definition())
print("Examples:", synset.examples())
print("Lemmas:", synset.lemmas())
print("Antonyms:", [lemma.antonyms() for lemma in synset.lemmas() if len(lemma.antonyms()) > 0])
print("Hypernyms:", synset.hypernyms())
print("Instance Hypernyms:", synset.instance_hypernyms())
print("Part Holonyms:", synset.part_holonyms())
print("Part Meronyms:", synset.part_meronyms())
print()
synsets = wordnet.synsets('code')
显示了这个
5 synsets:
Name code.n.01
POS: n
Definition: a set of rules or principles or laws (especially written ones)
Examples: []
Lemmas: [Lemma('code.n.01.code'), Lemma('code.n.01.codification')]
Antonyms: []
Hypernyms: [Synset('written_communication.n.01')]
Instance Hpernyms: []
Part Holonyms: []
Part Meronyms: []
...
Name code.n.03
POS: n
Definition: (computer science) the symbolic arrangement of data or instructions in a computer program or the set of such instructions
Examples: []
Lemmas: [Lemma('code.n.03.code'), Lemma('code.n.03.computer_code')]
Antonyms: []
Hypernyms: [Synset('coding_system.n.01')]
Instance Hpernyms: []
Part Holonyms: []
Part Meronyms: []
...
Name code.v.02
POS: v
Definition: convert ordinary language into code
Examples: ['We should encode the message for security reasons']
Lemmas: [Lemma('code.v.02.code'), Lemma('code.v.02.encipher'), Lemma('code.v.02.cipher'), Lemma('code.v.02.cypher'), Lemma('code.v.02.encrypt'), Lemma('code.v.02.inscribe'), Lemma('code.v.02.write_in_code')]
Antonyms: []
Hypernyms: [Synset('encode.v.01')]
Instance Hpernyms: []
Part Holonyms: []
Part Meronyms: []
同义词集和词元遵循您可以可视化的树结构
def hypernyms(synset):
return synset.hypernyms()
synsets = wordnet.synsets('soccer')
for synset in synsets:
print(synset.name() + " tree:")
pprint(synset.tree(rel=hypernyms))
print()
code.n.01 tree:
[Synset('code.n.01'),
[Synset('written_communication.n.01'),
...
code.n.02 tree:
[Synset('code.n.02'),
[Synset('coding_system.n.01'),
...
code.n.03 tree:
[Synset('code.n.03'),
...
code.v.01 tree:
[Synset('code.v.01'),
[Synset('tag.v.01'),
...
code.v.02 tree:
[Synset('code.v.02'),
[Synset('encode.v.01'),
...
WordNet 并未涵盖所有单词及其信息(如今英语中约有 170,000 个单词,最新版本的 WordNet 中约有 155,000 个),但这是一个很好的起点。在您学习了此构建块的概念之后,如果您发现它不能满足您的需求,您可以迁移到另一个构建块。或者,您可以构建自己的 WordNet!
亲自尝试
使用 Python 库,下载维基百科上关于开源的页面,并列出所有单词的同义词集和词元。
相似性比较
相似性比较是一个构建块,用于识别两段文本之间的相似性。它在搜索引擎、聊天机器人等领域有许多应用。
例如,“football”(橄榄球)和 “soccer”(足球)这两个词相关吗?
syn1 = wordnet.synsets('football')
syn2 = wordnet.synsets('soccer')
# A word may have multiple synsets, so need to compare each synset of word1 with synset of word2
for s1 in syn1:
for s2 in syn2:
print("Path similarity of: ")
print(s1, '(', s1.pos(), ')', '[', s1.definition(), ']')
print(s2, '(', s2.pos(), ')', '[', s2.definition(), ']')
print(" is", s1.path_similarity(s2))
print()
Path similarity of:
Synset('football.n.01') ( n ) [ any of various games played with a ball (round or oval) in which two teams try to kick or carry or propel the ball into each other's goal ]
Synset('soccer.n.01') ( n ) [ a football game in which two teams of 11 players try to kick or head a ball into the opponents' goal ]
is 0.5
Path similarity of:
Synset('football.n.02') ( n ) [ the inflated oblong ball used in playing American football ]
Synset('soccer.n.01') ( n ) [ a football game in which two teams of 11 players try to kick or head a ball into the opponents' goal ]
is 0.05
这两个词的最高路径相似度得分是 0.5,表明它们密切相关。
“code”(代码)和 “bug”(错误)怎么样?在计算机科学中使用的这些词的相似性得分是
Path similarity of:
Synset('code.n.01') ( n ) [ a set of rules or principles or laws (especially written ones) ]
Synset('bug.n.02') ( n ) [ a fault or defect in a computer program, system, or machine ]
is 0.1111111111111111
...
Path similarity of:
Synset('code.n.02') ( n ) [ a coding system used for transmitting messages requiring brevity or secrecy ]
Synset('bug.n.02') ( n ) [ a fault or defect in a computer program, system, or machine ]
is 0.09090909090909091
...
Path similarity of:
Synset('code.n.03') ( n ) [ (computer science) the symbolic arrangement of data or instructions in a computer program or the set of such instructions ]
Synset('bug.n.02') ( n ) [ a fault or defect in a computer program, system, or machine ]
is 0.09090909090909091
这些是最高的相似性得分,表明它们是相关的。
NLTK 提供了几种相似性评分器,例如
- path_similarity
- lch_similarity
- wup_similarity
- res_similarity
- jcn_similarity
- lin_similarity
请参阅 WordNet 接口 页面的“相似性”部分,以确定适合您应用程序的评分器。
亲自尝试
使用 Python 库,从维基百科类别:计算机术语列表页面开始,准备一个术语列表,然后查看这些词语是如何关联的。
树和树库 (treebank)
使用 NLTK,您可以将文本的结构以树形形式表示,以帮助进行文本分析。
这是一个例子
一个简单的文本,经过预处理和词性 (POS) 标记
import nltk
text = "I love open source"
# Tokenize to words
words = nltk.tokenize.word_tokenize(text)
# POS tag the words
words_tagged = nltk.pos_tag(words)
您必须定义语法才能将文本转换为树结构。此示例使用基于 Penn Treebank 标签 的简单语法。
# A simple grammar to create tree
grammar = "NP: {<JJ><NN>}"
接下来,使用语法创建一棵树
# Create tree
parser = nltk.RegexpParser(grammar)
tree = parser.parse(words_tagged)
pprint(tree)
这将产生
Tree('S', [('I', 'PRP'), ('love', 'VBP'), Tree('NP', [('open', 'JJ'), ('source', 'NN')])])
您可以更直观地看到它。
tree.draw()

(Girish Managoli, CC BY-SA 4.0)
这种结构有助于正确解释文本的含义。例如,识别此文本中的主语
subject_tags = ["NN", "NNS", "NP", "NNP", "NNPS", "PRP", "PRP$"]
def subject(sentence_tree):
for tagged_word in sentence_tree:
# A crude logic for this case - first word with these tags is considered subject
if tagged_word[1] in subject_tags:
return tagged_word[0]
print("Subject:", subject(tree))
它显示 “I” 是主语
Subject: I
这是一个基本的文本分析构建块,适用于更大的应用程序。例如,当用户说 “Book a flight for my mom, Jane, to NY from London on January 1st”(为我的妈妈简预订 1 月 1 日从伦敦到纽约的航班)时,使用此构建块的聊天机器人可以将请求解释为
动作:预订
内容:航班
旅客:Jane
出发地:伦敦
目的地:纽约
日期:1 月 1 日(明年)
树库 (treebank) 是指带有预标记树的语料库。开源、有条件免费使用和商业树库可用于多种语言。英语最常用的树库是宾州树库 (Penn Treebank),它从《华尔街日报》中提取,其中一部分包含在 NLTK 中。使用树库的一些方法
words = nltk.corpus.treebank.words()
print(len(words), "words:")
print(words)
tagged_sents = nltk.corpus.treebank.tagged_sents()
print(len(tagged_sents), "sentences:")
print(tagged_sents)
100676 words:
['Pierre', 'Vinken', ',', '61', 'years', 'old', ',', ...]
3914 sentences:
[[('Pierre', 'NNP'), ('Vinken', 'NNP'), (',', ','), ('61', 'CD'), ('years', 'NNS'), ('old', 'JJ'), (',', ','), ('will', 'MD'), ('join', 'VB'), ('the', 'DT'), ('board', 'NN'), ('as', 'IN'), ('a', 'DT'), ('nonexecutive', 'JJ'), ('director', 'NN'), ...]
查看句子中的标签
sent0 = tagged_sents[0]
pprint(sent0)
[('Pierre', 'NNP'),
('Vinken', 'NNP'),
(',', ','),
('61', 'CD'),
('years', 'NNS'),
...
创建语法以将其转换为树
grammar = '''
Subject: {<NNP><NNP>}
SubjectInfo: {<CD><NNS><JJ>}
Action: {<MD><VB>}
Object: {<DT><NN>}
Stopwords: {<IN><DT>}
ObjectInfo: {<JJ><NN>}
When: {<NNP><CD>}
'''
parser = nltk.RegexpParser(grammar)
tree = parser.parse(sent0)
print(tree)
(S
(Subject Pierre/NNP Vinken/NNP)
,/,
(SubjectInfo 61/CD years/NNS old/JJ)
,/,
(Action will/MD join/VB)
(Object the/DT board/NN)
as/IN
a/DT
(ObjectInfo nonexecutive/JJ director/NN)
(Subject Nov./NNP)
29/CD
./.)
以图形方式查看
tree.draw()

(Girish Managoli, CC BY-SA 4.0)
树和树库的概念是文本分析的强大构建块。
亲自尝试
使用 Python 库,下载维基百科上关于开源的页面,并以可呈现的视图表示文本。
命名实体识别
文本,无论是口语还是书面语,都包含重要数据。文本处理的主要目标之一是提取这些关键数据。几乎所有应用程序都需要它,例如预订机票的航空公司聊天机器人或问答机器人。NLTK 为此提供了命名实体识别功能。
这是一个代码示例
sentence = 'Peterson first suggested the name "open source" at Palo Alto, California'
查看在此句子中是否识别出名称和地点。像往常一样进行预处理
import nltk
words = nltk.word_tokenize(sentence)
pos_tagged = nltk.pos_tag(words)
运行命名实体标记器
ne_tagged = nltk.ne_chunk(pos_tagged)
print("NE tagged text:")
print(ne_tagged)
print()
NE tagged text:
(S
(PERSON Peterson/NNP)
first/RB
suggested/VBD
the/DT
name/NN
``/``
open/JJ
source/NN
''/''
at/IN
(FACILITY Palo/NNP Alto/NNP)
,/,
(GPE California/NNP))
已添加名称标签;仅从此树中提取命名实体
print("Recognized named entities:")
for ne in ne_tagged:
if hasattr(ne, "label"):
print(ne.label(), ne[0:])
Recognized named entities:
PERSON [('Peterson', 'NNP')]
FACILITY [('Palo', 'NNP'), ('Alto', 'NNP')]
GPE [('California', 'NNP')]
以图形方式查看
ne_tagged.draw()

(Girish Managoli, CC BY-SA 4.0)
NLTK 的内置命名实体标记器使用 PENN 的自动内容提取 (ACE) 程序,检测常见实体,例如 ORGANIZATION(组织)、PERSON(人)、LOCATION(地点)、FACILITY(设施)和 GPE(地缘政治实体)。
NLTK 可以使用其他标记器,例如 Stanford Named Entity Recognizer。这个经过训练的标记器是用 Java 构建的,但 NLTK 提供了与它一起工作的接口(请参阅 nltk.parse.stanford 或 nltk.tag.stanford)。
亲自尝试
使用 Python 库,下载维基百科上关于开源的页面,并识别对开源产生影响的人员以及他们贡献的地点和时间。
高级练习
如果您已准备好,请尝试使用这些文章中讨论的构建块构建这个上层结构。
使用 Python 库,下载维基百科的类别:计算机科学页面,并
- 识别最常出现的一元语法、二元语法和三元语法,并将其作为学生和工程师需要了解的该领域关键词或技术列表发布。
- 以图形方式显示该领域中重要的名称、技术、日期和地点。这可以是一个漂亮的信息图。
- 创建一个搜索引擎。您的搜索引擎的性能是否优于维基百科的搜索?
下一步是什么?
NLP 是应用程序构建中至关重要的支柱。NLTK 是一个经典、丰富且功能强大的工具包,它提供了构建实际吸引人的、有目的的现实世界应用程序的砖瓦。
在本系列文章中,我以 NLTK 为例,解释了 NLP 可以实现的功能。NLP 和 NLTK 还有更多功能。本系列是一个起点,旨在帮助您入门。
如果您的需求超出 NLTK 的能力范围,您可以训练新模型或向其添加功能。基于 NLTK 构建的新 NLP 库正在涌现,机器学习被广泛应用于语言处理。
评论已关闭。