【问题标题】:Looping over a tensor循环张量
【发布时间】:2017-09-05 18:18:35
【问题描述】:

我正在尝试以 python 方式处理可变大小的张量,类似于:

# X is of shape [m, n]
for x in X:
    process(x)

我尝试过使用tf.scan,问题是我想处理每个子张量,所以我尝试使用嵌套scan,但是我可以这样做,因为 tf.scan 与累加器一起工作,如果没有找到,它将把 elems 的第一个条目作为初始化程序,我不这样做想要做。 例如,假设我想为我的张量的每个元素添加一个(这只是一个示例),并且我想逐个元素地处理它。如果我运行下面的代码,我只会将一个添加到子张量中,因为 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})

有什么建议吗?

【问题讨论】:

    标签: python tensorflow


    【解决方案1】:

    要遍历张量,您可以尝试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 是一个标量。

    【讨论】:

    • 我之前试过这个,它引发了 ValueError 异常,因为我们正在使用一个 None 张量作为 dim_0
    • 哦,对不起,我错过了unstack 不适用于无尺寸。不过我发现了这个问题,Using tf.unpack() when first dimension of Variable is None 似乎得到了很好的回答。
    • 谢谢你 - 我不清楚是否可以以正常的 Python 方式遍历张量列表。就我而言,我使用 tf.split 而不是 unstack
    【解决方案2】:

    大部分 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)  
    

    【讨论】:

    • 我的问题比这更普遍,我一直在寻找解决方案,但到目前为止我没有成功。我想对张量的每个条目执行操作,上面的解决方案只执行元素操作。还有什么建议吗?
    • 您能否提供一个对张量的每个条目进行操作的函数示例?
    • 我想根据一些规则处理每个条目,例如我想要:sum(pos_xi) + 2 * sum(neg_xi)。矩阵 = [[1, -2, 3], [-5, 0, 1]] 第一项:(1+3) + 2*(-2) = 0 第二项:(0+1) + 2*( -5) = -9 结果 = [0, -9]
    • 在这种特殊情况下 tf.reduce_sum(a, 1),其中 a 是 tf.maximum(t, 0) - 2*tf.maximum(-t, 0) 应该可以工作。 Tensorflow 有很多函数可以执行 reduce 操作(sum、mean、max、min 等)和 elementwise 操作。通过适当组合这些功能,可以在绝大多数情况下达到预期的效果。
    • 经过一番搜索,似乎当您指出要执行任何处理之王时,您必须在您的张量上组合操作,并找到一种方法来向量化您的计算。对于那部分,你必须挤压你的思想,弄脏你的手!
    猜你喜欢
    • 2020-07-02
    • 1970-01-01
    • 2019-04-28
    • 1970-01-01
    • 2018-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多