《Python自然语言处理-雅兰·萨纳卡(Jalaj Thanaki)》学习笔记:05 特征工程和NLP算法

5.1 理解特征工程

特征工程是开发NLP应用程序的重要组成部分。特征是机器学习(ML)算法的输入参数。这些ML算法根据输入特性生成输出。特征工程是一门艺术和技术,因为它产生了可能的最佳特征,而选择最佳算法来开发NLP应用需要大量的工作和对特征工程以及NLP和ML算法的理解。在第2章,语料库和数据集的实际理解中,我们看到了数据是如何收集的,以及数据或语料库的不同格式是什么。在第三章,理解句子结构时,我们提到了一些基本的,但是NLP和语言学的重要方面。我们将在本章中使用这些概念来派生特性。在第四章,预处理中,我们研究了预处理技术。现在,我们将处理预处理的语料库,并从该语料库生成特性。

什么是特征工程?

了解NLP的基本特征

NLP的基本统计特征

除此之外,我们还将探讨各种工具或库是如何开发来生成特性的,我们可以使用的各种库是什么,以及在需要时如何调整开放源代码库或开放源代码工具。我们还将研究每个概念的挑战。在这里,我们不会从头开始开发工具,因为它超出了本书的范围,但是我们将引导您完成用于开发工具的过程和算法。因此,如果您想尝试构建定制的工具,这将帮助您,并将给您一个如何处理这些问题陈述的想法。

5.1.1 特征工程的定义

特征工程是从原始数据或语料库生成或派生特征(现象的属性或单个可测量属性)的过程,这将帮助我们开发NLP应用程序或解决与NLP相关的问题。

特征可以定义为一条信息或可测量的属性,在构建NLP应用程序或预测NLP应用程序的输出时很有用。

我们将使用ML技术来处理自然语言,并开发出能够提供最终输出的模型。这个模型称为机器学习模型(ML模型)。我们将机器学习算法的功能作为输入并生成机器学习模型。之后,我们将使用生成的机器学习模型为NLP应用程序生成适当的输出。

如果您想知道什么信息可以作为一个特性,那么答案是,任何属性都可以作为一个特性,只要它对于生成一个好的ML模型很有用,它将准确高效地为NLP应用程序生成输出。这里,您的输入特性完全依赖于您的数据集和NLP应用程序。

特性是使用NLP应用程序的领域知识派生的。这就是我们探索自然语言的基本语言学方面的原因,这样我们就可以在特征工程中使用这些概念。

5.1.2 特征工程的目的

在本节中,我们将介绍有助于我们理解特征工程的主要功能:

我们有计算机无法理解的自然语言的原始数据,而算法没有能力接受原始自然语言并生成NLP应用程序的预期输出。当您使用机器学习技术开发NLP应用程序时,功能扮演着重要的角色。

我们需要生成能够代表我们的语料库的属性,以及那些可以被机器学习算法理解的属性。ML算法只能理解通信中的特征语言,提出合适的属性或特征是一件大事。这就是特征工程的全部目的。

一旦我们生成了特征,我们就需要把它们作为输入,输入到机器学习算法中,在处理完这些输入特征之后,我们将得到ML模型。该ML模型将用于预测或生成新特性的输出。ML模型、精度和效率主要取决于特征,这就是为什么我们说特征工程是一种艺术和技能。

5.1.3 一些挑战

以下是特征工程中涉及的挑战:

提出好的特性是困难的,有时是复杂的。

在生成特性之后,我们需要决定应该选择哪些特性。当我们在此基础上执行机器学习技术时,这些特性的选择也起着重要的作用。选择适当特征的过程称为

特性选择。

有时,在特征选择过程中,我们需要消除一些不太重要的特征,而这种特征的消除也是特征工程的一个关键部分。

手工特征工程是耗时的。

特征工程需要领域专业知识,或者至少需要领域的基本知识。

5.2 NLP中的基础特征

除了挑战之外,NLP应用程序还严重依赖于基于各种NLP概念手工构建的特性。从这一点开始,我们将探索NLP世界中可用的基本特性。

5.2.1 句法解析和句法解析器

通过解析句子,几乎对每个NLP应用程序都有帮助,您可以得到一些最重要的特性
我们将探讨句法解析和句法解析器的概念。稍后,我们将了解上下文无关语法(CFG)和概率上下文无关语法(PCFG)。我们看看怎么开发统计分析器。如果您想创建自己的解析器,那么我们将解释这样做的过程,或者如果您想要调整现有的解析器,那么您应该需要执行什么步骤。我们还将使用可用的句法解析器工具进行实际工作。我们会看的在同一节后面的挑战。
句法解析器的基础
这里,我将用NLP域来解释句法解析器。解析器概念也存在于其他计算机科学领域,但是让我们集中讨论NLP领域,并开始了解解析器以及它可以为我们做什么。

在NLP中,解析器是一个程序,或者更具体地说,是一个以语句或词条序列的形式分析自然语言的工具。它将输入流分成更小的块。这将有助于我们理解流中每个元素的句法作用以及句子的基本语法层含义。在NLP中,解析器实际上使用上下文无关语法或概率上下文无关语法的规则来分析句子。我们已经在第3章,理解句子结构中看到了上下文无关语法。

解析器通常以解析器树或抽象语法树的形式生成输出。让我们看看这里的一些示例解析器树。解析器使用某些语法规则来生成包含单个单词或词汇项的解析树。
Alt
让我们先讨论符号:
S 句子开始
NP 名词短语
VP 动词短语
V 动词
N 名词
ART 冠词 a, an, or the

我们还将研究自顶向下的解析器和自下而上的解析器之间的区别。
理解句法解析的概念
首先,我们来讨论解析是什么。让我们定义术语解析。解析是一种形式化的分析或过程,它使用一个句子或符号流,借助于定义好的形式语法规则,我们可以理解句子的结构和意义。因此,解析句子中的每个单词,并组成结构。什么是一致的结构?构成结构是根据观察哪个词与其他词结合形成一个合理的句子单位。所以,英语,主语,在句子中主要排在第一位;He is Tom 这个句子对我们来说是有意义的,而这个句子is Tom he,没有意义。通过解析,我们实际上检查并试图获得一个合理的组成结构。以下几点将解释句法解析和句法解析器对我们的作用:

句法解析器按照语法规则执行解析过程,并生成一个解析树。这种分析树结构用于验证句子的语法结构。如果句子的分析树遵循语法规则并生成有意义的句子,那么我们就说语法以及使用该语法生成的句子是有效的。

在句法解析结束时,将生成一个解析树作为输出,它将帮助您检测句子中的歧义,因为。模棱两可的句子常常导致多个分析树。
Alt
让我们来看看自顶向下的解析器和自下而上的解析器之间的区别:

自顶向下分析 自下而上分析
自上而下的分析是假设驱动的。 自下而上的分析是数据驱动的。
在解析的每个阶段,解析器都假定一个结构,并从句子中按顺序取一个单词,并测试所取的单词或标记是否满足假设。 在这种类型的解析中,第一个单词取自输入字符串,然后解析器检查是否存在任何预定义的类别,以生成有效的句子结构,最后,它尝试将它们组合成语法中可接受的结构。
它以从左到右的方式扫描一个句子,当语法生成规则派生出词汇项时,解析器通常会检查输入是否派生出右句子。 这种分析从终端的输入字符串开始。这种类型的分析会搜索工作字符串的子字符串,因为如果任何字符串或子字符串与语法的右侧生成规则匹配,则它会将左侧非终结符替换为匹配的右侧规则。
它包括一个回溯机制。当确定使用了错误的规则时,它会备份并尝试另一个规则。 它通常不包括回溯机制。

从头开发解析器
在本节中,我们将尝试了解最著名的斯坦福解析器的过程,以及使用哪种算法来开发最成功的统计解析器。

为了了解最后一个过程,我们首先需要了解一些构建块和概念。然后,我们将结合所有概念来理解构建统计解析器(如斯坦福解析器)的整个过程。
语法类型
我们将看到两种类型的语法,它们将帮助我们理解解析器如何工作的概念。作为一个先决条件,我们将简单地解释它们,避免对主题太过深入。我们将使它们尽可能简单,我们将探索概念的基本直觉,这些概念将用于理解开发解析器的过程。

上下文无关语法

概率上下文无关文法
上下文无关语法
我们已经在第三章“句子的理解结构”中看到了上下文无关语法的基本概念。我们已经看到了CFG的正式定义。现在,我们将了解在构建解析器时语法规则的重要性。

CFG也称为短语结构语法。因此,CFG和短语结构语法是两个术语,但指的是一个概念。现在,让我们看一些与这种语法类型相关的例子,然后讨论遵循的约定,以便生成更自然的语法规则形式。语法规则、词汇和句子如下图:
Alt

概率上下文无关文法

Alt

计算树的概率
如果我们想计算一棵树的概率,这是很容易的,因为你需要乘以词汇和语法规则的概率值。这将给我们一棵树的概率。
Alt
P(t1) = 1.0 * 0.7 * 0.4 * 0.5 * 0.6 * 0.7 * 1.0 * 0.2 * 1.0 * 0.7 * 0.1 = 0.0008232
Alt
P(t2) = 0.00024696
计算字符串的概率
计算字符串的概率比计算树的概率更复杂。这里,我们要计算单词串的概率,为此,我们需要考虑所有可能的树结构,它们生成我们要计算概率的字符串。我们首先需要考虑将字符串作为树的一部分的所有树,然后通过添加不同的概率来计算最终概率,以生成最终概率值。P(S) = P(t1) +P(t2)
= 0.0008232 + 0.00024696
= 0.00107016
语法转换
语法转换是一种使语法更具限制性的技术,它使解析过程更加高效。我们将使用Chomsky Normal Form(CNF)来转换语法规则。让我们先研究一下CNF,然后再看一个例子。X-> Y Z or X-> w where X, Y, Z ε N and w ε T规则的含义很简单。在任何语法规则的右侧不应该有两个以上的非终结点;可以包括规则右侧有一个终结点的规则。要将现有语法转换为CNF,可以遵循以下基本过程:

可以使用递归函数删除空规则和一元规则

N元规则通过在语法规则中引入新的非终结点来划分。这适用于在右侧具有两个以上非终结点的规则。使用CNF时,可以使用新的转换规则获得相同的字符串,但其解析结构可能不同。应用CNF后新生成的语法也是CFG。

在现实生活中,不需要使用完整的CNF,这样做通常会非常痛苦。它只是让解析更高效,语法规则更清晰。在实际应用中,我们将一元规则作为语法规则,因为它们告诉我们一个单词是作为动词还是名词来对待,以及非终端符号信息,这意味着我们拥有词性标注的信息。
用Cocke-Kasami-Younger算法开发一个解析器
在计算机科学领域,CYK算法(也称为Cocke–Younger–Kasami算法)是一种用来对 上下文无关文法(CFG,Context Free Grammar)进行语法分析(parsing)的算法。该算法最早由John Cocke, Daniel Younger and Tadao Kasami分别独立提出,其中John Cocke还是1987年度的图灵奖得主。CYK算法是基于动态规划思想设计的一种自底向上语法分析算法。对于英语语言,有很多解析器可以使用,如果你想为任何其他语言构建一个解析器,你可以使用cocke-kasami-younger(CKY)算法。在这里,我们将查看一些在生成解析器方面对您有用的信息。我们还将研究CKY算法的主要逻辑。

我们需要先看看我们正在考虑的假设,然后再开始使用算法。我们的技术假设是,这里的每个解析器子树都是独立的。这意味着,如果我们有一个树节点np,那么我们只关注这个np节点,而不是它的派生节点;每个子树独立工作。
一步一步开发解析器
1、您应该标记具有人工注释解析树的语料库:如果它是按照Penn-TreeBank注释格式标记的,那么您就可以开始了。
2、有了这个标记的解析语料库,您可以派生语法规则并为每个语法规则生成概率。
3、您应该应用CNF进行语法转换
4、使用概率语法规则并将其应用于大型语料库;使用Viterbi最大分数的CKY算法获得最可能的解析结构。如果您提供了大量的数据,那么您可以使用ML学习技术,将此问题作为一个多类分类器问题来处理。
5、最后一个阶段是根据概率值为给定数据获取最佳的解析树。
现有的分析器工具

斯坦福解析器(https://stanfordnlp.github.io/CoreNLP/)

from stanfordcorenlp import StanfordCoreNLP
 
nlp = StanfordCoreNLP(r'E:\JavaLibraries\stanford-corenlp-full-2018-10-05')
#这里改成你stanford-corenlp所在的目录
sentence = 'The boy put tortoise on the rug.'
print('Tokenize:', nlp.word_tokenize(sentence)) 
print('Part of Speech:', nlp.pos_tag(sentence)) 
print('Named Entities:', nlp.ner(sentence)) 
print('Constituency Parsing:', nlp.parse(sentence))
print('Dependency Parsing:', nlp.dependency_parse(sentence)) 
 
nlp.close() # Do not forget to close! The backend server will consume a lot memery.

Tokenize: ['The', 'boy', 'put', 'tortoise', 'on', 'the', 'rug', '.']
Part of Speech: [('The', 'DT'), ('boy', 'NN'), ('put', 'VBD'), ('tortoise', 'NN'), ('on', 'IN'), ('the', 'DT'), ('rug', 'NN'), ('.', '.')]
Named Entities: [('The', 'O'), ('boy', 'O'), ('put', 'O'), ('tortoise', 'O'), ('on', 'O'), ('the', 'O'), ('rug', 'O'), ('.', 'O')]
Constituency Parsing: (ROOT
  (S
    (NP (DT The) (NN boy))
    (VP (VBD put)
      (NP (NN tortoise))
      (PP (IN on)
        (NP (DT the) (NN rug))))
    (. .)))
Dependency Parsing: [('ROOT', 0, 3), ('det', 2, 1), ('nsubj', 3, 2), ('dobj', 3, 4), ('case', 7, 5), ('det', 7, 6), ('nmod', 3, 7), ('punct', 3, 8)]

如果要分析中文句子可以使用下面的代码:

# _*_coding:utf-8_*_
 
# Other human languages support, e.g. Chinese
 
sentence = '清华大学位于北京。'
 
with StanfordCoreNLP(r'E:\JavaLibraries\stanford-corenlp-full-2018-10-05', lang='zh') as nlp:
    print(nlp.word_tokenize(sentence))
    print(nlp.pos_tag(sentence))
    print(nlp.ner(sentence))
    print(nlp.parse(sentence))
    print(nlp.dependency_parse(sentence))
['清华', '大学', '位于', '北京', '。']
[('清华', 'NR'), ('大学', 'NN'), ('位于', 'VV'), ('北京', 'NR'), ('。', 'PU')]
[('清华', 'ORGANIZATION'), ('大学', 'ORGANIZATION'), ('位于', 'O'), ('北京', 'STATE_OR_PROVINCE'), ('。', 'O')]
(ROOT
  (IP
    (NP (NR 清华) (NN 大学))
    (VP (VV 位于)
      (NP (NR 北京)))
    (PU 。)))
[('ROOT', 0, 3), ('compound:nn', 2, 1), ('nsubj', 3, 2), ('dobj', 3, 4), ('punct', 3, 5)]

另外:启动CoreNLP服务器命令
在windows中,cmd中
cd E:\JavaLibraries\stanford-corenlp-full-2018-10-05

进入到Stanford CoreNLP目录中执行该命令
java -mx4g -cp “*” edu.stanford.nlp.pipeline.StanfordCoreNLPServer -port 9000 -timeout 15000

现在我们可以使用如下的代码来调用这个server:

# coding=utf-8
 
from stanfordcorenlp import StanfordCoreNLP
nlp = StanfordCoreNLP('http://localhost', port=9000)
#这里改成了我们server的地址
sentence = 'Functions shall be declared at file scope.'
print(nlp.word_tokenize(sentence))
print(nlp.pos_tag(sentence))
print(nlp.ner(sentence))
print(nlp.parse(sentence))
print(nlp.dependency_parse(sentence))
nlp.close()
['Functions', 'shall', 'be', 'declared', 'at', 'file', 'scope', '.']
[('Functions', 'NNS'), ('shall', 'MD'), ('be', 'VB'), ('declared', 'VBN'), ('at', 'IN'), ('file', 'NN'), ('scope', 'NN'), ('.', '.')]
[('Functions', 'O'), ('shall', 'O'), ('be', 'O'), ('declared', 'O'), ('at', 'O'), ('file', 'O'), ('scope', 'O'), ('.', 'O')]
(ROOT
  (S
    (NP (NNS Functions))
    (VP (MD shall)
      (VP (VB be)
        (VP (VBN declared)
          (PP (IN at)
            (NP (NN file) (NN scope))))))
    (. .)))
[('ROOT', 0, 4), ('nsubjpass', 4, 1), ('aux', 4, 2), ('auxpass', 4, 3), ('case', 7, 5), ('compound', 7, 6), ('nmod', 4, 7), ('punct', 4, 8)]

Spacy解析器

pip install spacy  (原因是因为spacy2.0版本的模块路径(spacy/lang/en);而spacy1.9版本不会报这种错误。)
python -m spacy download en
import spacy
from spacy.en import English
parser = English()
nlp = spacy.load('en')
example = u"The boy with the spotted dog quickly ran after the firetruck."
document = nlp(example)

这个 document 现在是 spacy.english 模型的一个 class,并关联上了许多的属性。它会输出 document 中各种各样的属性,例如:token、token 的 index、词性标注、实体、向量、情感、单词等。下面让我们会对其中的一些属性进行一番探究。

  • Tokenization

spaCy 的 document 可以在 tokenized 过程中被分割成单句,这些单句还可以进一步分割成单词。你可以通过遍历文档来读取这些单词:

document[0]
The
document[len(document)-5]
ran
list(document.sents)
[The boy with the spotted dog quickly ran after the firetruck.]
  • 词性标注

词性标注即标注语法正确的句子中的词语的词性。这些标注可以用于信息过滤、统计模型,或者基于某些规则进行文本解析。

all_tags = {
   
   w.pos: w.pos_ for w in document}
all_tags
{82: 'ADJ',
 83: 'ADP',
 84: 'ADV',
 88: 'DET',
 90: 'NOUN',
 95: 'PUNCT',
 98: 'VERB'}
for word in 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值