早期学者解决问题所运用的是数学概率统计的方法,这些方法在实现前都要经过词特征的构建、特征降维和特征表示;后期由于机器学习的兴起,一开始使用全连接网络模型,它是指在神经网络中每两层之间的所有结点都是相连接的,但在处理图像数据时,全连接网络所需要的参数个数太多,比如处理一张单通道图片,图片大小为2828,设隐藏层的节点数为500个,则由其组成的全连接网络模型的参数有`2828*500+500=392500`,“+500”是因为考虑了偏置项b的情况,而当图片更大时,参数会急剧增多,参数过多不仅会导致网络模型计算速度变慢,同时也容易导致过拟合问题,CNN的出现就是为了在一定程度上改善这种情况。
从上图中可以看出,CNN的卷积层(Convolution)和池化层(Polling)中每个节点只与上一层的部分节点相连,卷积层的每个节点的输入只是上一层中的一小块,这个小块的大小由
卷积核的窗口
大小决定,通常来说,经过卷积层处理的节点矩阵会变得更深,具体的深度由卷积层中卷积核的多少来决定。
卷积核的参数是共享可以使得图像上的内容不受位置的影响
,即图片中的猫不管是在图片的左上角或者右下角都应该被分类为猫,同时共享卷积核的参数可以大幅减少网络模型中的参数,降低运算的复杂度。
池化层的每个节点的输入也是上一层(通常是卷积层)的一小块,这个小块的大小由池化核的窗口大小决定,池化层不会改变节点矩阵的深度,但它可以改变矩阵的大小,通俗来说,对于图像处理,
池化层中池化操作可以理解为是将一张分辨率高的图片转化为分辨率低的图片
。常用的池化操作有最大池化、平均池化等,通过卷积层和池化层后,可以进一步缩小网络模型中的参数个数,下面我们来分析下CNN如何减少网络模型中的参数。
但是存在一个问题——CNN无法解决长距离依赖(应该很眼熟这个)
一、RNN
1.1 CNN无法解决长距离依赖的问题,为啥呢?
全连接网络和卷积神经网络,这两种网络结构的层与层之间是全连接或者部分连接的,但是每层之间的节点是无连接的,这样的结构不能很好地解决序列问题,当我们想预测句子中下一个单词是什么的时候,通常会一句前文的语境来进行预测,例如“天空 很” 下一个单词很可能就“美,蓝,漂亮”之类的。(
参考
)
RNN通过每层节点之间的连接结构,来记忆之前的信息,并利用这些信息来影响后面节点的输入。RNN可充分挖掘序列数据中的
时序信息
和
语义信息
,这在处理时序数据时比全连接神经网络和CNN更具有深度表达能力。RNN可运用于语音识别、机器翻译、时序分析等领域。
1.2 RNN framework
图1 RNN(来自李宏毅老师
)
从图1中可以看出,RNN在每一个时刻都有一个输入x^i,然后基于给定x^1与h^j ,运用function f 输出y与h。和卷积神经网络卷积核或者池化核的参数共享相似,这里RNN结构中的参数在不同时刻也是共享的。
1.3 RNN 前向传播(
参考
)
图2 RNN的前向传播计算过程
如图2所示,假设节点状态的维度为
2
,节点的输入和输出维度为
1
,那么在循环体的
全连接层神经网络
的输入维度为
3
,也就是将上一时刻的状态与当前时刻的输入拼接成一维向量作为循环体的全连接层神经网络的输入,在这里
t0
时刻的节点状态初始化为
[0.0, 0.0]
,
t0
时刻的节点输入为
[1.0]
,拼接之后循环体的全连接层神经网络的输入为
[0.0, 0.0, 1.0]
,循环体中的全连接层的权重表示为二维矩阵
[[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]]
,偏置项为
[0.1, -0.1]
,我们可以看到权重矩阵和偏置项在
t0
和
t1
时刻的循环体中是一样的,这也说明了RNN结构中的参数在不同时刻中也是共享的。经过循环体中的全连接层神经网络后节点的状态改变为
tanh([0.6, 0.5]) = [0.537, 0.462]
,当前节点状态的输出作为下一个节点状态的输入。
为了将当前时刻的状态转变为节点的最终输出,RNN中还有另外一个全连接神经网络来计算节点输出,在图2中被表示为
[0.537, 0.462] * [1.0, 2.0] + [0.1] = [1.56]
,用于输出的全连接层权重为
[1.0, 2.0]
,偏置项为
[0.1]
,
1.56
表示为
t0
时刻节点的最终输出。得到RNN的前向传播结果之后,和其他神经网络类似,定义损失函数,使用反向传播算法和梯度下降算法训练模型,但RNN唯一的区别在于:由于它每个时刻的节点都有一个输出,所以
RNN的总损失为所有时刻(或部分时刻)上的损失和
。
二、LSTM
上节介绍的RNN模型,存在“长期依赖”的问题。模型在预测“大海的颜色是”下一个单词时,很容易判断为“蓝色”,因为这里相关信息与待预测词的位置相差不大,模型不需要记忆这个短句子之前更长的上下文信息。但当模型预测“十年前,北京的天空很蓝,但随着大量工厂的开设,废气排放监控不力,空气污染开始变得越来越严重,渐渐地,这里的天空变成了”下一个单词时,依靠“短期依赖”就不能很好的解决这类问题,因为仅仅根据“这里的天空变成了”这一小段,后一个单词可以是“蓝色”,也可以是“灰色”。上节描述的简单RNN结构可能无法学习到这种“长期依赖”的信息。
在此基础上,提出了长短期记忆网络(Long Short Term Memory Network,LSTM),LSTM可以解决训练过程中的梯度消失和梯度爆炸问题,简单来说就是在更长序列中有更好的表现。图3展示了LSTM单元结构图。
图3 LSTM framework (图片来自李宏毅老师)
与简单RNN结构中单一tanh循环体不同的是,LSTM使用
三个“门”
结构来控制不同时刻的状态和输出。所谓的“门”结构就是使用了sigmoid激活函数的
全连接神经网络
和一个按位做乘法的操作,sigmoid激活函数会输出一个0~1之间的数值,这个数值描述的是当前有多少信息能通过“门”,0表示任何信息都无法通过,1表示全部信息都可以通过。其中,“
遗忘门
”(Z^f, forget)和“
输入门
”(Z^i, information)是LSTM单元结构的核心。下面我们来详细分析下三种“门”结构。
图4 LSTM 三个门
2.1 三种
门
遗忘门
:用来让RNN“忘记”之前没有用的信息。比如“
十年前,北京的天空是蓝色的”,但当看到“空气污染开始变得越来越严重
”后,RNN应该忘记“北京的天空是蓝色的”这个信息。遗忘门会根据当前时刻节点的输入
Xt
、上一时刻节点的状态
C(t-1)
和上一时刻节点的输出
h(t-1)
来决定哪些信息将被遗忘。
输入门
:
用来让RNN决定当前输入数据中哪些信息将被留下来
。在RNN使用遗忘门“忘记”部分之前的信息后,还需要从当前的输入补充最新的记忆。输入门会根据当前时刻节点的输入Xt、上一时刻节点的状态C(t-1)和上一时刻节点的输出h(t-1)来
决定哪些信息将进入当前时刻节点的状态Ct
,比如看到“空气污染开始变得越来越严重”后,模型需要记忆这个最新的信息。
输出门(Z^o, output)
:LSTM在得到最新节点状态Ct后,结合上一时刻节点的输出h(t-1)和当前时刻节点的输入Xt来决定当前时刻节点的输出。比如当前时刻节点状态为被污染,那么“天空的颜色”后面的单词应该是“灰色”。
在TensorFlow中可以使用lstm = rnn_cell.BasicLSTMCell(lstm_hidden_size)来声明一个LSTM结构。
后面延伸的还有BRNN、DRNN
2.2 BRNN
RNN和LSTM都只能依据之前时刻的时序信息来预测下一时刻的输出,但在有些问题中,当前时刻的输出不仅和之前的状态有关,还可能和未来的状态有关系。比如预测一句话中缺失的单词不仅需要根据前文来判断,还需要考虑它后面的内容,真正做到基于上下文判断。BRNN有两个RNN上下叠加在一起组成的,输出由这两个RNN的状态共同决定。BRNN结构图如图5所示。
图5 双向循环神经网络
对于每个时刻
t
,输入会同时提供给两个方向相反的RNN,输出由这两个单向RNN共同决定。
2.3 DRNN
DRNN可以增强模型的表达能力,主要是将每个时刻上的循环体重复多次,每一层循环体中参数是共享的,但不同层之间的参数可以不同。
三、GRU(
参考
)
GRU(Gate Recurrent Unit)是循环神经网络(Recurrent Neural Network, RNN)的一种。和LSTM(Long-Short Term Memory)一样,也是为了解决长期记忆和反向传播中的梯度等问题而提出来的。GRU能够达到LSTM相当的效果,并且相比之下更容易进行训练,能够很大程度上提高训练效率,因此很多时候会更倾向于使用GRU。
3.1 GRU framework
结合
和
(之前节点的相关信息),GRU会得到当前隐藏节点的输出
和传递给下一个节点的隐状态
。
图6 GRU分解
3.2 重置门
然后,通过上一个传输下来的状态
和当前节点的输入
来获取两个门控状态。如图6所示,其中
控制重置的门控(reset gate),
为控制更新的门控(update gate)。得到门控信号之后,首先使用重置门控来得到“重置”之后的数据
,再将
与输入
进行拼接,再通过一个
tanh
激活函数来将数据放缩到-1~1的范围内。即得到如下图7所示的
。
图7 重置
这里的
主要是包含了当前输入的
数据。有针对性地对
添加到当前的隐藏状态,相当于”记忆了当前时刻的状态“。类似于LSTM的选择记忆阶段。
图8 的
是Hadamard Product,也就是操作矩阵中对应的元素相乘,因此要求两个相乘矩阵是同型的。
则代表进行矩阵加法操作。
3.3 更新记忆
最后介绍GRU最关键的一个步骤,我们可以称之为”更新记忆“阶段。
在这个阶段,我们同时进行了遗忘了记忆两个步骤。我们使用了先前得到的更新门控
(update gate)。更新表达式:
首先再次强调一下,门控信号(这里的
)的范围为0~1。门控信号越接近1,代表”记忆“下来的数据越多;而越接近0则代表”遗忘“的越多。
GRU很聪明的一点就在于,我们使用了同一个门控
就同时可以进行遗忘和选择记忆(LSTM则要使用多个门控)。
:表示对原本隐藏状态的选择性“遗忘”。这里的
可以想象成遗忘门(forget gate),忘记
维度中一些不重要的信息。
: 表示对包含当前节点信息的
进行选择性”记忆“。与上面类似,这里的
同理会忘记
维度中的一些不重要的信息。或者,这里我们更应当看做是对
维度中的某些信息进行选择。
:结合上述,这一步的操作就是忘记传递下来的
中的某些维度信息,并加入当前节点输入的某些维度信息。
可以看到,这里的遗忘
和选择
是联动的。也就是说,对于传递进来的维度信息,我们会进行选择性遗忘,则遗忘了多少权重 (
),我们就会使用包含当前输入的
中所对应的权重进行弥补
。以保持一种”恒定“状态。
3.4. LSTM与GRU的关系
大家看到
(reset gate)实际上与他的名字有点不符。我们仅仅使用它来获得了
。
那么这里的
实际上可以看成对应于LSTM中的hidden state;上一个节点传下来的
则对应于LSTM中的cell state。1-z对应的则是LSTM中的
forget gate,那么 z我们似乎就可以看成是选择门
了。大家可以结合我的两篇文章来进行观察,这是非常有趣的。
3.5 总结
GRU输入输出的结构与普通的RNN相似,其中的内部思想与LSTM相似。与LSTM相比,GRU内部少了一个”门控“,参数比LSTM少,但是却也能够达到与LSTM相当的功能。考虑到硬件的计算能力和时间成本,因而很多时候我们也就会选择更加”实用“的GRU啦。