作者:廖蓉以 | 来源:互联网 | 2023-09-10 00:33
NotethatifwewrapabasecellwithdropoutandthenuseittobuildaMultiRNNCell,bothinputdropoutandou
Note that if we wrap a base cell with dropout and then use it to build a MultiRNNCell, both input dropout and output dropout will be applied between layers (so if both are, say, 0.9, the dropout in between layers will be 0.9 * 0.9 = 0.81). If we want equal dropout on all inputs and outputs of a multi-layered RNN, we can use only output or input dropout on the base cell, and then wrap the entire MultiRNNCell with the input or output dropout like so:
cell = tf.nn.rnn_cell.LSTMCell(state_size, state_is_tuple=True)
cell = tf.nn.rnn_cell.DropoutWrapper(cell, input_keep_prob=global_dropout)
cell = tf.nn.rnn_cell.MultiRNNCell([cell] * num_layers, state_is_tuple=True)
cell = tf.nn.rnn_cell.DropoutWrapper(cell, output_keep_prob=global_dropout)
LSTMCell和BasicLSTMCell的区别:
1. 增加了use_peepholes, bool值,为True时增加窥视孔。图片来源于:http://colah.github.io/posts/2015-08-Understanding-LSTMs/
2. 增加了cell_clip, 浮点值,把cell的值限制在 ±cell_clip内
c = clip_ops.clip_by_value(c, -self._cell_clip, self._cell_clip)
3. 增加了num_proj(int)和proj_clip(float), 相对于BasicLSTMCell,在输出m计算完之后增加了一层线性变换,并限制了输出的值
m = _linear(m, self._num_proj, bias=False, scope=scope)
m = clip_ops.clip_by_value(m, -self._proj_clip, self._proj_clip)
Tensorflow中的dynamic lstm
作者:王买买提
链接:https://www.zhihu.com/question/52200883/answer/153694449
来源:知乎
在每一个train step,传入model的是一个batch的数据(这一个batch的数据forward得到predictions,计算loss,backpropagation更新参数),这一个batch内的数据一定是padding成相同长度的。
那么,如果可以只在一个batch内部进行padding,例如一个batch中数据长度均在6-10这个范围内,就可以让这个batch中所有数据pad到固定长度10,而整个dataset上的数据最大长度很可能是100,这样就不需要让这些数据也pad到100那么长,白白浪费空间。
所以dynamic_rnn实现的功能就是可以让不同迭代传入的batch可以是长度不同数据,但同一次迭代一个batch内部的所有数据长度仍然是固定的。例如,第一时刻传入的数据shape=[batch_size, 10],第二时刻传入的数据shape=[batch_size, 12],第三时刻传入的数据shape=[batch_size, 8]等等。
但是rnn不能这样,它要求每一时刻传入的batch数据的[batch_size, max_seq],在每次迭代过程中都保持不变。
这样不就必须要求全部数据都要pad到统一的max_seq长度了吗?是的,但也有个折中办法。
——将数据集的sequence length做个初步统计,看会落在哪几个区间段内。然后根据区间段将数据进行归类,也就是所谓的放在不同buckets中。
最后用rnn为每一个buckets都创建一个sub graph。训练的时候,根据当前batch data所归属的bucket id,找到它对应的sub graph,进行参数更新(虽然是不同的sub graph,但参数是共享的。至少tensorflow中是这么实现的~\(≧▽≦)/~)
具体可参看:https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/legacy_seq2seq/python/ops/seq2seq.py#L1143
另外,两者的输入形式确实不同,但你提到的“将填充的部分输出为0”,给rnn传入sequence_length这个参数后,也是可以的。