使用 Python 和 NLTK 进行 NLP 分析的高级指南

深入了解自然语言处理背后的基础概念。
83 位读者喜欢这篇文章。
Brain on a computer screen

opensource.com

在我的上一篇文章中,我介绍了自然语言处理 (NLP) 和自然语言工具包 (NLTK),这是宾夕法尼亚大学创建的 NLP 工具包。我演示了如何在 Python 中解析文本和定义停用词,并介绍了语料库的概念,语料库是文本数据集,有助于使用现成的数据进行文本处理。在本文中,我将继续利用数据集来比较和分析自然语言。

本文涵盖的基本构建块包括

  • WordNet 和同义词集 (synsets)
  • 相似性比较
  • 树和树库 (treebank)
  • 命名实体识别

WordNet 和同义词集 (synsets)

WordNet 是 NLTK 中的大型词汇数据库语料库。WordNet 维护由名词、动词、形容词、副词、同义词、反义词等关联的词的认知同义词(通常称为同义词集)。

WordNet 是一个非常有用的文本分析工具。它适用于多种语言(中文、英语、日语、俄语、西班牙语等),并有多种许可证(从开源到商业许可证)。第一个 WordNet 由普林斯顿大学为英语创建,采用类似 MIT 的许可证。

一个词通常根据其含义和词性与多个同义词集相关联。每个同义词集通常提供以下属性

属性 定义 示例
名称 同义词集的名称 示例:单词 “code” 有五个同义词集,名称为 code.n.01code.n.02code.n.03code.v.01code.v.02
POS 此同义词集中单词的词性 单词 “code” 有三个名词形式的同义词集和两个动词形式的同义词集
定义 单词的定义(以 POS 形式) 动词形式 “code” 的定义之一是:“(计算机科学)计算机程序中数据或指令的符号排列”
示例 单词用法的示例 “code” 的示例之一:“我们应该对消息进行编码以确保安全”
词元 (Lemmas) 与此单词 + POC 相关的其他单词同义词集(不完全是同义词,但可以认为是同义词);词元与词元相关,而不是直接与单词相关 code.v.02 的词元(如 “将普通语言转换为代码” 中的 “code”)是 code.v.02.enciphercode.v.02.ciphercode.v.02.cyphercode.v.02.encryptcode.v.02.inscribecode.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()

这种结构有助于正确解释文本的含义。例如,识别此文本中的主语

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()

树和树库的概念是文本分析的强大构建块。

亲自尝试

使用 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()

NLTK 的内置命名实体标记器使用 PENN 的自动内容提取 (ACE) 程序,检测常见实体,例如 ORGANIZATION(组织)、PERSON(人)、LOCATION(地点)、FACILITY(设施)和 GPE(地缘政治实体)。

NLTK 可以使用其他标记器,例如 Stanford Named Entity Recognizer。这个经过训练的标记器是用 Java 构建的,但 NLTK 提供了与它一起工作的接口(请参阅 nltk.parse.stanfordnltk.tag.stanford)。

亲自尝试

使用 Python 库,下载维基百科上关于开源的页面,并识别对开源产生影响的人员以及他们贡献的地点和时间。

高级练习

如果您已准备好,请尝试使用这些文章中讨论的构建块构建这个上层结构。

使用 Python 库,下载维基百科的类别:计算机科学页面,并

  • 识别最常出现的一元语法、二元语法和三元语法,并将其作为学生和工程师需要了解的该领域关键词或技术列表发布。
  • 以图形方式显示该领域中重要的名称、技术、日期和地点。这可以是一个漂亮的信息图。
  • 创建一个搜索引擎。您的搜索引擎的性能是否优于维基百科的搜索?

下一步是什么?

NLP 是应用程序构建中至关重要的支柱。NLTK 是一个经典、丰富且功能强大的工具包,它提供了构建实际吸引人的、有目的的现实世界应用程序的砖瓦。

在本系列文章中,我以 NLTK 为例,解释了 NLP 可以实现的功能。NLP 和 NLTK 还有更多功能。本系列是一个起点,旨在帮助您入门。

如果您的需求超出 NLTK 的能力范围,您可以训练新模型或向其添加功能。基于 NLTK 构建的新 NLP 库正在涌现,机器学习被广泛应用于语言处理。

接下来阅读什么
User profile image.
Girish 在印度的全球 IT 服务组织拥有超过 20 年的技术和软件经验。Girish 是 “I Got” 云平台的架构师,该平台旨在利用开源堆栈和现代架构模式(如微服务、容器化和多租户)来提升金字塔底层。Girish 撰写关于开源和技术主题的文章。

评论已关闭。

知识共享许可协议本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.