自然语言处理实战项目
1950年,艾伦·图灵(Alan Turing)发表了一篇题为“ 计算机机械与智能(Computing Machinery and Intelligence) ” 的文章,提出了著名的“图灵测试(Turing Test)”。这当中涉及了自动解释和自然语言的生成,作为判断智能的条件,这就是自然语言处理(Natural Language Processing,NLP)发展的开端。
自然语言处理是计算机科学和人工智能(artificial intelligence,AI)的一个研究领域,它关注自然语言(如英语或汉语普通话)的处理。这种处理通常包括将自然语言转换成计算机能够用于理解这个世界的数据(数字)。同时,这种对世界的理解有时被用于生成能够体现这种理解的自然语言文本(即自然语言生成)。
语言的发明是为了便于沟通交流,是人类建立共识的基础。而现在,奋斗在自然语言处理技术的程序员们都有一个目标:让计算机也能理解人类的语言。
NLP的魅力——创造会交流的机器
自从计算机被发明出来,机器一直在处理语言。然而,这些“形式”语言(如早期语言Ada、COBOL和Fortran)被设计成只有一种正确的解释(或编译)方式。
目前,维基百科列出了700多种编程语言。相比之下,Ethnologue已经确认的自然语言总数是当前世界各地人们所用的自然语言的10倍。谷歌的自然语言文档索引远超过1亿吉字节,而且这只是索引而已,当前在线的实际自然语言内容大小肯定超过1000亿吉字节,同时这些文档并没有完全覆盖整个互联网。
“自然语言”与“自然世界”中“自然”一词的意义相同。世界上自然的、进化的事物不同于人类设计和制造的机械的、人工的东西。能够设计和构建软件来阅读和处理大家现在正在阅读的语言,该语言正是关于如何构建软件来处理自然语言的,这非常高级,也十分神奇。
起初,Google等搜索网站需要一些技巧才能找到我们要找的东西,但很快就变得更加智能了,可以接受越来越多的词汇搜索。然后智能手机的文字自动补全功能开始变得先进起来,中间按钮给出的通常就是我们要找的词。这些就是自然语言处理的魅力——让机器理解我们的想法。
越来越多的娱乐、广告和财务报告内容在不需要人动一根手指的情况下就可以生成。NLP机器人可以编写整个电影脚本。视频游戏和虚拟世界经常会出现与我们对话的机器人,它们有时甚至会谈论机器人和人工智能本身。这种“戏中戏”将得到更多的关于电影的元数据,然后现实世界中的机器人会据此撰写评论以帮助大家决定看哪部电影。
随着NLP技术的发展,信息流和计算能力也不断增强。我们现在只需在搜索栏中输入几个字符,就可以检索出完成任务所需的准确信息。搜索提供的前几个自动补全选项通常非常合适,以至于让我们感觉是有一个人在帮助我们进行搜索。
入门NLP的几个基础知识
1.正则表达式
正则表达式使用了一类特殊的称为正则语法(regular grammar)的形式语言语法。正则语法的行为可预测也可证明,而且足够灵活,可以支持市面上一些最复杂的对话引擎和聊天机器人。Amazon Alexa和Google Now都是依赖正则语法的主要基于模式的对话引擎。深奥、复杂的正则语法规则通常可以用一行称为正则表达式的代码来表示。Python中有一些成功的聊天机器人框架,如Will,它们完全依赖这种语言来产生一些有用的和有趣的行为。Amazon Echo、Google Home和类似的复杂而又有用的助手也都使用了这种语言,为大部分用户交互提供编码逻辑。
2.词序和语法
词的顺序很重要。那些在词序列(如句子)中控制词序的规则被称为语言的语法(grammar,也称文法)。这是之前的词袋或词向量例子中所丢弃的信息。幸运的是,在大多数简短的短语甚至许多完整的句子中,上述词向量近似方法都可以奏效。如果只是想对一个短句的一般意义和情感进行编码的话,那么词序并不十分重要。看一下“Good morning Rosa”这个例子中的所有词序结果:
>>> from itertools import permutations>>>
[" ".join(combo) for combo in\... permutations("Good morning Rosa!".split(), 3)]['Good morning Rosa!',
'Good Rosa! morning',
'morning Good Rosa!',
'morning Rosa! Good',
'Rosa! Good morning',
'Rosa! morning Good']
现在,如果试图孤立地解释这些字符串中的每一个(不看其他字符串),那么可能会得出结论,即这些字符串可能都有相似的意图或含义。我们甚至可能注意到Good这个词的大写形式,并把它放在脑海中短语的最前面。但是我们也可能认为Good Rosa是某种专有名词,如餐馆或花店的名字。尽管如此,一个聪明的聊天机器人或者布莱切利公园20世纪40年代的聪明女士可能会用同样无伤大雅的问候语来回应这6种情况中的任何一种:“Good morning my dear General.”
我们(在脑海中)再用一个更长、更复杂的短语来尝试一下,这是一条逻辑语句,其中词的顺序非常重要:
>>> s = """Find textbooks with titles containing 'NLP',
... or 'natural' and 'language', or
... 'computational' and 'linguistics'."""
>>> len(set(s.split()))12
>>> import numpy as np
>>> np.arange(1, 12 + 1).prod()
# factorial(12) = arange(1, 13).prod()479001600
词排列的数量从简单的问候语factorial(3)
== 6激增到更长的语句factorial(12)
== 479001600
很明显,词序所包含的逻辑对任何希望正确回复的机器而言都很重要。尽管普通的问候语通常不会因为词袋处理而造成混淆,但如果把更复杂的语句放入词袋中,就会丢失大部分意思。就像前面示例中的自然语言查询一样,词袋并不是处理数据库查询的最佳方式。
3.词向量
2012年,微软实习生Thomas Mikolov发现了一种用一定维度的向量表示词的含义的方法。Mikolov训练了一个神经网络来预测每个目标词附近的共现词。2013年,Mikolov和他的队友在谷歌发布了创建这些词向量的软件,称为Word2vec。
Word2vec仅仅基于大型未标记文本语料库来学习词的含义,而不需要标记Word2vec词汇表中的词。我们不需要告诉Word2vec算法玛丽·居里是一个科学家、伐木者是一个足球队、西雅图是一个城市、波特兰是俄勒冈州和缅因州的一个城市,也不需要告诉Word2vec足球是一项运动、一个团队是一群人,或者城市既是地点也是社区。Word2vec完全可以靠自己学到更多的知识!大家需要做的只是准备一个足够大的语料库,其中在科学、足球或城市相关的词附近提到玛丽·居里、伐木者队和波特兰。
正是Word2vec这种无监督的特性使它无比强大,因为世界上充满了未标记、未分类、非结构化的自然语言文本。
4.Word2vec和GloVe
Word2vec是一个巨大的突破,但它依赖于必须经反向传播来训练的神经网络模型。反向传播在效率上通常不如使用梯度下降法直接优化的代价函数。由Jeffrey Pennington领导的斯坦福大学NLP研究团队研究了Word2vec的工作原理,并从中找到可优化的代价函数。他们计算词的共现次数并记录在一个正方形矩阵中。他们发现可以对这个共现矩阵进行奇异值分解,分解得到的两个权重矩阵的意义与Word2vec产生的完全相同。关键点在于用同样的方法对共现矩阵进行归一化。在某些情况下,Word2vec模型无法收敛,而斯坦福大学的研究人员能够通过他们提出的SVD方法得到全局最优解。这个方法是对词共现的全局向量(在整个语料库中的共现)直接进行优化,因此命名为GloVe(global vectors of word co-occurrences)。
GloVe可以产生相当于Word2vec输入权重矩阵和输出权重矩阵的矩阵,其生成的语言模型具有与Word2vec相同的精确率,而且花费的时间更少。GloVe通过更高效地使用数据来加速训练进程。它可以在较小的语料库进行训练,并仍然能够收敛。SVD算法已经改进了几十年,所以GloVe在调试和算法优化方面很有优势。相比之下,Word2vec依赖反向传播来更新表示词嵌入的权重,而神经网络的反向传播效率低于GloVe使用的SVD这种更成熟的优化算法。
尽管Word2vec首先普及了基于词向量进行语义推理的概念,不过大家还是应当尽量使用GloVe来训练新的词向量模型。通过GloVe,大家更有可能找到词向量表示的全局最优解,从而得到更精确的结果。
GloVe的优点如下:
1.训练过程更快;
2.更有效地利用CPU、内存(可以处理更大规模的文档);
3.更有效地利用数据(对小型语料库有帮助);
4.在相同训练次数的情况下精确率更高。
5.知识方法
A.L.I.C.E.和其他AIML聊天机器人完全依赖模式匹配。在构想AIML之前,第一个流行的聊天机器人ELIZA也使用了模式匹配和模板。但是这些聊天机器人的开发人员在模式和模板中硬编码了回复的逻辑。硬编码不能很好地“扩展”,这种扩展不是从处理性能而是从人力的角度来说的。以这种方式构建的聊天机器人的复杂性随着投入人力的增加呈线性增长。事实上,随着这个聊天机器人的复杂性不断增长,我们开始看到自己努力的回报却在递减,这是因为随着“活动组件”之间交互的增加,聊天机器人的行为变得越来越难以预测和调试。
如今,数据驱动编程是应对大多数复杂编程挑战的现代方法。如何使用数据对聊天机器人进行编程?在上一章中,我们学习了如何使用信息提取从自然语言文本(非结构化数据)中创建结构化知识。仅仅基于读入文本,就可以构建关系或事实组成的网络,这些文本可以是维基百科文章,甚至是大家自己的个人日志。
通过逻辑推理来处理知识图谱,可以回答包含在知识库中的世界相关的问题。然后可以使用推理答案填写模板化回复中的变量,从而创建自然语言答案。问答系统,例如IBM在Jeopardy获胜的“沃森”(Watson),最初也是以这种方式构建的,尽管最近的版本几乎必然也采用了搜索或信息检索技术。知识图谱可以说是将聊天机器人带到现实世界的“根本”。
基于知识库的方法不仅限于回答关于世界的问题。知识库也可以使用正在进行的与对话相关的事实进行实时填充。这可以让聊天机器人快速了解对话目标以及他们的喜好。
6.检索(搜索)方法
另一种“倾听”用户的数据驱动方法是在历史对话日志中搜索之前的语句。这类似于人类倾听者尝试回想之前他们在哪里听到过该问题、句子或词。机器人不仅可以搜索自己的对话日志,还可以搜索任何人与人之间的对话记录、机器人和人之间的对话记录,甚至是机器人和机器人之间的对话记录。但和以往一样,脏数据进脏数据出。因此,我们应该清理并整合历史对话的数据库,以确保机器人搜索(并模仿)高质量的对话。我们希望人类享受与机器人之间的对话。
基于搜索的聊天机器人应确保其对话数据库包含令人愉快或有用的对话,并且它们应该是设定个性的机器人预期交流的一些主题。对于基于搜索的机器人,一些好的对话资源例子包括电影对话脚本、IRC频道上的客户服务日志(用户满意的部分)和人类之间的直接消息互动(如果那些人愿意与我们分享的话)。如果没有获得想要使用的对话中涉及的所有人的书面同意,请不要使用大家自己的电子邮件或短消息日志。
如果决定将机器人之间的对话合并到语料库中,那么请千万小心。我们的数据库中只需要那些至少有一个人看起来对交互感到满意的语句,哪怕只是继续对话。除非是真正非常智能的聊天机器人,否则很少采用机器人之间的对话。
基于搜索的聊天机器人可以使用历史对话日志来查找和机器人的交谈对象刚刚说的话类似的语句示例。为了便于搜索,应该把对话语料库组织成语句-回复对。如果回复作为被回复的语句,那么该回复应该在数据库中出现两次,一次作为回复,然后再作为促使回复的语句。数据库表中的回复列随后可作为“语句”(或促使)列的语句的回复依据。