上一章我们讲到,卷积神经网络(CNN)的出现带动了计算机视觉领域的
巨大发展,同时也让世人看到了深度学习的无限潜力。自从在数字图像处理领
域取得巨大的成功以后,人们就在想,既然CNN的数据处理能力这么强,能不
能尝试将其用在自然语言处理领域来帮助计算机理解文本内容呢?一旦实现,
意味着计算机能够像人类一样阅读文字,理解文字的含?,向真正的人工智能
迈出了一大步。
在自然语言处理这门学科中有一类任务称为“统计语言模型”,这是一种
用于计算某个句子合理排列方式的模型。利用语言模型,可以确定哪组词序列
的排列更合理,或者给定一个句子中的若干词,预测?一个最可能出现的词。
语言模型在实际项目中的应用非常广泛,例如语音转文本,若计算机检测到的
音节为“xixi”,则可能对应的中文为“嘻嘻”“嬉戏”“淅淅”等词,这时
候语言模型就可以根据整个句子表达的意思选择可能性最大的候选词;又或者
用于图像中的文字识别,有些字变形或者有些字的角度倾斜、被遮挡,都可以
用语音模型来选择正确的字。试想如果语言模型采用CNN技术,该如何实现
呢?
举个例子,我们告诉计算机:“马儿在小溪旁喝水,一直以来全靠这条小
溪滋养了__。”前面输入了一段文本,希望让计算机帮我们补全空白处缺失的
词。在这个例子中,空白处缺失的词最有可能是“马儿”或者“它”,不太可
能是“我”“小李”或“大地”这些词。
早期在使用CNN解决这个问题时,很容易会想到使用图像处理的思路,即
检测邻近像素点的变化,构建边缘线条,根据边缘线条在第二层检测出一些简
单的形状,然后基于这些形状检测出更高级的特征,比如脸部轮廓等。因此在
文本处理中,我们也尝试用邻近的单词推测附近单词可能出现的取值,采用N-
Gram模型,N为自然数,可以是2或者3。也就是说模型假定这个空缺的单词只
与这个词前面2个词或3个词相关。
我 们 以 2-Gram 模 型 为 例 , 提 取 原 句 中 空 白 处 的 前 两 个 单 词 “ 滋
养”“了”,计算机会在语料库中快速搜寻这两个单词后面最可能出现的单
词。如果只看这两个单词,无论如何也不会得出“马儿”这样的答案,因为忽
略了句子一开始的关键信息。如果采用 3-Gram,增加“小溪”这个单词,同
样也不会得到我们想要的答案。这时候很多读者会想,只要继续提高N的值不
就好了,把N值扩大到13不就能获取到句子的关键信息了吗?但实际上这种改
进没有任何意?,如果想处理任意长度的句子,那么N值设为多少都不合适。
为什么卷积的方式到了文本中就不太适用了呢?
细想,在图像处理中,相邻的像素点大概率互相关联,因为它们描述的都
是同一个物体的一部分。但是在文本中,尤其是在一个句子中,前一个单词对
于当前单词的词性推断其实是有很大影响的,例如“游戏”这个词既是名词又
是动词,如果前面一个词是“玩”,那么很显然这里的“游戏”就是一个名
词。并且句子中每个单词的词性、表达的含?也远比图像复杂得多,例如“水
份”一词放在不同的场景?表达的意思也不同,不像计算机视觉一样直观。
也就是说,在传统的卷积神经网络中,输入和输出都是相对确定的,卷积
核被设定好大小以后,其对整个图像的每个像素都适用,并且上一个输出结果
对?一个输出结果没有任何影响。但是在文本中,当我们理解一句话的意思
时,孤立理解每个单词的意思是不够的,我们需要处理的是这些词语连接起来
的完整内容。在计算机中,这种前后数据有关联的内容是一种特殊的“时间序
列数据”。时间序列数据是指在不同时间点上收集到的数据,这类数据反映了
某一事物、现象等随时间变化的状态或程度。这是时间序列数据的定?,文字
序列以及视频中由每一帧不同的画面连接起来的序列都属于特殊的时间序列数
据。
显然,传统的卷积神经网络难以解决这类训练样本输入都是长短不一的序
列的问题,并且这些序列前后之间还存在关联关系,因此卷积神经网络在自然
语言处理领域并不能再次大显身手。在这种情况?我们急需一种新的神经网络
结构,用于处理时间序列型数据。
12.2.2 循环神经网络登场
循环神经网络(Recurrent Neural Network,RNN)是一类用于处理序列
数据的神经网络。它广泛应用于自然语言处理中的语音识别、手写识别以及机
器翻译等。随着研究的深入,后来常与卷积神经网络一起,处理计算机视觉问
题。
我们知道,基础的神经网络通常包含输入层、隐藏层和输出层,并且通过
激活函数控制输出,层与层之间通过权值连接。只需要事先确定好激活函数,
神经网络通过样本训练模型就能够不断学习,改变各层之间的权值。基础的神
经网络仅仅在层与层之间建立权值连接,从输入层到隐藏层再到输出层,层与
层之间全连接,同一层内的节点无连接,如图12-1所示。

RNN最大的不同之处在于,网络会对前面的信息进行记忆并参与到当前输
出的计算中,隐藏层之间的节点不再是无连接的,且隐藏层的输入不仅包括
当前时刻输入层的输出,还包括上一时刻隐藏层的输出 。对于一段文本内容
来说,如果其被输入普通的神经网络中,每个词对应的输出结果只与这个词有
关系。但是RNN的结构经过改造后能够实现往模型中输入一段文本,每一个词
对应的输出内容不再是孤立的,而是和前面的内容存在一定的关联关系。一个
简单的循环神经网络如图 12-2 所示,它由一个输入层、一个隐藏层和一个输
出层组成。
从上图中可以发现,如果把W 的部分去掉,它就变成了一个普通的全连接
神经网络。X 是一个向量,它表示输入层的值;S 是一个向量,它表示隐藏层
的值,在图中隐藏层实际上包含了很多个节点,节点数与向量S 的维度相同;
O 也是一个向量,表示输出层的值;U 是输入层到隐藏层的权重矩阵,它将我
们的原始输入进行抽象作为隐藏层的输入。V 是隐藏层到输出层的权重矩阵,
从隐藏层学习到的信息经过它再一次被抽象,并作为最终输出。
在普通神经网络的基础上增加一个W模块就变成了RNN。怎么理解这个W模
块呢?实际上它代表网络的记?控制者,负责调度记?。循环神经网络的隐藏
层的值S 不仅仅取决于这次的输入X ,还取决于上一次隐藏层的参数S 。权重
矩阵W 就是利用隐藏层上一次的值作为这一次输入的权重的。RNN 可以被看作
对同一神经网络的多次赋值,每次赋值后计算得到的信息会被传递到?一个赋
值继续使用。所以,将这个循环展开,就是如图12-3所示的样子。
在RNN中,网络某一时刻的输入X t 是一个n维向量,和普通神经网络稍微
不同的是 RNN的输入是一整个序列,可以用 X =[X 1 ,X 2 ,X 3 ,…,X t
,X t+1 ,…,X T ]表示。对于语言模型来说,每一个X t 表示一个词向量,
一个序列表示一个完整的句子。
上文说过,CNN 通过“局部连接”和“权值共享”这两点实现相邻区域的
特征提取,而RNN则引入了“状态”的概念使前后输入数据产生关联关系。在
RNN中,输入数据后,不是通过简单的卷积就能获得输出值,而是先得出某个
状态的结果,然后再由这个状态的结果得到?一个状态的结果。如图12-3所
示,RNN在t时刻接收到输入X t 之后,隐藏层的值为S t ,输出值为O t ,关键
的一点是,S t 的值不仅仅取决于X t ,还取决于S t-1 。如此一来,两个状
态之间的结果就建立了联系,当前样本的输出结果会影响?一个样本的输出结
果,甚至影响后面很多个样本的输出结果,从而使最终结果反映出序列特征,
这就是RNN挖掘时刻数据关联的一般性思路。
事实上,我们可以把这些“状态”理解为网络结构的“记忆”。这种记
忆能帮助网络记住之前看到过的样本的关键信息,并结合最新的样本所带来
的信息来进行决策 。如果我们想预测一个句子里某个词后面一个词是什么,
我们需要知道哪些词在它前面,这些词提供了什么样的信息,而RNN可以刻画
一个序列当前的输出与之前信息的关系。
12.2.3 RNN的结构
RNN 相比普通神经网络较为灵活,普通的神经网络通常接受一个固定大小
的向量作为输入,并产生一个固定大小的向量作为输出。但是RNN在处理一个
序列数据时,可以将这个序列上不同时刻的数据依次传入循环神经网络的输入
层,而输出可以是对序列中?一个时刻数据的预测,也可以是对当前时刻信息
的处理结果。RNN 要求每一个时刻都要有输入,但不一定每个时刻都有输出。
因此,RNN 产生了多种不同的网络结构,常见的如图12-4所示。
图中每个矩形都表示一个向量。箭头表示矩阵权值,第一层为输入向量,
第三层为处理后的输出向量。(a)为基本的神经网络,其中一个固定大小的输
入对应一个固定大小的输出;(b)同样是单一输入,但输出是一个序列数据;
(c)把序列输入转化为单个输出;(d)把序列输入转化为序列输出;(e)同步的
序列输入和输出。
这几种结构分别用在什么场景?呢?
首先是“1 to N”这种情况有两种结构:一种是只在序列开始进行输入计
算;还有一种结构是把输入信息作为每个阶段的输入,如图12-5所示。这
种“1 to N”的结构可以处理很多类问题,例如图片标注,输入一张图片,而
输出的序列是一段描述这张图片的句子。也可以输入一个类别,通过模型自动
生成一段这个类别的音乐或者文字。
与此相对应的是“N to 1”结构,即输入是一个序列,但输出?是一个单
值。在这种情况?,RNN 的结构只要将前面每一个输出都去掉,在最后统一将
前面的输入转化成一个输出即可,如图 12-6 所示。这种结构通常用在情绪分
析的场景,将某个句子归类为表达积极或消极的情绪;也常用在判断视频类别
的场景,将一段视频逐帧输入模型中,来判断这段视频的类别。
第三种情况是最常见的“N to N”结构,所谓的“N to N”结构即网络的
输入序列和输出序列等长,如图12-7所示。作为一种最基础的RNN结构,“N
to N”结构也有广泛的应用。例如在机器翻译领域,用RNN模型读取一个句
子,然后用其他语言输出这个句子;或者在信息抽取的“命名实体识别”任务
中,我们需要识别某段文本中具有特定意?的实体,主要包括人名、地名、机
构名以及专有名词等,以便我们分析句子和文本的组成。
最后一种“N to M”结构是RNN的变体,这也是一种多对多模型,M通常比
N大。这种结构又称为“Encoder-Decoder模型,或叫作“Seq2Seq”模型。对
于这种情况,RNN 的做法通常是先将输入序列编码成一个上?文向量c,如图
12-8所示。
编码完成后,我们用一个RNN对向量c的结果进行解码,简单理解就是将向
量c作为初始状态的隐变量输入解码网络,其就像一座桥梁一样连接输入部分
的隐藏层以及最后输出部分的隐藏层,如图12-9所示
“N to M”结构符合我们进行序列建模的大多数情况,因此也是最常用、
最重要的 RNN 模型。在现实生活中我们遇到的绝大多数问题的输入和输出序
列都不等长 。例如在进行汉英翻译时,英语句子和翻译过来的汉语句子基本
上不是等长的。模型接收到完整的输入后才会开始输出,因为翻译后的句子的
第一个词的确定可能需要前面整个输入序列的信息。