我正在尝试以python方式处理可变大小的张量,如下所示:
# X is of shape [m, n]
for x in X:
process(x)
我曾尝试使用 tf.scan ,问题是我想处理每个子张量,所以我尝试使用嵌套的扫描,但是我启用了它,因为 tf.scan 使用累加器,如果没有找到它将把 elems 的第一个条目作为初始化程序,我不会这样做#39我想做。 举个例子,假设我想在张量的每个元素中添加一个(这只是一个例子),我想逐个元素地处理它。如果我运行下面的代码,我将只添加一个子张量,因为 scan 将第一个张量视为初始化器,以及每个子张量的第一个元素。
import numpy as np
import tensorflow as tf
batch_x = np.random.randint(0, 10, size=(5, 10))
x = tf.placeholder(tf.float32, shape=[None, 10])
def inner_loop(x_in):
return tf.scan(lambda _, x_: x_ + 1, x_in)
outer_loop = tf.scan(lambda _, input_: inner_loop(input_), x, back_prop=True)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
rs = sess.run(outer_loop, feed_dict={x: batch_x})
有什么建议吗?
答案 0 :(得分:7)
要循环张量,您可以尝试tf.unstack
将rank-R张量的给定维度解包为rank-(R-1)张量。
因此,为每个张量添加1会看起来像:
import tensorflow as tf
x = tf.placeholder(tf.float32, shape=(None, 10))
x_unpacked = tf.unstack(x) # defaults to axis 0, returns a list of tensors
processed = [] # this will be the list of processed tensors
for t in x_unpacked:
# do whatever
result_tensor = t + 1
processed.append(result_tensor)
output = tf.concat(processed, 0)
with tf.Session() as sess:
print(sess.run([output], feed_dict={x: np.zeros((5, 10))}))
显然,您可以从列表中进一步解压缩每个张量以处理它,直到单个元素。为避免大量嵌套解压缩,您可以先尝试使用tf.reshape(x, [-1])
展平x,然后像
flattened_unpacked = tf.unstack(tf.reshape(x, [-1])
for elem in flattened_unpacked:
process(elem)
在这种情况下,elem
是标量。
答案 1 :(得分:7)
大多数tensorflow内置函数都可以元素应用。所以你可以将张量传递给函数。像:
outer_loop = inner_loop(x)
但是,如果你有一些无法以这种方式应用的功能(它真的很容易看到这个功能),你可以使用map_fn
。
说,你的函数只是给张量的每个元素(或其他)加1:
inputs = tf.placeholder...
def my_elementwise_func(x):
return x + 1
def recursive_map(inputs):
if tf.shape(inputs).ndims > 0:
return tf.map_fn(recursive_map, inputs)
else:
return my_elementwise_func(inputs)
result = recursive_map(inputs)