首页 文章

张量流RNN的动态张量形状

提问于
浏览
1

我正在为tensorflow RNN尝试一个非常简单的例子 . 在那个例子中,我使用动态rnn . 代码如下:

data = tf.placeholder(tf.float32, [None, 10,1]) #Number of examples, number of input, dimension of each input
target = tf.placeholder(tf.float32, [None, 11])
num_hidden = 24
cell = tf.nn.rnn_cell.LSTMCell(num_hidden,state_is_tuple=True)
val, _ = tf.nn.dynamic_rnn(cell, data, dtype=tf.float32)
val = tf.transpose(val, [1, 0, 2])
last = tf.gather(val, int(val.get_shape()[0]) - 1)
weight = tf.Variable(tf.truncated_normal([num_hidden, int(target.get_shape()[1])]))
bias = tf.Variable(tf.constant(0.1, shape=[target.get_shape()[1]]))
prediction = tf.nn.softmax(tf.matmul(last, weight) + bias)
cross_entropy = -tf.reduce_sum(target * tf.log(tf.clip_by_value(prediction,1e-10,1.0)))
optimizer = tf.train.AdamOptimizer()
minimize = optimizer.minimize(cross_entropy)
mistakes = tf.not_equal(tf.argmax(target, 1), tf.argmax(prediction, 1))
error = tf.reduce_mean(tf.cast(mistakes, tf.float32))

实际上,代码取自tutorial . 该RNN网络的输入是二进制数序列 . 每个数字都放在一个数组中 . 例如,一个seuquence有格式:
[[1],[0],[0],[1],[1],[0],[1],[1],[1],[0]] 输入的形状为[无,10,1],分别为批量大小,序列大小和嵌入大小 . 现在因为动态rnn可以接受变量输入形状,我更改代码如下:

data = tf.placeholder(tf.float32, [None, None,1])

基本上,我想使用可变长度序列(当然相同批次中的所有序列长度相同,但批次之间不同) . 但是,它会抛出错误:

Traceback (most recent call last):
  File "rnn-lstm-variable-length.py", line 48, in <module>
    last = tf.gather(val, int(val.get_shape()[0]) - 1)
TypeError: __int__ returned non-int (type NoneType)

我知道第二个维度是 None ,不能在 get_shape()[0] 中使用 . 但是,我认为必须有办法克服这个问题,因为RNN通常会接受可变的lenth输入 . 我该怎么做?

2 回答

  • 3

    tf.gather 需要一个张量,所以你可以使用 tf.shape(val) 得到一个在运行时计算的张量为 val 的形状 - 例如 tf.gather(val, tf.shape(val)[0] - 1)

  • 0

    tl;dr :尝试使用 tf.batch(..., dynamic_pad=True) 批量处理数据 .


    @ chris_anderson的评论是正确的 . 最终,您的网络需要一个密集的数字矩阵才能使用,并且有一些策略可以将可变长度数据转换为超矩形:

    • 将所有批次填充到固定大小(例如,假设每个输入的最大长度为500个项目,并且每个批次中的每个项目都填充到500个) . 这个策略没有任何动态 .

    • 将每批次填充应用于批次中最长项目的长度(动态填充) .

    • 根据长度填充输入并按批次应用填充 . 这与#2相同,但整体填充较少 .

    您也可以使用other strategies .

    要执行此批处理,您可以使用:

    • tf.train.batch - 默认情况下它没有填充,您需要自己实现它 .

    • tf.train.batch(..., dynamic_pad=True)

    • tf.contrib.training.bucket_by_sequence_length

    我怀疑你对 tf.nn.dynamic_rnn 的使用感到困惑 . 重要的是要注意 dynamic_rnn 中的 dynamic 指的是TensorFlow展开网络的重复部分的方式 . 在 tf.nn.rnn 中,重复在图中静态完成(没有内部循环,它在图形构建时展开) . 但是,在_875086中,TensorFlow使用 tf.while_loop 在运行时在图形内部进行迭代 . 要使用动态填充,您需要使用动态展开,但它不会自动执行 .

相关问题