使用 tf.while_loop (TensorFlow) 从图形中累积输出

Accumulating output from a graph using tf.while_loop (TensorFlow)

长话短说,我有一个 RNN 堆叠在 CNN 之上。 CNN 是单独创建和训练的。为了澄清事情,我们假设 CNN 以 [BATCH SIZE, H, W, C] 占位符的形式接受输入(H = 高度,W = 宽度,C = 通道数)。

现在,当堆叠在 RNN 之上时,组合网络的整体输入将具有以下形状:[BATCH SIZE, TIME SEQUENCE, H, W, C],即小批量中的每个样本由 TIME_SEQUENCE很多图片。此外,时间序列的长度是可变的。有一个名为 sequence_lengths 的单独占位符,其形状为 [BATCH SIZE],其中包含与小批量中每个样本的长度相对应的标量值。 TIME SEQUENCE的值对应最大可能的时序长度,对于长度较小的样本,剩余值补零

我想做什么

我想将 CNN 的输出累积到形状为 [BATCH SIZE, TIME SEQUENCE, 1] 的张量中(最后一个维度只包含 CNN 为每个批次元素的每个时间样本输出的最终分数)这样我就可以将整个信息块转发到堆叠在 CNN 之上的 RNN。棘手的是,我还希望能够将错误从 RNN 反向传播到 CNN(CNN 已经经过预训练,但我想稍微微调一下权重),所以我必须留在图中,即我无法对 session.run().

进行任何调用

my_cnn_model.process_input 中,我只是通过普通 CNN 传递输入。其中创建的所有变量都带有 tf.AUTO_REUSE,因此应该确保 while 循环为所有循环迭代重复使用相同的权重。

确切问题

image_output_sequence是一个变量,但是不知怎么的,当tf.while_loop调用body方法的时候,就变成了Tensor类型的对象,无法赋值。我收到错误消息:Sliced assignment is only supported for variables

即使我使用另一种格式,比如使用 BATCH SIZE Tensors 的元组,每个维度都具有 [TIME SEQUENCE, H, W, C],这个问题仍然存在。

我也愿意完全重新设计代码,只要能很好地完成工作即可。

解决方案是使用TensorArray类型的对象,它是专门为解决此类问题而制作的。下面一行:

image_output_sequence = tf.Variable(tf.zeros([batch_size, max_sequence_length, 1], tf.float32))

替换为:

image_output_sequence = tf.TensorArray(size=batch_size, dtype=tf.float32, element_shape=[max_sequence_length, 1], infer_shape=True)

TensorArray 实际上并不要求每个元素都有固定的形状,但对于我来说它是固定的,所以最好强制执行。

然后在 body 函数中,替换为:

ios[lc].assign(padded_cnn_features)

与:

ios = ios.write(lc, padded_cnn_output)

然后在tf.while_loop语句之后,可以把TensorArray堆叠起来形成一个正则的Tensor进一步处理:

stacked_tensor = result.stack()