如何在tensorflow中使用tf.while_loop()进行可变长度输入?

时间:2017-01-12 03:35:07

标签: python tensorflow

我正在尝试使用tf.while_loop()来处理可变长度输入。但是,我只能用它来固定长度。将shape =(4)更改为shape =(None)后,代码不再有效。 tf.dynamic_rnn似乎处理可变长度输入。我不确定tf.ynamic_rnn是如何用tf.while_loop()实现的。

import tensorflow as tf
import numpy as np
from tensorflow.python.ops import tensor_array_ops
from tensorflow.python.ops import array_ops

with tf.Graph().as_default(), tf.Session() as sess:
  initial_m = tf.Variable(0.0, name='m')

  inputs = tf.placeholder(dtype='float32', shape=(4))
  #The code no longer works after I change shape=(4) to shape=(None)
  #inputs = tf.placeholder(dtype='float32', shape=(None)) 

  time_steps = tf.shape(inputs)[0]

  initial_outputs = tf.TensorArray(dtype=tf.float32, size=time_steps)
  initial_t = tf.constant(0, dtype='int32')

  def should_continue(t, *args):
    return t < time_steps

  def iteration(t, m, outputs_):
    cur = tf.gather(inputs, t)
    m  = m * 0.5 + cur * 0.5
    outputs_ = outputs_.write(t, m)
    return t + 1, m, outputs_

  t, m, outputs = tf.while_loop(
    should_continue, iteration,
    [initial_t, initial_m, initial_outputs])

  outputs = outputs.pack()
  init = tf.global_variables_initializer()
  sess.run([init])
  print sess.run([outputs], feed_dict={inputs: np.asarray([1,1,1,1])})

输出(更改前):

[array([ 0.5   ,  0.75  ,  0.875 ,  0.9375], dtype=float32)]

输出(更改后):

Traceback (most recent call last):
  File "simple.py", line 26, in <module>
    [initial_t, initial_m, initial_outputs])
  File "/usr/local/lib/python2.7/site-packages/tensorflow/python/ops/control_flow_ops.py", line 2636, in while_loop
    result = context.BuildLoop(cond, body, loop_vars, shape_invariants)
  File "/usr/local/lib/python2.7/site-packages/tensorflow/python/ops/control_flow_ops.py", line 2469, in BuildLoop
    pred, body, original_loop_vars, loop_vars, shape_invariants)
  File "/usr/local/lib/python2.7/site-packages/tensorflow/python/ops/control_flow_ops.py", line 2450, in _BuildLoop
    _EnforceShapeInvariant(m_var, n_var)
  File "/usr/local/lib/python2.7/site-packages/tensorflow/python/ops/control_flow_ops.py", line 586, in _EnforceShapeInvariant
    % (merge_var.name, m_shape, n_shape))
ValueError: The shape for while/Merge_1:0 is not an invariant for the loop. It enters the loop with shape (), but has shape <unknown> after one iteration. Provide shape invariants using either the `shape_invariants` argument of tf.while_loop or set_shape() on the loop variables.

2 个答案:

答案 0 :(得分:8)

如果从所有变量中删除形状,它都有效:

import tensorflow as tf
import numpy as np

config = tf.ConfigProto(graph_options=tf.GraphOptions(
  optimizer_options=tf.OptimizerOptions(opt_level=tf.OptimizerOptions.L0)))
tf.reset_default_graph()
sess = tf.Session("", config=config)
#initial_m = tf.Variable(0.0, name='m')

#The code no longer works after I change shape=(4) to shape=(None)
inputs = tf.placeholder(dtype='float32', shape=(None)) 
time_steps = tf.shape(inputs)[0]
initial_outputs = tf.TensorArray(dtype=tf.float32, size=time_steps)
initial_t = tf.placeholder(dtype='int32')
initial_m = tf.placeholder(dtype=tf.float32)

def should_continue(t, *args):
    return t < time_steps

def iteration(t, m, outputs_):
    cur = tf.gather(inputs, t)
    m  = m * 0.5 + cur * 0.5
    outputs_ = outputs_.write(t, m)
    return t + 1, m, outputs_

t, m, outputs = tf.while_loop(should_continue, iteration,
                              [initial_t, initial_m, initial_outputs])

outputs = outputs.stack()
init = tf.global_variables_initializer()
sess.run([init])
print(sess.run([outputs],
               feed_dict={inputs: np.asarray([1, 1, 1, 1]), initial_t: 0,
                          initial_m: 0.}))

答案 1 :(得分:2)

if ($_POST) { foreach ($_POST as $key => $value) { $name = "{$key}"; $$name = $value; echo "<pre>"; echo $name; } echo "<pre>"; echo $name; echo "<pre>"; echo $age; echo "<pre>"; echo $location; } 具有一个名为tf.while_loop的键控参数。在那里,您可以列出所有张量的预期形状,从而可以指定哪些尺寸应该保持不变,哪些尺寸可以变化。例如,您可以像这样构建循环:

shape_invariants

这将允许t, final_tensor = tf.while_loop(should_continue, iteration, [t0, initial_tensor], [t0.get_shape(), tf.TensorShape([None,10])]) 改变其第一维度,只要第二维度保持大小为10。