地图\u fn和tf.keras.层Inpu先生

2024-04-27 03:41:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个输入,它由两个整数组成,start和end。 我想生成一个张量,它包含从开始到结束的整数。 例如,给定(2,5)作为输入,我想生成(2,3,4,5) 以下是我的尝试:

start_end_input = tf.keras.layers.Input(shape=(2,), dtype=tf.int32, name="start_end")
tf.map_fn(lambda row: tf.range(row[0], row[1]), start_end_input, dtype=(tf.int32, tf.int32))

我得到了这个:

self._tensor_array = [None for _ in range(size)]
TypeError: 'Tensor' object cannot be interpreted as an integer

有什么想法吗?你知道吗

谢谢。你知道吗


Tags: namemapinputlayerstfrange整数start
1条回答
网友
1楼 · 发布于 2024-04-27 03:41:31

我不太清楚为什么需要在这里使用keras.Input层。但是假设您可以不使用这个层(因为它使单独访问元素变得复杂,例如x[0])。既然您使用的是tf2.0,我希望您可以直接使用numpy数组或tf.Tensor。如果没有,请告诉我,我将尝试寻找一种合并keras.Input层的方法。你知道吗

但我主要想指出您将遇到的错误(即使您通过上面的步骤来传递这个错误),以及对于某些工作解决方案,您可以预期的性能差异。简而言之,tf.map_fn无法处理在每行转换之后返回可变大小输出的情况。更多细节here。问题就是这样,因为tf.range将返回大小不同的行。你知道吗

但是,如果您确定这些范围界限在合理的上限之下(例如,范围的最大值将是1000),您可以使用tf.map_fn,如下所示。基本上,我们正在填充行转换的每个结果,以便所有结果都具有相同的长度。你知道吗

m = tf.reduce_max(a)

def range_with_map(a):
    o = tf.map_fn(lambda x: tf.concat([tf.range(x[0],x[1]), tf.ones(shape=[x[0]+m-x[1]+1], dtype=tf.int32)*-1], axis=0), a, dtype=tf.int32)
    b = tf.RaggedTensor.from_tensor(o, padding=-1)
    return b

%timeit range_with_map(a)

它跑进来了

18.3 ms ± 1.58 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

您还可以使用@tf.function进一步提高性能

@tf.function
def range_with_map_v2(a):
    o = tf.map_fn(
        lambda x: tf.concat([tf.range(x[0],x[1]), tf.ones(shape=[x[0]+m-x[1]+1], dtype=tf.int32)*-1], axis=0), 
        a, dtype=tf.int32) 
    b = tf.RaggedTensor.from_tensor(o, padding=-1)
    return b

6.63 ms ± 304 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

但是如果这不是一个选项,那么我能看到的最好的方法就是使用for循环。你知道吗

def range_with_for_loop(a):
    res = []
    for r in a:
        res.append(tf.reshape(tf.range(r[0],r[1]),[1,-1]))        
    return tf.ragged.stack(res)

不用说这是最糟糕的表现

26.1 ms ± 1.04 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

:所有性能均为w.r.t.我的机器配备了Nvidia GTX 960

相关问题 更多 >