Sigmoid函数的导数范围是(0,0.25], Tanh函数的导数是(0,1]。
由于RNN中会执行很多累乘,小于1的小数累乘会导致梯度越来越接近于0,出现梯度消失现象。
Tanh与Sigmoid相比,梯度更大,收敛速度更快并且出现梯度消失的情况要优于Sigmoid。
另一点是Sigmoid的输出均大于0,不是零对称的,这会导致偏移现象,因为每一层的输入都是大于零的。 关于原点对称的数据输入,训练效果更好。
RNN为什么不用Relu?
这其实是一个伪命题,发明Relu函数的初衷就是为了克服Tanh函数在RNN中的梯度消失现象。
但是由于Relu的导数不是0就是1,恒为1的导数容易导致梯度爆炸,不过梯度爆炸不用慌,通过简单的梯度截断机制就可以得到优化。
Relu激活函数是RNN中避免梯度消失现象的一个重要方法。
为什么Relu用在RNN中会梯度爆炸,在普通CNN中不会?
Relu在RNN中会导致非常大的输出值,由于每个神经元(设系数为w)的输出都会作为输入传给下一个时刻本神经元,这就导致会对系数矩阵w执行累乘,如果w中由一个特征值大于1,那么非常不幸,若干次累乘之后数值就会很庞大,在前向传播时候导致溢出,后向传播导致梯度爆炸(当然可做截断优化)。
而在CNN中,不存在系数矩阵w的累乘,每一层的系数w都是独立的,互不相同,有大于1的,有小于1的,所以在很大程度上可以抵消,而不至于让最终的数值很大。
首先需要强调Encoder和Decoder都是RNN(LSTM)模型,都有循环输入(自己的输出作为下次的输入)。
Encoder部分的输入是序列(一句话)经过word embedding(词嵌入)方法处理过的词向量表示和上一个时间点本Encoder输出的结果, 输出的是当前时间点的中间编码c。
(word embedding词嵌入是一种用低维向量表示高维向量的一种方式,可以保证在语义上相近的词编码后距离相近)
Decoder部分的输入是 Encoder部分输出的中间编码和上一个时间点本Decoder输出的预测结果(一句话)的word embedding词向量。
(图来自 知乎 盛源车)
上图加了Attention,生成结果的时候会用到Encoder的隐层输出,如果不加Attention,则结果完全依赖与Decoder的输出(Decoder输入是Encoder的输出)
Encoder-Decoder模型中怎么体现出前一个时间序列对后一个时间序列影响?
每一个时间点的序列经过Encoder编码之后(加Attention或不加),再由Decoder解码输出序列结果,这个结果一方面作为“翻译”输出,一方面再作为输入(经过word embedding词嵌入表示),和下一个时间点的编码序列一起,送给Decoder解码翻译,得到“翻译”输出。 以此体现了上一个时间点序列对下一个时间点序列的影响作用。
实际上,当前时间点的输出,是当前输入和之前所有时间点上的输出共同作用的结果。
seq2seq 是一个Encoder–Decoder 结构的网络,它的输入是一个序列,输出也是一个序列, Encoder 中将一个可变长度的信号序列变为固定长度的向量表达,Decoder 将这个固定长度的向量变成可变长度的目标的信号序列。
传统Encoder-Decoder结构中,Encoder把所有的输入序列不管多长多短都编码成一个固定长度的语义特征c再解码,这就导致了两个问题,一是对长输入序列而言的信息丢失,二是丢失了序列原有的结构化信息,忽略了序列数据之间的相互关系信息,这两者导致准确度降低。
那么加入了Attention机制的Encoder-Decoder结构生成的语义向量c是定长的吗?答案或许大概是定长的。
Attention机制的机制不是“针对不同长度的输入得到不同长度的中间编码”,而是让Decoder的每一个时刻在输出上所依赖的中间编码c里边的元素的权重不同,即当前输出(LSTM是时间依赖关系,下一个时刻的输出受上一个时刻输出的影响,所以生成如一句话时LSTM的输出必然是从前到后,一个字(词)一个字(词)的生成的,这一点比较关键)更应该更多关注固定长度中间编码c中的哪几个元素。这样就相当于LSTM的每一个时刻的解码输出的输入的那个中间编码c是不一样的(c本身一样,c中元素权重不一样)。
Attention加入的位置
再看一下具有Attention结构的Encoder-Decoder模型总体结构:
假设Decoder中有两层的LSTM,则Attention加入的位置是在两层LSTM隐层之间,Attention和第一层LSTM的输出一起给到第二层SLTM。
所以Attention是加在Decoder的中间结果上的。
Attention具体操作
上图中最下边一排最右侧的蓝色方框是Decoder隐层中某一时刻的中间输出。
具有不同权重的编码序列c分别与Decoder隐层中第一个时刻到最后一个时刻的隐层输出相乘,再经过一个softmax等操作再还原回来同等维度大小的隐层输出。从前时刻到最后时刻依次执行。是每一个元素都和Attention相乘,而不是整体乘一次(前后关联,有前输出才有后边的输出,不可能一次输出)。
Attention中对每个元素权重系数的确定
Attention如何确定中间编码c中1~j个元素分别对于输出序列Decoder隐藏层中1~i个元素的权重值aij?
在Attention模块中维护一个求权重值aij的函数,这个函数可以有不同的实现方法,它的输出需要经过Softmax进行归一化得到符合概率分布取值区间的注意力分配概率分布数值aij。
既然已经知道Attention中编码序列c中哪个(几个)元素对于解码序列某一时刻来说最重要,为什么不直接根据重要性直接输出结果?
为了给网络一次改过自新的机会。 一是计算出来的“最重要”的结论不一定正确,二是编解码需要兼顾整体上的表达,只关注最重要的有可能绝对翻译是对的,但是语义上却不通顺。