RNN与LSTM

RNN在时间维度上做循环,将当前step的输入和之前的输出状态混合计算作为当前step的输出。

 LSTM 解决the long-term dependency problem

贯穿网络始终的核心是cell state ,起了conveyor belt传送带的作用,LSTM使用门gate来对cell state中的信息进行添加和删减。

一个gate的大致结构为,黄色部分为sigmoid控制的layer以0到1的概率允许信息的通过。

  • 忘记门

        基于上一step的输出$h_{t-1}$和当前的输入$x_{t}$操作,决定上一step的信息有多少应该被保留并送入当前step的cell中,当我们看到新的主语,我们希望忘记旧的主语。 例如,他今天有事,所以我。。。当处理到‘’我‘’的时候选择性的忘记前面的’他’,或者说减小这个词对后面词的作用。

  •  输入门

           两步操作,sigmoid生成一个向量,tanh生成一个向量,在下一步中做组合。我们希望增加新的主语的类别到细胞状态中,来替代旧的需要忘记的主语。 
   例如:他今天有事,所以我。。。。当处理到‘’我‘’这个词的时候,就会把主语我更新到细胞中去。

  • 输出门

这个门将旧状态$C_{t-1}$最终更新到新的当前输出状态$C_t$中,用到的变量也是前面的门计算出来的数值

状态的计算,通过这三个门计算就能得出,但实际的输出$h_t$还需一步

 如果要得到最终的输出, 一般来说还需要添加一个全连接层。

 一个简单的伪代码示例:

关于LSTM的参数个数:

上一次的状态 $h_(t-1)$是通过cancat和下一次的输入 $x_(t)$ 结合起来的,比如 x是28位的向量,$h_(t-1)$是128位的,那么拼起来就是156位的向量,一个LSTM网络的参数个数计算:假设 num_units 是128,输入是28位的,那么四个小黄框的参数一共有 (128+28)*(128*4),也就是156 * 512。

 双向LSTM

单向的 RNN,是根据前面的信息推出后面的信息,双向网络照顾了前后两个方向的信息,对候选信息的判定更加精准。

Tensorflow中双向LSTM接口为tensorflow.nn.bidirectional_dynamic_rnn()

函数的输出为一个tuple(outputs,output_state)。对于outputs来说存储了fw和bw两个方向的输出tensor,shape为[batch_size, step,cell.state_size],最终结果需要将两者做一个concat,tf.concat(outputs,2),shape变为[batch_size,step,2*cell.state_size]。从上面可以看出,LSTM输出的最后一个dim维度其实就是由隐层单元(状态数量)决定的特别注意的是bidirectional_dynamic_rnn不支持多层cell,只能传递单层cell,如果要使用多层cell,只能在外面循环调用多次接口来实现,比较坑。

tensorflow中的rnn接口和dynamic_rnn接口的区别在于动态创建和静态创建step
tf.nn.rnn creates an unrolled graph for a fixed RNN length. That means, if you call tf.nn.rnn with inputs having 200 time steps you are creating a static graph with 200 RNN steps. First, graph creation is slow. Second, you’re unable to pass in longer sequences (> 200) than you’ve originally specified.tf.nn.dynamic_rnn solves this. It uses a tf.While loop to dynamically construct the graph when it is executed. That means graph creation is faster and you can feed batches of variable size.

原文地址:https://www.cnblogs.com/punkcure/p/8413297.html