在TensorFlow的dynamic_rnn中使用sequence_length参数时如何处理填充

我正在尝试使用TensorFlow中的dynamic_rnn函数来加速训练。经过一些阅读,我了解到加速训练的一种方法是明确传递一个值给该函数中的sequence_length参数。进一步阅读后,并找到这个Stack Overflow的解释,似乎我需要传递的是一个向量(可能由tf.placeholder定义),该向量包含批次中每个序列的长度。

让我感到困惑的地方在于:为了利用这一点,我应该将每个批次填充到批次中最长的序列长度,而不是训练集中最长的序列长度吗?TensorFlow如何处理任何较短序列中的剩余零值/填充标记?此外,这里主要的优势真的是速度,还是只是在训练期间确保我们掩盖了填充标记的额外保证?任何帮助/背景信息将不胜感激。


回答:

我应该将每个批次填充到批次中最长的序列长度,而不是训练集中最长的序列长度吗?

批次内的序列必须对齐,即必须具有相同的长度。因此,您问题的总体答案是“是的”。但不同的批次不必具有相同的长度,因此您可以将输入序列分层成大小大致相同的组,并相应地填充它们。这种技术称为分桶,您可以在此教程中阅读相关内容。

TensorFlow如何处理任何较短序列中的剩余零值/填充标记?

这几乎是直观的。tf.nn.dynamic_rnn返回两个张量:outputstates。假设实际序列长度为t,填充后的序列长度为T

那么outputi > t之后将包含零,而states将包含第t个单元的状态,忽略尾随单元的状态。

这是一个示例:

import numpy as npimport tensorflow as tfn_steps = 2n_inputs = 3n_neurons = 5X = tf.placeholder(dtype=tf.float32, shape=[None, n_steps, n_inputs])seq_length = tf.placeholder(tf.int32, [None])basic_cell = tf.nn.rnn_cell.BasicRNNCell(num_units=n_neurons)outputs, states = tf.nn.dynamic_rnn(basic_cell, X,                                     sequence_length=seq_length, dtype=tf.float32)X_batch = np.array([  # t = 0      t = 1  [[0, 1, 2], [9, 8, 7]], # instance 0  [[3, 4, 5], [0, 0, 0]], # instance 1  [[6, 7, 8], [6, 5, 4]], # instance 2])seq_length_batch = np.array([2, 1, 2])with tf.Session() as sess:  sess.run(tf.global_variables_initializer())  outputs_val, states_val = sess.run([outputs, states], feed_dict={    X: X_batch,     seq_length: seq_length_batch  })  print(outputs_val)  print()  print(states_val)

请注意,实例1被填充,因此outputs_val[1,1]是一个零向量,且states_val[1] == outputs_val[1,0]

[[[ 0.76686853  0.8707901  -0.79509073  0.7430128   0.63775384]  [ 1.          0.7427926  -0.9452815  -0.93113345 -0.94975543]] [[ 0.9998851   0.98436266 -0.9620067   0.61259484  0.43135557]  [ 0.          0.          0.          0.          0.        ]] [[ 0.99999994  0.9982034  -0.9934515   0.43735617  0.1671598 ]  [ 0.99999785 -0.5612586  -0.57177305 -0.9255771  -0.83750355]]][[ 1.          0.7427926  -0.9452815  -0.93113345 -0.94975543] [ 0.9998851   0.98436266 -0.9620067   0.61259484  0.43135557] [ 0.99999785 -0.5612586  -0.57177305 -0.9255771  -0.83750355]]

此外,这里主要的优势真的是速度,还是只是在训练期间确保我们掩盖了填充标记的额外保证?

当然,批处理比一次一个地输入序列更有效。但指定长度的主要优势是您可以从RNN中获得合理的状态,即填充项不会影响结果张量。如果您不设置长度,但手动选择正确的状态,您将获得完全相同的结果(和相同的速度)。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注