[译] 天然语言处理真是有趣!

计算机如何理解人类的语言

计算机擅长处理结构化的数据,像电子表格和数据库表之类的。可是咱们人类的平常沟通是用词汇来表达的,而不是表格,对计算机而言,这真是件棘手的事。html

遗憾的是,咱们并非生活在到处都是结构化数据的时代。前端

这个世界上的许多信息都是非结构化的 —— 不只仅是英语或者其余人类语言的原始文本。咱们该如何让一台计算机去理解这些非结构化的文本而且从中提取信息呢?python

天然语言处理,简称 NLP,是人工智能领域的一个子集,目的是为了让计算机理解并处理人类语言。让咱们来看看 NLP 是如何工做的,而且学习一下如何用 Python 写出可以从原始文本中提取信息的程序。android

注意:若是你不关心 NLP 是如何工做的,只想剪切和粘贴一些代码,直接跳过至“用 Python 处理 NLP 管道”部分。ios

计算机能理解语言吗?

自从计算机诞生以来,程序员们就一直尝试去写出可以理解像英语这样的语言的程序。这其中的缘由显而易见 —— 几千年来,人类都是用写的方式来记录事件,若是计算机可以读取并理解这些数据将会对人类大有好处。git

目前,计算机还不能像人类那样彻底了解英语 —— 但它们已经能作许多事了!在某些特定领域,你能用 NLP 作到的事看上去就像魔法同样。将 NLP 技术应用到你的项目上可以为你节约大量时间。程序员

更好的是,在 NLP 方面取得的最新进展就是能够轻松地经过开源的 Python 库好比 spaCytextacyneuralcoref 来进行使用。你须要作的只是写几行代码。github

从文本中提取含义是很难的

读取和理解英语的过程是很复杂的 —— 即便在不考虑英语中的逻辑性和一致性的状况下。好比,这个新闻的标题是什么意思呢?web

环境监管机构盘问了非法烧烤的业主。(“Environmental regulators grill business owner over illegal coal fires.”)算法

环境监管机构就非法燃烧煤炭问题对业主进行了询问?或者按照字面意思,监管机构把业主烤了?正如你所见,用计算机来解析英语是很是复杂的一件事。

在机器学习中作一件复杂的事一般意味着建一条管道。这个办法就是将你的问题分红细小的部分,而后用机器学习来单独解决每个细小的部分。再将多个相互补充的机器学习模型进行连接,这样你就能搞定很是复杂的事。

并且这正是咱们将要对 NLP 所使用的策略。咱们将理解英语的过程分解为多个小块,并观察每一个小块是如何工做的。

一步步构建 NLP 管道

让咱们看一段来自维基百科的文字:

伦敦是英格兰首都,也是英国的人口最稠密的城市。伦敦位于英国大不列颠岛东南部泰晤士河畔,两千年来一直是一个主要定居点。它是由罗马人创建的,把它命名为伦蒂尼恩。(London is the capital and most populous city of England and the United Kingdom. Standing on the River Thames in the south east of the island of Great Britain, London has been a major settlement for two millennia. It was founded by the Romans, who named it Londinium.)

(来源:维基百科“伦敦”

这段文字包含了几个有用的信息。若是电脑可以阅读这段文字而且理解伦敦是一个由罗马人创建的,位于英国的城市等等,那就最好不过了。可是要达到这个要求,咱们须要先将有关书面知识的最基本的概念传授给电脑,而后不断深刻。

步骤一:语句分割

在管道中所要作的第一件事就是将这段文字分割成独立的句子,由此咱们能够获得:

  1. “伦敦是英国的首都,也是英格兰和整个联合王国人口最稠密的城市。(London is the capital and most populous city of England and the United Kingdom.)”
  2. “位于泰晤士河流域的伦敦,在此后两个世纪内为这一地区最重要的定居点之一。(Standing on the River Thames in the south east of the island of Great Britain, London has been a major settlement for two millennia.)”
  3. 它由罗马人创建,取名为伦蒂尼恩。(It was founded by the Romans, who named it Londinium.)”

咱们假设每个句子都表明一个独立的想法。那么相较于能理解整篇文章的程序而言,咱们能够更加容易地写出可以理解独立语句的程序。

建立一个语句分割模型就像使用标点符号来分割语句同样简单。可是现代 NLP 管道一般须要更加复杂的技术来解决文档排版不整齐的状况。

第二步:文字符号化

如今咱们已经把文档分割成了句子,咱们能够一步一步地处理这些句子,让咱们从文档中的第一个句子开始:

“London is the capital and most populous city of England and the United Kingdom.”

下一步就是在管道中将这个句子分割成独立的词语或符号。这就称做分词。接下来看看对这个句子分词的结果:

“London”, “is”, “ the”, “capital”, “and”, “most”, “populous”, “city”, “of”, “England”, “and”, “the”, “United”, “Kingdom”, “.”

分词在英语中是容易完成的。咱们只要分割那些空格分隔的词语。咱们也将标点符号做为单词,由于它们也具备含义。

第三步:猜想每一个词的属性

接下来,咱们须要猜想一下每个词的属性 —— 名词,动词和形容词等等。知道每一个词在句子中所扮演的角色以后,就可以帮助咱们推断句子的含义。

要知道词的属性,咱们能够将每一个词(包括一些上下文的词)提供给预先训练的词性分类模型:

词性分类模型在最初经过数百万个英语句子的训练,这些句子中每一个词的属性都已经被标记,并以此让模型学会复制这种标记的行为。

记住,这个模型是基于统计数据的 —— 它并非以和人类同样的方式理解词的含义。它所知道的只是如何依靠以前标记的相似单词和句子来猜想语句的含义。

在处理完整个句子以后,咱们会得出这样的结果:

根据这些信息,咱们已经可以开始搜集一些很是基础的含义。好比,这个句子中的名词包括“伦敦”和“首都”,因此这个句子极有多是与伦敦有关的。

第四步:文本词形还原

在英语(以及其它大多数语言)中,词语以不一样的形式出现。来看看下面这两个句子:

I had a pony.

I had two ponies.

两句话都讲到了名词小马 (pony),可是它们有着不一样的词形变化。知道词语的基本形式对计算机处理文本是有帮助的,这样你就能知道两句话在讨论同一个概念。不然,“pony” 和 “ponies” 对于电脑来讲就像两个彻底不相关的词语。

在 NLP 中,咱们称这个过程为词形还原 —— 找出句子中每个词的最基本的形式或词元

对于动词也同样。咱们也可以经过寻找动词最初的非结合形式来进行词形还原。因此 “I had two ponies” 变为 “I [have] two [pony]”。

词形还原通常是经过具备基于其词性的词汇形式的查找表来完成工做的,而且可能具备一些自定义的规则来处理以前从未见过的词语。

这就是通过词形还原添加动词最初形式的句子:

惟一变化的地方就是将 “is” 变为 “be”。

第五步:识别终止词

接下来,咱们须要考虑句子中的每一个单词的重要性。英语有不少频繁出现的填充词好比 “and”、“the” 和 “a”。 在对文本进行统计的时候,随着这些词出现频率的升高,将会出现不少歧义。一些 NLP 管道将这些词语标记为“终止词” —— 在进行任何分析以前须要过滤掉的词语。

这就是将终止词过滤掉以后的句子:

终止词的识别一般是由查询一个硬编码的已知终止词列表来完成。可是不存在对于全部应用来讲通用的标准终止词列表。这个列表极大程度上是由你的应用所决定的。

举个例子,若是你正在创建一个与摇滚乐队有关的搜索引擎,须要确保你没有忽略单词 “The”。不只是由于这个单词出如今不少乐队名中,并且还有一个 80 年代的著名摇滚乐队叫作 The The

第六步:依存语法解析

下一步就是找出句子中的每个词之间的依存关系,这就作依存语法解析

目标就是构建一棵树,为句子中的每个词赋予一个父类词语。树的根是句子中的主要动词。根据这个句子构造的解析树的开头就是这个样子:

但咱们还能够作的更多。为了识别每个词的父类词,咱们还能够预测这两个词之间存在的关系:

这颗解析树为咱们展现了这个句子的主体是名词伦敦,并且它和首都之间有着 be 关系。咱们最终发现了一些有用的信息 —— 伦敦是一个首都!若是咱们遵循着这个句子的整颗解析树(不只是图示信息),甚至可以发现伦敦是英国的首都。

就像咱们早前使用机器学习模型来预测词性那样,以将词语输入机器学习模型并输出结果的方式来完成依存语法分析。 可是分析依存语法是一项十分复杂的任务,它须要用一整篇文章来做为分析某些细节的上下文。 若是你很好奇它是如何工做的,有一篇做者为 Matthew Honnibal 的优秀文章值得一读 用 500 行 Python 代码来解析英语 (Parsing English in 500 Lines of Python)

可是尽管这位做者在 2015 年发表了一条说明称这种方法如今已成为标准,但它已通过时甚至再也不被做者使用过。在 2016 年,谷歌推出了一种新的依存语法分析方法,称为 Parsey McParseface,它采用了一种新的深度学习方法,超越了以前的表现,并在业界内快速流传。一年以后,他们又发布了新的模型,称为 ParseySaurus,对某些方面作了进一步改善。换句话说,解析技术依旧是搜索领域的一项热门技术,而且在不断地变化和改进。

不少英语语句是十分模糊且难以解析的,这一点须要牢记在心。在那些例子中,模型会根据以前解析过的最类似的句子来进行猜想,但这并不完美,有时这个模型会产生使人尴尬的错误。但随着时间的推移,咱们的 NLP 模型将会继续以合理的方式更好地解析文本。

想要在你本身的句子上试一试依存语法解析吗?这是来自 spaCy 团队的一个很棒的互动演示

第六步(下):查找名词短语

到如今为止,咱们将句子中的每个词语都做为一个独立的实体。但有时将一些词语链接起来可以更加合理地表达一个想法或事件。咱们可以用依存关系解析树中的信息来自动地将全部阐述相同事物的词语组合在一块儿。

举个例子,好比这一个:

咱们能够将名词短语组合在一块儿达到这样的结果:

咱们要根据最终目标来决定是否要进行这一步。可是若是咱们并不须要获得哪些词是形容词这些额外细节而是更关注抽取句子中的完整含义,这一般是简化句子一个简单的方法。

第七步:命名实体识别(NER)

如今咱们已经完成全部困难的工做,终于能够抛弃书面的语法并开始动手实现想法了。

在咱们的句子中,有着如下名词:

这些名词中,有一部分与实际意义相同。好比说“伦敦”、“英格兰”和“英国”表明了地图上的物理位置。若是能检测到这些那真是太棒了!有了这些信息,咱们就可以使用 NLP 在自动地提取一个在文档中说起的真实世界地理位置列表。

命名实体识别NER)的目标就是为了检测和标记这些表明真实世界中某些事物的名词。在使用咱们的 NER 标记模型对句子中的每一个词语进行处理以后,句子就变成这样:

但 NER 系统并不仅是作这些简单的查找字典的工做。而是使用某个词语在句子中的上下文以及统计模型来猜想某个词语表明哪一种类型的名词。一个优秀的 NER 系统可以根据上下文线索辨别出人名 “Brooklyn Decker” 和 地名 “Brooklyn”。

这些是经典的 NER 系统可以标记的事物:

  • 人名
  • 公司名
  • 地理位置(物理位置和政治位置)
  • 产品名称
  • 日期和时间
  • 金额
  • 事件名称

自从 NER 可以帮助轻易地从文本中获取结构化数据,便被普遍使用。它是从 NLP 管道中得到结果的最便捷途径之一。

想本身试一试专名识别技术吗?这是来自 spaCy 团队的另外一个很棒的互动演示

第八步:共指解析

在此刻,咱们已经对句子有了充分的了解。咱们了解了每一个词语的词性、词语之间的依存关系以及哪些词语是表明命名实体的。

但是,咱们还须要解决一个大问题。英语中存在着大量的代词 —— 好比。这些是咱们对在句子中反复出现的名称的简化。人们可以根据上下文来获得这些词表明的内容。可是咱们的 NLP 模型并不知道这些代词的含义,由于它每次只检查一个句子。

来看看咱们的文档中的第三个句子:

“It was founded by the Romans, who named it Londinium.”

若是咱们用 NLP 管道解析这个句子,咱们就能知道“它”是由罗马人创建的。但若是能知道“伦敦”是由罗马人创建的那会更有用。

当人们读这个句子时,可以很容易得出“它”表明“伦敦”。共指解析的目的是根据整个句子中的代词来找出这种相同的映射。咱们是想要找出全部指向同一实体的词语。

这就是在咱们的文档中对“伦敦”使用共指解析的结果:

将共指信息、解析树和命名实体信息结合在一块儿,咱们就可以从这个文档中提取出不少信息!

共指解析是咱们正在进行工做的管道中的最艰难步骤之一。它甚至比语句解析还要困难。深度学习的最新进展带来更精确的方法,但它还不够完美。若是你想多了解一下它是如何工做的,从这里开始

想要参与协做共指解析?看看这个来自 Hugging Face 的协做共指解析演示

用 Python 来构建 NLP 管道

这是咱们的完整 NLP 管道的概览:

共指解析是一项并不总要完成的可选步骤。

哎呀,有好多步骤啊!

注意:在咱们往下看以前,值得一提的是,这些都是构建传统 NLP 管道的步骤,你能够根据你的目的以及如何实现你的 NLP 库来决定是跳过仍是重复某些步骤。举个例子,一些像 spaCy 这样的库,是先使用依存语法解析,得出结果后再进行语句分割。

那么,咱们该如何构建这个管道?多谢像 spaCy 这样神奇的 python 库,管道的构建工做已经完成!全部的步骤都已完成,时刻准备为你所用。

首先,假设你已经安装了 Python 3,你能够按以下步骤来安装 spaCy:

# 安装 spaCy 
pip3 install -U spacy

# 下载针对 spaCy 的大型英语模型
python3 -m spacy download en_core_web_lg

# 安装一样大有用处的 textacy
pip3 install -U textacy
复制代码

在一段文档中运行 NLP 管道的代码以下所示:

import spacy

# 加载大型英语模型
nlp = spacy.load('en_core_web_lg')

# 咱们想要检验的文本
text = """London is the capital and most populous city of England and the United Kingdom. Standing on the River Thames in the south east of the island of Great Britain, London has been a major settlement for two millennia. It was founded by the Romans, who named it Londinium. """

# 用 spaCy 解析文本. 在整个管道运行.
doc = nlp(text)

# 'doc' 如今包含了解析以后的文本。咱们能够用它来作咱们想作的事!
# 好比,这将会打印出全部被检测到的命名实体:
for entity in doc.ents:
    print(f"{entity.text} ({entity.label_})")
复制代码

若是你运行了这条语句,你就会获得一个关于文档中被检测出的命名实体和实体类型的表:

London (GPE)  
England (GPE)  
the United Kingdom (GPE)  
the River Thames (FAC)  
Great Britain (GPE)  
London (GPE)  
two millennia (DATE)  
Romans (NORP)  
Londinium (PERSON)
复制代码

你能够查看每个实体代码的含义

须要注意的是,它误将 “Londinium” 做为人名而不是地名。这多是由于在训练数据中没有与之类似的内容,不过它作出了最好的猜想。若是你要解析具备专业术语的文本,命名实体的检测一般须要作一些微调

让咱们把这实体检测的思想转变一下,来作一个数据清理器。假设你正在尝试执行新的 GDPR 隐私条款而且发现你所持有的上千个文档中都有我的身份信息,例如名字。如今你的任务就是移除文档中的全部名字。

若是将上千个文档中的名字手动去除,须要花上好几年。但若是用 NLP,事情就简单了许多。这是一个移除检测到的名字的数据清洗器:

import spacy

# 加载大型英语 NLP 模型
nlp = spacy.load('en_core_web_lg')

# 若是检测到名字,就用 "REDACTED" 替换
def replace_name_with_placeholder(token):
    if token.ent_iob != 0 and token.ent_type_ == "PERSON":
        return "[REDACTED] "
    else:
        return token.string

# 依次解析文档中的全部实体并检测是否为名字
def scrub(text):
    doc = nlp(text)
    for ent in doc.ents:
        ent.merge()
    tokens = map(replace_name_with_placeholder, doc)
    return "".join(tokens)

s = """ In 1950, Alan Turing published his famous article "Computing Machinery and Intelligence". In 1957, Noam Chomsky’s Syntactic Structures revolutionized Linguistics with 'universal grammar', a rule based system of syntactic structures. """

print(scrub(s))
复制代码

若是你运行了这个,就会看到它如预期般工做:

In 1950, [REDACTED] published his famous article "Computing Machinery and Intelligence". In 1957, [REDACTED]   
Syntactic Structures revolutionized Linguistics with 'universal grammar', a rule based system of syntactic structures.
复制代码

信息提取

开箱即用的 spaCy 能作的事实在是太棒了。但你也能够用 spaCy 解析的输出来做为更复杂的数据提取算法的输入。这里有一个叫作 textacy 的 python 库,它实现了多种基于 spaCy 的通用数据提取算法。这是一个良好的开端。

它实现的算法之一叫作半结构化语句提取。咱们用它来搜索解析树,查找主体为“伦敦”且动词是 “be” 形式的简单语句。这将会帮助咱们找到有关伦敦的信息。

来看看代码是怎样的:

import spacy
import textacy.extract

# 加载大型英语 NLP 模型
nlp = spacy.load('en_core_web_lg')

# 须要检测的文本
text = """London is the capital and most populous city of England and the United Kingdom. Standing on the River Thames in the south east of the island of Great Britain, London has been a major settlement for two millennia. It was founded by the Romans, who named it Londinium. """

# 用 spaCy 来解析文档
doc = nlp(text)

# 提取半结构化语句
statements = textacy.extract.semistructured_statements(doc, "London")

# 打印结果
print("Here are the things I know about London:")

for statement in statements:
    subject, verb, fact = statement
    print(f" - {fact}")
复制代码

它打印出了这些:

Here are the things I know about London:

 - the capital and most populous city of England and the United Kingdom.  
- a major settlement for two millennia.
复制代码

也许这不会太使人印象深入。但若是你将这段代码用于维基百科上关于伦敦的整篇文章上,而不仅是这三个句子,就会获得使人印象十分深入的结果:

Here are the things I know about London:

 - the capital and most populous city of England and the United Kingdom  
 - a major settlement for two millennia  
 - the world's most populous city from around 1831 to 1925 - beyond all comparison the largest town in England - still very compact - the world's largest city from about 1831 to 1925  
 - the seat of the Government of the United Kingdom  
 - vulnerable to flooding  
 - "one of the World's Greenest Cities" with more than 40 percent green space or open water  
 - the most populous city and metropolitan area of the European Union and the second most populous in Europe  
 - the 19th largest city and the 18th largest metropolitan region in the world  
 - Christian, and has a large number of churches, particularly in the City of London  
 - also home to sizeable Muslim, Hindu, Sikh, and Jewish communities  
 - also home to 42 Hindu temples  
 - the world's most expensive office market for the last three years according to world property journal (2015) report - one of the pre-eminent financial centres of the world as the most important location for international finance - the world top city destination as ranked by TripAdvisor users - a major international air transport hub with the busiest city airspace in the world - the centre of the National Rail network, with 70 percent of rail journeys starting or ending in London - a major global centre of higher education teaching and research and has the largest concentration of higher education institutes in Europe - home to designers Vivienne Westwood, Galliano, Stella McCartney, Manolo Blahnik, and Jimmy Choo, among others - the setting for many works of literature - a major centre for television production, with studios including BBC Television Centre, The Fountain Studios and The London Studios - also a centre for urban music - the "greenest city" in Europe with 35,000 acres of public parks, woodlands and gardens - not the capital of England, as England does not have its own government 复制代码

如今事情变得有趣了起来!咱们自动收集了大量的信息。

为了让事情变得更有趣,试试安装 neuralcoref 库而且添加共指解析到你的管道。这将为你提供更多的信息,由于它会捕捉含有“它”的而不是直接表示“伦敦”的句子。

咱们还能作什么?

看看这个 spaCy 文档textacy 文档,你会发现不少可以用于解析文本的方法示例。目前咱们所看见的只是一个小示例。

这里有另一个实例:想象你正在构建一个可以向用户展现咱们在上一个例子中提取出的全世界城市的信息的网站。

若是你的网站有搜索功能,能像谷歌那样可以自动补全常规的查询就太好了:

谷歌对于“伦敦”的自动补全建议

若是这么作,咱们就须要一个可能提供给用户的建议列表。咱们可使用 NLP 来快速生成这些数据。

这是从文档中提取经常使用名词块的一种方式:

import spacy
import textacy.extract

# 加载大型英语 NLP 模型
nlp = spacy.load('en_core_web_lg')

# 须要检测的文档
text = """London is the capital and most populous city of England and the United Kingdom. Standing on the River Thames in the south east of the island of Great Britain, London has been a major settlement for two millennia. It was founded by the Romans, who named it Londinium. """

# 用 spaCy 解析文档
doc = nlp(text)

# 提取半结构化语句
statements = textacy.extract.semistructured_statements(doc, "London")

# 打印结果
print("Here are the things I know about London:")

for statement in statements:
    subject, verb, fact = statement
    print(f" - {fact}")
复制代码

若是你用这段代码来处理维基百科上关于伦敦的文章,就会获得以下结果:

westminster abbey  
natural history museum  
west end  
east end  
st paul's cathedral royal albert hall london underground great fire british museum london eye .... etc .... 复制代码

更进一步

这只是你能够用 NLP 作到的事中的一个小示例。在之后的文章中,咱们将会谈论一些其余的应用,例如文本分类或亚马逊 Alexa 系统是如何解析问题的。

但目前要作的事,就是安装 spaCy 并使用它。若是你不是 Python 程序员而且使用不一样的 NLP 库,这种想法应该也能奏效。

若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

相关文章
相关标签/搜索