在使用tensorflow构建lstm网络时,在网上看了不少文章,大部分都是忽略细节,重要的地方一带而过,不重要的地方长篇大论。最近仔细看了看,决定总结一下,供大家参考,错误的地方还望指正。
我这里主要要介绍的细节,主要包括参数 num_units和sequence_length的理解,以及 tf.nn.rnn_cell.MultiRNNCell 和 tf.nn.dynamic_rnn 两个常见API的使用
(1)参数num_units的理解
先看下面一段代码
import
上面执行单层单向循环网络的代码中,构建了一个单层lstm,num_units=128 可以理解为每一个时间步骤输出结果的维度。这里的X表示一个批次的数据,样本的矩阵大小是 25 * 640 ,通过25个时间步骤展开lstm,每一个时间步骤,输入一个维度为 n=640的向量。输出的则是维度为128的向量。t 时刻
计算这个单层lstm的神经元总数量
- 神经元总数量 = 4 * ((num_units + n) * num_units + num_units)
- 神经元总数量 = 4 * ((128 + 640) * 128 + 128)
对于 sequence_length 的理解
- 在进行自然语言处理时,可能每句话长度不一致,但是在我们将矩阵送入模型时,要求长度是一致的。因此不相同的时间步长要求一致,以最大步长为准。这样也就需要进行填充,但是如果仅仅完成填充,在训练的时候不把这些填充的数据去除的话,那么这些填充位置的向量也会学习到特征,进一步影响梯度的计算,因此需要使用sequence_length来指定有效长度,跳过填充的部分。
补充一点:
//
(2)多层LSTMCell :tf.nn.rnn_cell.MultiRNNCell
大部分情况,构建的LSTM网络都会用到多层。将x输入第一层LSTM的后得到隐层状态 h,这个隐层状态就相当于第二层LSTM的输入,第二层LSTM的隐层状态又相当于第三层RNN的输入,以此类推。通过MultiRNNCell得到的cell实际也是RNNCell的子类实例,因此也有call方法。同样可以通过tf.nn.dynamic_rnn来一次运行多步。
在TensorFlow中,使用tf.nn.rnn_cell.MultiRNNCell 函数对RNNCell进行堆叠,式例代码:
import
下面附两张图,非常清晰的描述了多隐层LSTM网络的计算过程
![35202cbfee54d3db16d1c3a5760c68bb.png](https://i-blog.csdnimg.cn/blog_migrate/0ea3ba4401d689ee6d33fa480b7bfc9f.jpeg)
![decd0df792edbb44347aeb2f95ef58e9.png](https://i-blog.csdnimg.cn/blog_migrate/859346255d537a1c26d82dbf5c1ee217.jpeg)
(3)一次性执行多步call方法 :tf.nn.dynamic_rnn
基础的RNNCell有一个很明显的问题:对于单个的RNNCell,我们使用它的call函数进行运算时,只是在序列时间上前进了一步。比如使用x1、h0得到h1,通过x2、h1得到h2等。这样的h话,如果我们的序列长度为10,就要调用10次call函数,比较麻烦。对此,TensorFlow提供了一个函数,使用该函数就相当于调用了n次call函数。即通过{h0,x1, x2, …., xn}直接得{h1,h2…,hn}。
使用tf.nn.dynamic_rnn也会有两个返回值,分别是 outputs, states。其实和上面使用call方法的返回值原理相同,只是处理step的不同,所以结构有所不同。关于这个函数使用我推荐一批很不错的文章,所以我就不介绍了。
https://blog.csdn.net/junjun150013652/article/details/81331448blog.csdn.net