深度学习处理文本(1)

发布于:2025-03-31 ⋅ 阅读:(29) ⋅ 点赞:(0)

自然语言处理概述

在计算机科学领域,我们将人类语言(如英语或普通话)称为“自然”语言,以区别于为机器设计的语言(如汇编语言、LISP或XML)​。每一种机器语言都是设计出来的:人类工程师写下一组正式规则,描述用这种语言可以编写哪些语句以及这些语句的含义。**规则在先,只有这组规则是完备的,人们才会开始使用这种语言。**人类语言正好相反:**使用在先,规则出现在后。自然语言是进化形成的,就像生物体一样,这是我们称其为“自然语言”的原因。**自然语言的“规则”​(比如英语语法)是在事后确立的,而且经常被使用者忽视或破坏。因此,虽然机器可读语言是严格、高度结构化的,使用明确的句法规则将固定词表中准确定义的概念组合在一起,但自然语言是模糊、混乱、不断扩展的,并且还在不断变化。创建出能够理解自然语言的算法,是一件很重要的事情:语言(特别是文本)是我们大多数交流与文化的基础。互联网上大多是文本。语言是我们存储几乎所有知识的方式。我们的思想在很大程度上建立在语言之上。但长期以来,理解自然语言的能力一直是机器所无法实现的。有人曾天真地认为,可以简单地写出“英语规则集”​,就像写出LISP规则集一样。因此,早期人们在尝试构建自然语言处理(natural language processing,NLP)系统时,都是从“应用语言学”的视角进行的。工程师和语言学家手动编写复杂的规则集,以实现初级的机器翻译或创建简单的聊天机器人,比如20世纪60年代著名的ELIZA程序,可以使用模式匹配来进行非常简单的对话。但是,语言是一种叛逆的事物,很难被形式化所束缚。经过人们数十年的努力,这些系统的能力仍然令人失望。直到20世纪90年代,手动编写规则一直都是主流方法。但从20世纪80年代末开始,由于出现了更快的计算机和更多的可用数据,一种更好的替代方法开始变得可行。如果你发现自己构建的系统包含大量特定规则,那么作为聪明的工程师,你可能会问:​“我能否使用数据语料库来自动寻找这些规则?我能否在某个规则空间内搜索规则,而不必自己想出这些规则?​”提出这些问题,你就已经开始做机器学习了。因此,在20世纪80年代末,人们开始将机器学习方法应用于自然语言处理。最早的方法是基于决策树,其目的是自动开发先前系统中的那种if/then/else规则。随后,从logistic回归开始,统计学方法开始加速发展。随着时间的推移,参数学习模型完全占据主导地位,语言学被看作一种障碍而不是有用的工具。早期的语音识别专家Frederick Jelinek在20世纪90年代开玩笑说:​“每次我解雇一名语言学家,语音识别的性能都会提高一些。​”这就是现代自然语言处理:利用机器学习和大型数据集,让计算机可以不对语言进行理解(这是一个更崇高的目标)​,而是接收一段语言作为输入,并返回一些有用的内容,比如预测以下内容:“这段文本的主题是什么?​”​(文本分类)“这段文本是否包含脏话?​”​(内容过滤)“这段文本是积极的还是消极的?​”​(情感分析)“这是一个不完整的句子,下一个词应该是什么?​”​(语言模型)“这用德语怎么说?​”​(翻译)“你会如何用一段话来概括这篇文章?​”​(摘要)在阅读本章时请记住,你训练的文本处理模型并不会像人类一样理解语言;相反,模型只是在输入数据中寻找统计规律。事实证明,这足以在许多简单任务上表现很好。计算机视觉是应用于像素的模式识别,与此类似,自然语言处理是应用于单词、句子和段落的模式识别。

自然语言处理的工具集—决策树、logistic回归—从20世纪90年代到21世纪10年代初只经历了缓慢的发展。当时的研究重点大多在特征工程上。然而,在2014年~2015年,事情终于开始发生变化。很多研究人员开始研究RNN的语言理解能力,特别是LSTM,它是一个源自20世纪90年代末的序列处理算法,直到那时才开始受到关注。2015年初,人们刚刚开始对RNN重新产生巨大的兴趣。Keras提供了第一个开源、易于使用的LSTM实现。在此之前只有“研究代码”​,无法被轻易复用。然后从2015年~2017年,RNN主导了蓬勃发展的自然语言处理领域,特别是双向LSTM模型,它在许多重要的任务(从摘要到问题回答再到机器翻译)上达到了最先进的水平。在2017年~2018年,一种新的架构取代了RNN,它就是Transformer。Transformer在很短时间内就在整个领域取得了巨大进展,如今大多数自然语言处理系统是基于Transformer的。我们来深入了解细节。本章内容既涵盖基础知识,也包括用Transformer做机器翻译。

准备文本数据

深度学习模型是可微函数,只能处理数值张量,不能将原始文本作为输入。文本向量化是指将文本转换为数值张量的过程。文本向量化有许多种形式,但都遵循相同的流程,如图11-1所示。首先,将文本标准化,使其更容易处理,比如转换为小写字母或删除标点符号。然后,将文本拆分为单元[称为词元(token)],比如字符、单词或词组。这一步叫作词元化。最后,将每个词元转换为一个数值向量。这通常需要首先对数据中的所有词元建立索引。我们来详细看一下每个步骤。

在这里插入图片描述

文本标准化

我们来看下面这两个句子。两句话的意思相同:​“日落来临。我凝视着墨西哥的天空。大自然难道不美好吗?​”不过,标点、大小写等存在细微差异。——译者注“sunset came. i was staring at the Mexico sky. Isnt nature splendid??”“Sunset came; I stared at the México sky. Isn’t nature splendid?”两个句子非常相似——事实上,它们几乎完全相同。然而,如果将它们转换成字节串,会得到非常不同的表示,因为“i”和“I”是不同的字符,​“Mexico”和“México”是不同的单词,​“Isnt”不同于“Isn’t”​,等等。机器学习模型不会预先知道“i”和“I”是同一个字母、​“é”是带有重音符的“e”​,以及“staring”和“stared”是同一个动词的两种形式。文本标准化是一种简单的特征工程,旨在消除你不希望模型处理的那些编码差异。它不是机器学习所特有的,如果你想搭建一个搜索引擎,那么也需要做同样的事情。

最简单也是最广泛使用的一种标准化方法是:将所有字母转换为小写并删除标点符号。这样前面的两个句子就会变为:“sunset came i was staring at the mexico sky isnt nature splendid”“sunset came i stared at the méxico sky isnt nature splendid”两个句子更加相似了。另一种常见的变换是将特殊字符转换为标准形式,比如将“é”转换为“e”​、将“æ”转换为“ae”等。这样一来,词元“méxico”就会转换为“mexico”​。最后还有一种更高级的标准化方法,但在机器学习中很少使用,它就是词干提取(stemming)​:将一个词的变体(比如动词的不同变位)转换为相同的表示,比如将“caught”和“been catching”转换为“​[catch]​”​,或者将“cats”转换为“​[cat]​”​。使用词干提取之后,​“was staring”和“stared”就都会转换为“​[stare]​”​,这样前面两个相似的句子就会变成相同的编码:“sunset came i [stare] at the mexico sky isnt nature splendid”

使用这些标准化方法之后,模型将需要更少的训练数据,并且具有更好的泛化效果。模型不需要很多“Sunset”和“sunset”的示例就可以知道二者含义相同,并且即使在训练集中只见过“mexico”​,也可以理解“México”​。当然,标准化也可能会删掉一些信息,所以要始终牢记任务背景。举个例子,如果你的模型要从采访文章中提取出问题,那么你肯定应该将“​?​”作为单独的词元,而不应删掉它,因为它对这项特定任务来说很有用。

文本拆分(词元化)

完成文本标准化之后,你需要将文本拆分成能够向量化的单元(词元)​,这一步叫作词元化。词元化有以下3种方法。单词级词元化(word-level tokenization)​:词元是以空格(或标点)分隔的子字符串。这种方法的一个变体是将部分单词进一步拆分成子词,比如将“staring”拆分成“star+ing”​,或者将“called”拆分成“call+ed”​。N 元语法词元化(N-gram tokenization)​:词元是N个连续单词,比如“the cat”或“he was”都是二元语法词元。字符级词元化(character-level tokenization)​:每个字符都是一个词元。我们在实践中很少采用这种方法,只有在专门的领域才会用到,比如文本生成或语音识别。一般来说,你可以一直使用单词级词元化或N元语法词元化。有两种文本处理模型:一种是关注词序的模型,叫作序列模型(sequence model)​;另一种将输入单词作为一个集合,不考虑其原始顺序,叫作词袋模型(bag-of-words model)​。如果要构建序列模型,则应使用单词级词元化;如果要构建词袋模型,则应使用N元语法词元化。N元语法可以手动向模型注入少量局部词序信息。我们将介绍这两种模型及其使用场景。

理解N元语法和词袋

单词N元语法是从一个句子中提取的N个(或更少)连续单词的集合。这一概念中的“单词”也可以替换为“字符”​。下面来看一个简单的例子。对于句子“The cat sat on the mat”​(猫坐在垫子上)​,它可以分解为以下二元语法的集合。

{"the", "the cat", "cat", "cat sat", "sat",
 "sat on", "on", "on the", "the mat", "mat"}

这个句子也可以分解为以下三元语法的集合。

{"the", "the cat", "cat", "cat sat", "the cat sat",
 "sat", "sat on", "on", "cat sat on", "on the",
 "sat on the", "the mat", "mat", "on the mat"}

这样的集合分别叫作二元语法袋(bag-of-2-grams)和三元语法袋(bag-of-3-grams)​。袋(bag)这一术语指的是,我们处理的是词元组成的集合,而不是列表或序列,也就是说,词元没有特定的顺序。这种词元化方法叫作词袋(bag-of-words)或N元语法袋(bag-of-N-grams)​。词袋是一种不保存顺序的词元化方法(生成的词元是一个集合,而不是一个序列,舍弃了句子的总体结构)​,因此它通常用于浅层的语言处理模型,而不是深度学习模型。提取N元语法是一种特征工程,深度学习序列模型不需要这种手动方法,而是将其替换为分层特征学习。一维卷积神经网络、RNN和Transformer都可以通过观察连续的单词序列或字符序列来学习单词组或字符组的数据表示,而无须明确知道这些组的存在。