为num_splits使用变量为tf.split()

时间:2016-01-24 00:04:41

标签: tensorflow

是否可以将num_split参数的占位符输入用于tf.split()?

我最好还是喜欢这样的事情:

num_splits = tf.placeholder(tf.int32)
inputs = tf.placeholder(tf.int32, [5, None])
split_inputs = tf.split(1, num_splits, inputs)


TypeError: Expected int for argument 'num_split' not <tensorflow.python.framework.ops.Tensor object at 0x10b819ad0>.

我的方法可能有问题。我希望枚举可变形状张量的维度。谢谢!

2 个答案:

答案 0 :(得分:14)

对于核心图操作,存在一种“张量张量输出”的一般哲学,因此如果您可以重构计算以处理可变大小的单个张量而不是可变数量的张量,则可以简化操作。

packunpacksplit等操作处理多个张量但在图形构建时编译为“张入/张量”操作,这就是为什么{{ 1}}需要修复。像num_splitsdynamic_partitiondynamic_stitch这样的操作可以为具有变量dequeue_many - 维度的单个张量接管部分功能。

如果你真的需要处理可变数量的张量,典型的方法是将计算分解为多个0调用,每个session.run调用一个输入张量,并使用队列将事物联系在一起。有一个run沿着第0维分割变量大小的输入,并为每一行产生张量,所以如果你想在slice_input_producer的每一行的循环中评估myfunction,你可以这样做

inputs

如果你运行它,你应该看到

def myfunction(vector):
  result = tf.reduce_sum(vector)
  print_result = tf.Print(result, [result], "myfunction called ")
  return print_result

MAX_ROWS = 10

# input matrix with 2 columns and unknown number of rows (<MAX_ROWS)
inputs = tf.placeholder(tf.int32, [None, 2])
# copy of inputs, will need to have a persistent copy of it because we will
# be fetching rows in different session.run calls
data = tf.Variable(inputs, validate_shape=False)
# input producer that iterates over the rows and pushes them onto Queue
row = tf.train.slice_input_producer([data], num_epochs=1, shuffle=False)[0]
myfunction_op = myfunction(row)

# this op will save placeholder values into the variable
init_op = tf.initialize_all_variables()

# Coordinator is not necessary in this case, but you'll need it if you have
# more than one Queue in order to close all queues together
sess = tf.Session()
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)

sess.run([init_op], feed_dict={inputs:[[0, 0], [1, 1], [2, 2]]})

try:
  for i in range(MAX_ROWS):
    sess.run([myfunction_op])
except tf.errors.OutOfRangeError:
  print('Done iterating')
finally:
  # When done, ask other threads to stop.
  coord.request_stop()

答案 1 :(得分:0)

在不相关的情况下,类似问题的解决方案是将占位符用于最大大小的固定长度。假设我有一个长度为40的序列。t = tf.range(40)。 现在在运行时,我得到了拆分(例如x = [6,9,10,5,1])。现在按照步骤

第1步: 确定可以拆分的最大数量,例如: 19

第2步

    num_splits = tf.placeholder(tf.int32, [19]) 
    y= tf.split(t, num_or_size_splits=num_splits, axis=0)

这会将序列分为运行时确定的拆分大小

步骤4 : 在运行时:

    x = [6,9,10,5,1] 
    x += [40-sum(x)] + [0 for i in range(19-1-len(x))]

第一行表示我们需要的实际拆分大小
拆分要求拆分大小总计为拆分总大小,在这种情况下为40,而剩余拆分的拆分大小为0。

session.run(y, feed_dict={text_len:x})将显示如下结果:

[0, 1, 2, 3, 4, 5]  
[ 6,  7,  8,  9, 10, 11, 12, 13, 14]  
[15, 16, 17, 18, 19, 20, 21, 22, 23, 24]  
[25, 26, 27, 28, 29]  
[30]  
[31, 32, 33, 34, 35, 36, 37, 38, 39]  
[]
.
.
[]  

步骤5 : (可选,首选)填充零,直到序列的最大长度

    def pad_up_to(t, max_in_dims, constant_values):
        s = tf.shape(t)
        paddings = [[0, m-s[i]] for (i,m) in enumerate(max_in_dims)]
        return tf.pad(t, paddings, 'CONSTANT', constant_values=constant_values)


    m = []
    for t1 in y :
      t1=tf.reshape(t1,[1,-1])
      t_padded = pad_up_to(t1, [1,15], 0)
      session.run(t_padded  , feed_dict={text_len:x})  
      m+=  [t_padded]
    m= tf.concat(m,0)

这将用0填充块以创建大小相等的块。

注意:上面的方法帮助我将序列转换为NLP相关任务的句子(句子数可变)

功能:pad_up_to()来自 Q:42334646