智客公社

标题: 这把神器,让你用 Python 一口吻掌握 53 种自然言语处理 [打印本页]

作者: 邦枝5葵    时间: 2019-6-25 17:57
标题: 这把神器,让你用 Python 一口吻掌握 53 种自然言语处理

导语:不久之前,斯坦福大学公开了它最新的自然言语处理代码库—— StanfordNLP。它不但包含了残缺的语义分析工具链,还带有 73 个不同的高精度神经网络模型,能解析 53 种不同的人类言语。是不是很牛×啊?明天的教程里,我就手把手带你在 Python 上运用 StanfordNLP,停止一些自然言语处理实战。

[attach]158512[/attach]



在学习自然言语处理(NLP)的过程中,我们常常会遇到这样一个成绩:“我们能不能为除英语之外的其他言语构建模型呢?”在很长一段工夫里,这都是一个难以完成的义务。要知道,每种言语都有本人独特的语法形式和纤细的言语差别,而且除了英语之外,其他言语的数据集真实是少之又少。

但如今,我们有了 StanfordNLP 这一神器。

当我第一次看到 StanfordNLP 的引见时,我几乎无法抑制本人的激动之情。作者宣称它可以支持超过 53 中不同的人类言语!(没错,你没看错,的确是 53 种……我当时也觉得本人一定是眼花了。)

在 StanfordNLP 的官方网站上,作者列出了目前支持的一切 53 种人类言语,其中包含了许多其他 NLP 库所没有的言语,比如印地语、日语和我们最爱的中文。这几乎是为我们打开了通往有限能够的新世界的大门啊!

[attach]158513[/attach]



StanfordNLP 到底是何方神圣,我为啥需求用它?

简单地说,StanfordNLP 是一系列预训练好的,高程度的神经网络模型。目前的 73 个模型都是来自 2017、18 年 CoNLL 会议上的研讨者。它们都是用 PyTorch 训练而来的,你也可以用本人的语料库来训练和评价它们,是不是很酷炫?

[attach]158514[/attach]



此外,StanfordNLP 还包含了一个官方的 CoreNLP 封装。CoreNLP 作为一款广受好评的史诗级 NLP 库,在此之前,你只能依托 Java 才能用上它。对有兴味的读者,我建议你看看这个教程,了解更多有关 CoreNLP 的信息,以及它在 Python 中的工作原理。

对 NLP 爱好者来说,真是没有比这个更棒的了。如今,就让我们在 Python 中实践操作一下吧!

小编预备了一份Python学习材料,给那些正在学习Python的同窗,或者预备学习Python的同窗,关注,分享,私信小编“01”即可收费获取!

[attach]158515[/attach]



在 Python 中安装设置 StanfordNLP 库

最后,这个库里有一些奇异的东西,让我感到非常困惑。例如,你需求运用 Python 3.6 / 3.7 或更高版本才能运用 StanfordNLP。为了安全起见,我在 Anaconda 中设置了一个单独的 Python 3.7.1 环境。详细步骤如下:
1、打开 conda 命令行,输入:
conda create -n stanfordnlp python=3.7.1
普通来说一路 yes 到底即可。
接着激活刚建立的环境:
conda activate stanfordnlp
conda 4.6 或更高版本可以用:
source activate stanfordnlp
在新环境里安装 StanfordNLP 库:
pip install stanfordnlp


接上去,我们需求下载对应自然言语的模型。打开一个 Python 命令行,导入 StanfordNLP 库:
import stanfordnlp
接着下载对应的言语模型,以英语(“en”)为例:
stanfordnlp.download('en')
根据你网络速度的不同,这能够需求花费一些工夫。普通来说你得下载大概 300M 的内容。

一些留意事项
StanfordNLP 是基于 PyTorch 1.0.0 构建的。假如你尝试在更早的版本上运转它,能够会遇到一些奇异的成绩。你可以在命令行运转这样的命令来检查你的 PyTorch 版本:
pip freeze | grep torch


正常状况下你应该看到相似 torch==1.0.0 这样的输入。
我试过在没有独立显示芯片的机器上跑这个库,比如我的联想 Thinkpad E470(8G 内存,英特尔核显)。
结果是,Python 很快就甩了一个 memory error 给我。因此,我换到一台有独立显卡的机器下去运转这些代码,我激烈建议你也这么做。
对了,你可以试试 Google 出品的地表最强 Python 编辑器——Google Colab,它提供了 12-14G 的内存,以及收费的 GPU 算力。

好啦,说了这么多,你应该曾经装好了相关的库和模型了吧?让我们试着末尾一些基本的 NLP 处理吧。

运用 StanfordNLP 完成简单的 NLP 义务

假设我们要分析一段英文材料,首先,我们需求建立一个文字处理管道(pipeline):
nlp
=
stanfordnlp
.
Pipeline
(
processors
=

"tokenize,mwt,lemma,pos"
)
doc
=
nlp
(
"""The prospects for Britain’s orderly withdrawal from the European Union
on March 29 have receded further, even as MPs rallied to stop a no-deal scenario.
An amendment to the draft bill on the termination of London’s membership of the
bloc obliges Prime Minister Theresa May to renegotiate her withdrawal agreement
with Brussels. A Tory backbencher’s proposal calls on the government to come up
with alternatives to the Irish backstop, a central tenet of the deal Britain agreed
with the rest of the EU."""
)

我们经过 processors="" 参数指定需求分析的详细义务。假如不传入任何参数,程序将默许调用全部 5 个处理模块停止分析。详细可见下表:



[attach]158516[/attach]





表格内容翻译自 StanfordNLP 项目主页

让我们在实战中检验一下这些分析器吧。

分词处理

当 TokenizeProcessor 运转的时分,分词处理过程将在后台运转,理想上,它的处理速度相当快。你可以运用 print_tokens() 方法来查看分词结果:
doc
.
sentences
[
0
].
print_tokens
()



[attach]158517[/attach]





结果就相似下面这样。每个 token 对象都包含了句子中每个词的索引,以及一个包含了 Word 对象的列表(以防有一些由多个单词/字组成的短语/词组。每一个 Word 对象都包含了详细的信息,包括序号、单词原形、词性、形状特征等标签。

词形还原

这就要用到 LemmaProcessor 给每个 Word 对象生成的 lemma 属性了(参见下面分词结果图中的 lemma= 部分)。我们只需求简单的几行代码就可以对一切单词停止词形还原:
# 文件名: lemma.py
import
pandas
as
pd
def
extract_lemma
(
doc
):
parsed_text
=

{
'word'
:[],

'lemma'
:[]}

for
sent
in
doc
.
sentences
:

for
wrd
in
sent
.
words
:

# 提取文本和原形
parsed_text
[
'word'
].
append
(
wrd
.
text
)
parsed_text
[
'lemma'
].
append
(
wrd
.
lemma
)

# 前往值是一个 DataFrame 对象

return
pd
.
DataFrame
(
parsed_text
)
extract_lemma
(
doc
)

这将前往一个 pandas 的数据表(DataFrame 对象),列出了每个单词及其对应的单词原形:



[attach]158518[/attach]





词性分析与标注

用于词性分析的 POSProcessor 可以又快又准地处理多种不同言语。和词形还原一样,词性分析的标签也很容易读取和输入:
# 文件名: parts_of_speech.py
# 定义一个存放 POS 值及对应词性描画的字典对象
pos_dict
=

{

'CC'
:

'coordinating conjunction'
,

'CD'
:

'cardinal digit'
,

'DT'
:

'determiner'
,

'EX'
:

'existential there (like: \"there is\" ... think of it like \"there exists\")'
,

'FW'
:

'foreign word'
,

'IN'
:

'preposition/subordinating conjunction'
,

'JJ'
:

'adjective \'big\''
,

'JJR'
:

'adjective, comparative \'bigger\''
,

'JJS'
:

'adjective, superlative \'biggest\''
,

'LS'
:

'list marker 1)'
,

'MD'
:

'modal could, will'
,

'NN'
:

'noun, singular \'desk\''
,

'NNS'
:

'noun plural \'desks\''
,

'NNP'
:

'proper noun, singular \'Harrison\''
,

'NNPS'
:

'proper noun, plural \'Americans\''
,

'PDT'
:

'predeterminer \'all the kids\''
,

'POS'
:

'possessive ending parent\'s'
,

'PRP'
:

'personal pronoun I, he, she'
,

'PRP$'
:

'possessive pronoun my, his, hers'
,

'RB'
:

'adverb very, silently,'
,

'RBR'
:

'adverb, comparative better'
,

'RBS'
:

'adverb, superlative best'
,

'RP'
:

'particle give up'
,

'TO'
:

'to go \'to\' the store.'
,

'UH'
:

'interjection errrrrrrrm'
,

'VB'
:

'verb, base form take'
,

'VBD'
:

'verb, past tense took'
,

'VBG'
:

'verb, gerund/present participle taking'
,

'VBN'
:

'verb, past participle taken'
,

'VBP'
:

'verb, sing. present, non-3d take'
,

'VBZ'
:

'verb, 3rd person sing. present takes'
,

'WDT'
:

'wh-determiner which'
,

'WP'
:

'wh-pronoun who, what'
,

'WP$'
:

'possessive wh-pronoun whose'
,

'WRB'
:

'wh-abverb where, when'
,

'QF'

:

'quantifier, bahut, thoda, kam (Hindi)'
,

'VM'

:

'main verb'
,

'PSP'

:

'postposition, common in indian langs'
,

'DEM'

:

'demonstrative, common in indian langs'
}
def
extract_pos
(
doc
):
parsed_text
=

{
'word'
:[],

'pos'
:[],

'exp'
:[]}

for
sent
in
doc
.
sentences
:

for
wrd
in
sent
.
words
:

if
wrd
.
pos
in
pos_dict
.
keys
():
pos_exp
=
pos_dict
[
wrd
.
pos
]

else
:
pos_exp
=

'NA'
parsed_text
[
'word'
].
append
(
wrd
.
text
)
parsed_text
[
'pos'
].
append
(
wrd
.
pos
)
parsed_text
[
'exp'
].
append
(
pos_exp
)

return
pd
.
DataFrame
(
parsed_text
)
extract_pos
(
doc
)

留意到下面那个宏大的字典对象了吗?那是为了把词性分析的标签和人类能懂的描画逐一对应起来。这能让我们更好地了解文件的语法结构。

程序将输入一个数据表对象,其中包含 3 列:单词(Word)、词性(pos)以及对应的解释(exp)。解释列中的内容包含了最多的语义信息,也是对我们最有用的部分。



[attach]158519[/attach]



添加了解释列之后,我们就能更容易地看出分析器处理词句时的准确性如何。让我欣喜的是,绝大部分的词语都可以被正确地标记起来,它甚至能正确地判别出一个词的时态和词性,包括它是单数还是复数方式等。

依存关系解析

依存关系解析也是 StanfordNLP 里开箱即用的工具之一。你只需求在程序中调用 print_dependencies() 方法,就能方便地获取到句子中一切元素的依存关系:
doc
.
sentences
[
0
].
print_dependencies
()



[attach]158520[/attach]



总的来说,程序将在一次管道处理过程中计算上述的每一个步骤。对于能运用 GPU 的机器来说,整个运算过程普通要不了几分钟就能搞定。

于是,我们曾经摸清了用 StanfordNLP 库完成简单文字处理义务的基本操作,如今我们该试试在各种不同言语上停止异样的操作啦!

对印地语运用 StanfordNLP 停止处理

StanfordNLP 在处理功能和多言语文本解析支持方面都拥有非常突出的表现。我们如今就来深化研讨一下后面这部分。

处理印地语文字(梵文文本)

首先,我们先下载印地语的模型(相对来说小多了!):
stanfordnlp
.
download
(
'hi'
)

接着,把一段印地语文字放出来,作为目的文本:
hindi_doc
=
nlp
(
"""केंद्र की मोदी सरकार ने शुक्रवार को अपना अंतरिम बजट पेश किया. कार्यवाहक वित्त मंत्री पीयूष गोयल ने अपने बजट में किसान, मजदूर, करदाता, महिला वर्ग समेत हर किसी के लिए बंपर ऐलान किए. हालांकि, बजट के बाद भी टैक्स को लेकर काफी कन्फ्यूजन बना रहा. केंद्र सरकार के इस अंतरिम बजट क्या खास रहा और किसको क्या मिला, आसान भाषा में यहां समझें"""
)

要生成一切的标签,这样就曾经足够了,让我们检查一下吧:
extract_pos
(
hindi_doc
)



[attach]158521[/attach]



毫不不测,词性分析器很完美地处理了印地语文本。看看这个“अपना”吧,词性分析器指出这是个人称代词(我、他、她),这还是比较准确的。

调用 CoreNLP 的 API 停止文字分析

CoreNLP 是一个久经考验的工业级自然言语处理工具集,它的高功能和准确性都是相当有名的。要想调用 CoreNLP 复杂的 API,你只需求在 StanfordNLP 里写上三行代码。你没看错,的确只需求 3 行代码就能设置好了!
1、~~打开冰箱门~~ 不,是下载 CoreNLP 包。打开你的 Linux 终端,输入以下命令:
wget http://nlp.stanford.edu/software/stanford-corenlp-full-2018-10-05.zip


2、解压下载好的软件包:
unzip stanford-corenlp-full-2018-10-05.zip


3、启动 CoreNLP 服务器:
java -mx4g -cp "*" edu.stanford.nlp.pipeline.StanfordCoreNLPServer -port 9000 -timeout 15000

留意: CoreNLP 需求 Java8 才能运转,请务必确保你曾经安装好了 JDK 和 JRE 1.8.x 以上版本。

接着,你需求让 StanfordNLP 获取到 CoreNLP 所在的途径。你需求把 CoreNLP 的途径写入环境变量 $CORENLP_HOME 中。在我下面的例子中,CoreNLP 所在的文件夹是直接放在用户的 home 目录中,所以我的环境变量是这样:
export
CORENLP_HOME
=
stanford
-
corenlp
-
full
-
2018
-
10
-
05
/

下面的预备工作完成之后,你就可以启动服务进程,并用 Python 代码给它发送央求。接上去,我们将启动服务器,设置客户端,发送处理央求,并最后从前往的对象中获取所需的数据。让我们一同看看这个综合性的实例吧。

1. 构建一个 CoreNLP 客户端
# 文件名: corenlp_setup.py
from
stanfordnlp
.
server
import

CoreNLPClient
# 输入实例文本
print
(
'---'
)
print
(
'input text'
)
print
(
''
)
text
=

"Chris Manning is a nice person. Chris wrote a simple sentence. He also gives oranges to people."
print
(
text
)
# 显示服务器启动信息
print
(
'---'
)
print
(
'starting up Java Stanford CoreNLP Server...'
)
# 启动客户端进程
with

CoreNLPClient
(
annotators
=[
'tokenize'
,
'ssplit'
,
'pos'
,
'lemma'
,
'ner'
,
'depparse'
,
'coref'
],
timeout
=
30000
,
memory
=
'16G'
)

as
client
:

# 把处理央求发送给服务器
ann
=
client
.
annotate
(
text
)

# 获取前往对象的第 1 个句子
sentence
=
ann
.
sentence
[
0
]

2. 依存关系分析及词性分析
# 文件名: corenlp_depparse.py

# 获取第 1 个句子的依存关系

print
(
'---'
)

print
(
'dependency parse of first sentence'
)
dependency_parse
=
sentence
.
basicDependencies

print
(
dependency_parse
)

# 获取第 1 个句子中的第 1 个词

print
(
'---'
)

print
(
'first token of first sentence'
)
token
=
sentence
.
token
[
0
]

print
(
token
)

# 词性分析结果

print
(
'---'
)

print
(
'part of speech tag of token'
)
token
.
pos

print
(
token
.
pos
)

3. 命名实体辨认(NER)与共指链(Co-Reference Chains)的解析
# 文件名: corenlp_ner.py
# 获取命名实体标签

print
(
'---'
)

print
(
'named entity tag of token'
)

print
(
token
.
ner
)

# 获取句子中的第 1 个实体指称语(entity mention)

print
(
'---'
)

print
(
'first entity mention in sentence'
)

print
(
sentence
.
mentions
[
0
])

# 获取共指链

print
(
'---'
)

print
(
'coref chains for the example'
)

print
(
ann
.
corefChain
)

# 用正则表达式模板查找 wrote 对应的主语
pattern
=

'([ner: PERSON]+) /wrote/ /an?/ []{0,3} /sentence|article/'
matches
=
client
.
tokensregex
(
text
,
pattern
)

# sentences 中包含了每一条婚配到的句子

assert
len
(
matches
[
"sentences"
])

==

3

# 检查 length 的值,你就知道能否有成功婚配到

assert
matches
[
"sentences"
][
1
][
"length"
]

==

1

# 像大部分正则分组一样,你可以直接获取婚配到的文字
matches
[
"sentences"
][
1
][
"0"
][
"text"
]

==

"Chris wrote a simple sentence"
matches
[
"sentences"
][
1
][
"0"
][
"1"
][
"text"
]

==

"Chris"

# 还可以用 semgrex 表达式直接查找结果
pattern
=

'{word:wrote} >nsubj {}=subject >dobj {}=object'
matches
=
client
.
semgrex
(
text
,
pattern
)

# sentences 中包含了每一条婚配到的句子

assert
len
(
matches
[
"sentences"
])

==

3

# 检查 length 的值,你就知道能否有成功婚配到

assert
matches
[
"sentences"
][
1
][
"length"
]

==

1

# 像大部分正则分组一样,你可以直接获取婚配到的文字
matches
[
"sentences"
][
1
][
"0"
][
"text"
]

==

"wrote"
matches
[
"sentences"
][
1
][
"0"
][
"$subject"
][
"text"
]

==

"Chris"
matches
[
"sentences"
][
1
][
"0"
][
"$object"
][
"text"
]

==

"sentence"

在 Python 中运用 CoreNLP 的时分,我最喜欢的就是它带来的方便与易用。

个人以为,StanfordNLP 的优势与不足之处

思索到将来的运用前景,StanfordNLP 最让我兴奋的优势有:

但是,还是有一些成绩需求处理。以下是我对 StanfordNLP 需求改进的地方的看法:

最后,希望你仔细地看一看 StanfordNLP 的官方文档——从本文发布到如今,说不定又有新的变化了呢。

结语

就目前来说,相似 CoreNLP 这样神奇的工具正在积极拥抱 Python 软件生态系统,斯坦福这样的科研巨头也正在努力开源他们的软件,这让我对将来抱着悲观的态度。

的确,StanfordNLP 刚发布 0.2.0 版本不久。虽然这次的版本分明地减少了模型大小,加快了速度,但它可改进的空间还很大。再思索到有斯坦福“官方”加持,它将来一定会愈加完善,愈加弱小。所以,如今正是末尾学习运用它的最佳机遇——为什么不快人一步,提早掌握这项技能呢?
作者: yeederjon    时间: 2019-6-26 07:38
边撸边过
作者: 难有一曲钟萦耳    时间: 2019-6-27 07:56
支持,赞一个
作者: 小冷子    时间: 2019-6-28 07:24
顶起顶起顶起




欢迎光临 智客公社 (http://bbs.cnaiplus.com/) Powered by Discuz! X3.4