长短时记忆网络 LSTM
长短时记忆网络(Long Short Term Memory,简称LSTM)是循环神经网络的一种,它为了解决RNN自身的缺陷,向RNN单元中引入了门机制进行改善,下面我们来看看它具体是怎么做的吧。本文内容组织如下:
1. LSTM的设计思路
在循环神经网络RNN中我们谈到,RNN不太能够保持长期的依赖,过长的信息容易导致RNN单元内部状态的混乱,导致无法准确的表达一句话的语义。
我觉得这家餐馆的菜品很不错,烤鸭非常正宗,包子也不错,酱牛肉很有嚼劲,但是服务员态度太恶劣了,我们在门口等了50分钟都没有能成功进去,好不容易进去了,桌子也半天没人打扫,整个环境非常吵闹,我的孩子都被吓哭了,我下次不会带朋友来。
我们来看上面这句话,这句话很长,但是人读这句话的时候会记住几个关键的信息,比如烤鸭正宗,牛肉有嚼劲,服务员态度恶劣,环境吵闹等信息;但同时也会忽略掉一些内容,比如"我觉得","好不容易"等不重要的内容。这说明有选择的记忆比记忆整句话更加容易,LSTM正是受这一点的启发而设计的。
它通过引入门机制来控制LSTM单元需要记忆哪些信息,遗忘哪些信息,从而保持更长的信息依赖,更加轻松地表达整个句子语义。
2. LSTM是怎样工作的
同RNN一样,LSTM也是一种循环神经网络,他也是只有一个物理LSTM单元,按照时间步骤展开处理时序数据,如图1所示。
假设现在有这样一句话:南京市长江大桥,分词之后是:[南京,市,长江,大桥]。LSTM单元在第1个时刻会处理"南京"这个单词,在第2个时刻会处理"市"这个单词,依次类推。
我们再来看下每个时刻LSTM单元的输入和输出,显然在每个时刻LSTM会接收3种数据,同时输出2种数据。在时刻t,LSTM单元的输入是:单词xt (词向量),上一个时刻的状态向量ct−1(上边的横线) 和 上一个时刻的隐状态向量ht−1(下边的横线);LSTM单元的输出是: 当前时刻的状态向量ct和 当前时刻的隐状态向量ht。
图2展示了LSTM处理"南京市长江大桥"这句话的过程,我们可以看到在第1个时刻,模型输入了单词"南京", 初始的状态向量c0和初始的隐状态向量h0,模型输出的是状态向量c1和隐状态向量h1;在第2个时刻,模型输入了单词"市",第1个时刻的状态向量 c1和h1,模型的输出是状态向量c2和隐状态向量h2,其他的时刻依次类推。这就是LSTM处理时序信息的整体过程。
这里需要注意的是,在LSTM中虽然有两个状态向量ct和ht,但一般来讲,我们会将ct视为能够代表阅读到当前LSTM单元信息的状态(或者说是记忆), 而ht是当前LSTM单元对外的输出状态,它是实际的工作状态向量,即一般会利用ht来做一些具体的任务。
3. 从公式层面理解LSTM
前边我们从宏观上解释了LSTM是如何工作的,接下来我深入到LSTM单元内部进行介绍,看看它是如何保持数据的长期依赖的。我们先来看下LSTM单元内部是什么样的。
图3展示了LSTM单元内部的结构,里面包含了这样截个重要的组件:
-
状态向量ct:它控制着整个LSTM单元的状态或者记忆,它会根据每个时刻的输入进行更新,从而实时保持LSTM单元的记忆。
-
隐状态向量ht:它是当前LSTM单元对外的输出状态,它是实际的工作状态向量,即一般会利用htht来做一些具体的任务。
-
输入门it:控制当前时刻的输入信息需要向状态向量ctct中注入哪些信息。举个例子,当输入信息是一些没有实际意义的词,比如"的",可能模型不会让这些信息流入到状态向量中,从而保持模型的语义表达。
-
遗忘门ft:控制前一时刻的状态向量ct−1ct−1需要被屏蔽/遗忘哪些信息。举个例子**,昨天我去爬了长城,哦不对是前天**, 当模型看到"不对,是前天"的时候,可能就会忘记前边的"昨天"。
-
输出门ot:控制当前时刻的状态向量ctct需要对外输出哪些信息,最终输出的信息即为htht。
在了解了这些基本概念后,我们来看下这些组件的具体生成过程,首先来看下这三个门的生成过程,以时刻tt为例:
\[\begin{array}{*{20}{l}}
{{i_t}}&{ = sigmoid({W_i}{x_t} + {U_i}{h_{t - 1}} + {b_i})}\\
{{f_t}}&{ = sigmoid({W_f}{x_t} + {U_f}{h_{t - 1}} + {b_f})}\\
{{o_t}}&{ = sigmoid({W_o}{x_t} + {U_o}{h_{t - 1}} + {b_o})}
\end{array}\]
可以看到,这三个门的计算是使用输入数据xt和ht−1进行线性变换后,将结果传递给sigmoid函数,因为sigmoid函数是值域(0,1)的函数,即它能够将数据映射到这个固定区间,从而控制信息的流动。
接下来我门来计算下当前LSTM单元的待输入信息:
\[a\_t{\rm{ }} = {\rm{ }}tanh\left( {W\_ax\_t + U\_ah\_\left\{ {t - 1} \right\} + b\_a} \right)\]
同样是对输入数据xt和ht−1进行线性变换,然后将结果传递给tanh函数,最终的结果即为待向当前LSTM单元的状态向量ct中注入的信息。有了以上这些组件,接下来就可以更新当前LSTM单元的状态向量ct了。
\[{c_t} = {f_t} \cdot {c_{t - 1}} + {i_t} \cdot {a_t}\]
显然,LSTM单元状态ctct的更新是对上一个时刻的状态ct−1进行有选择的遗忘,对当前时刻的待输入信息atat将有选择的输入,最后将两者的结果进行相加,表示向当前LSTM单元即融入了以前的状态信息ct−1,同时又注入了当前最新的信息at。在计算出当前时刻的状态向量ct后,就可以根据该状态向量对外进行输出了。
\[{h_t} = {o_t} \cdot tanh({c_t})\]
即通过输出门对当前的状态信息ct进行有选择的输出。
4. 使用LSTM设计情感分析任务
前边我们讲完了LSTM的原理,包括宏观工作流程和微观公式理论,下面我们使用LSTM去简单生成一个情感分析的案例,期望能够给读者带来一些使用经验。
4.1 情感分析是什么
情感分析(sentiment classification)意在提炼出一句话中的感情色彩,比如高兴,普通,惊讶,伤心,愤怒等。但一般为了简化问题,会将这些感情划分为3类:积极、中立和消极情感,如图4所示。 因此可以将情感分析任务建模成一个文本三分类问题。
我们来看下边的例子,第1句话显然是对手机的赞美,因此它的情感类别为积极;第2个句话是说热水器有问题,因此它的情感类别为消极;第3句话不带有任何感情色彩,因此它的情感类别是中立。
我很喜欢这款手机,它的拍照功能很强大。
这个热水器太费电了,千万不能买。
今天我看了一本书,这本书的名字是人间失格。
4.2 使用LSTM进行文本分类建模¶
在循环神经网络RNN章节中,我们谈到当RNN读完最后一个单词的时候,其实已经读完了整个句子,那么最后这个单词输出的向量可以被视为整个句子的语义向量。LSTM同样适用这个做法,只是这里一般将前边讲到的隐状态向量作为整个句子的语义向量。
图5展示了一种使用LSTM建模文本分类的结构图,当给定一个文本序列的时候,首先我们先对文本序列进行分词,然后将每个单词的词向量传递LSTM,LSTM后会生成该句子的语义向量;然后将该语义向量传递给一个线性层,从而将这个语义向量映射为一个长度为3个情感向量,其中每一维代表一个情感类别。但是这个这个情感向量数值未归一化,因此还需要使用softmaxsoftmax进行归一化,使其变成一个数值在[0,1]之间,相加和为1的数值。最后这个情感向量分数最大的那一维对应的情感类别就是整个句子的情感类别。
总结一下,本篇文章讲述了LSTM的设计原理,LSTM的宏观工作流程,LSTM的公式推导,以及使用LSTM简单完成情感分析功能,看到这里相信大家对LSTM已经有了不错的认识。