看看代码:
import tensorflow as tf
import numpy as np
elems = tf.ones([1,2,3],dtype=tf.int64)
alternates = tf.map_fn(lambda x: (x, x, x), elems, dtype=(tf.int64, tf.int64, tf.int64))
with tf.Session() as sess:
print(sess.run(alternates))
Run Code Online (Sandbox Code Playgroud)
输出是:
(array([[[1, 1, 1],
[1, 1, 1]]], dtype=int64), array([[[1, 1, 1],
[1, 1, 1]]], dtype=int64), array([[[1, 1, 1],
[1, 1, 1]]], dtype=int64))
Run Code Online (Sandbox Code Playgroud)
我无法理解输出,谁能告诉我?
elems是张量,所以应该沿轴0拆包,我们会得到[[1,1,1],[1,1,1]],然后map_fn通[[1,1,1],[1,1,1]]入lambda x:(x,x,x),这意味着x=[[1,1,1],[1,1,1]],我想的输出map_fn是
[[[1,1,1],[1,1,1]],
[[1,1,1],[1,1,1]],
[[1,1,1],[1,1,1]]]
Run Code Online (Sandbox Code Playgroud)
输出的形状是[3,2,3]或列表shape(2,3)
但事实上,输出是一个张量列表,每个张量的形状是[1,2,3].
或者换句话说:
import tensorflow as tf
import numpy as np
elems = tf.constant([1,2,3],dtype=tf.int64)
alternates = tf.map_fn(lambda x: (x, 2*x, -x), elems, dtype=(tf.int64, tf.int64, tf.int64))
with tf.Session() as sess:
print(sess.run(alternates))
Run Code Online (Sandbox Code Playgroud)
为什么输出
(array([1, 2, 3], dtype=int64),
array([2, 4, 6], dtype=int64),
array([-1, -2, -3], dtype=int64))
Run Code Online (Sandbox Code Playgroud)
而不是
(array([1, 2, -1], dtype=int64),
array([2, 4, -2], dtype=int64),
array([3, 6, -3], dtype=int64))
Run Code Online (Sandbox Code Playgroud)
这两个问题是一样的.
import tensorflow as tf
import numpy as np
elems = [tf.constant([1,2,3],dtype=tf.int64)]
alternates = tf.map_fn(lambda x: x, elems, dtype=tf.int64)
with tf.Session() as sess:
print(sess.run(alternates))
Run Code Online (Sandbox Code Playgroud)
elems是一个张量列表,所以根据api,tf.constant([1,2,3],dtype=tf.int64)将沿-0轴解压缩,因此map_fn将起作用[x for x in [1,2,3]],但实际上它会引发错误.
ValueError: The two structures don't have the same nested structure. First struc
ture: <dtype: 'int64'>, second structure: [<tf.Tensor 'map/while/TensorArrayRead
V3:0' shape=() dtype=int64>].
Run Code Online (Sandbox Code Playgroud)
怎么了?
import tensorflow as tf
import numpy as np
elems = (tf.constant([1,2,3],dtype=tf.int64),tf.constant([1,2,3],dtype=tf.int64))
alternates = tf.map_fn(lambda x: x, elems, dtype=(tf.int64, tf.int64))
with tf.Session() as sess:
print(sess.run(alternates))
Run Code Online (Sandbox Code Playgroud)
输出是
(array([1, 2, 3], dtype=int64), array([1, 2, 3], dtype=int64))
Run Code Online (Sandbox Code Playgroud)
看来elems没有拆包,为什么?
import tensorflow as tf
import numpy as np
elems = (tf.constant([1,2,3],dtype=tf.int64),tf.constant([1,2,3],dtype=tf.int64))
alternates = tf.map_fn(lambda x: [x], elems, dtype=(tf.int64, tf.int64))
with tf.Session() as sess:
print(sess.run(alternates))
Run Code Online (Sandbox Code Playgroud)
它会引发错误
TypeError: The two structures don't have the same sequence type. First structure
has type <class 'tuple'>, while second structure has type <class 'list'>.
Run Code Online (Sandbox Code Playgroud)
谁能告诉我tf.map_fn是如何工作的?
第一,
elems = tf.ones([1,2,3],dtype=tf.int64)
Run Code Online (Sandbox Code Playgroud)
elems 是形状为1x2x3且充满1的3维张量,即:
[[[1, 1, 1],
[1, 1, 1]]]
Run Code Online (Sandbox Code Playgroud)
然后,
alternates = tf.map_fn(lambda x: (x, x, x), elems, dtype=(tf.int64, tf.int64, tf.int64))
Run Code Online (Sandbox Code Playgroud)
alternates是三个张量的元组,其形状与相同elems,每个张量根据给定的函数构建。由于该函数仅返回一个元组重复其输入三次,因此这意味着三个张量将与相同elems。如果函数是,lambda x: (x, 2 * x, -x)则第一个输出张量将与相同elems,第二个输出张量将为的两倍,elems而第三个输出张量则相反。
在所有这些情况下,最好使用常规运算代替tf.map_fn;但是,在某些情况下,可能会有一个函数接受N个维度的张量,并且您有一个要应用N + 1 的张量。
更新:
可以tf.map_fn这么说,我认为您正在考虑“另一种方式”。张量中元素或行的数量与函数中输出的数量之间没有一一对应的关系;实际上,您可以传递一个返回元组的函数,该元组具有所需的任意多个元素。
拿最后一个例子:
elems = tf.constant([1,2,3],dtype=tf.int64)
alternates = tf.map_fn(lambda x: (x, 2*x, -x), elems, dtype=(tf.int64, tf.int64, tf.int64))
Run Code Online (Sandbox Code Playgroud)
tf.map_fn首先elems在第一个轴上拆分,即1,2和3,然后将函数应用于每个轴,得到:
(1, 2, -1)
(2, 4, -2)
(3, 6, -3)
Run Code Online (Sandbox Code Playgroud)
请注意,正如我所说,这些元组可以具有所需的任意多个元素。现在,产生最终输出,将结果放在同一位置;所以你得到:
[1, 2, 3]
[2, 4, 6]
[-1, -2, -3]
Run Code Online (Sandbox Code Playgroud)
同样,如果函数产生的元组包含更多元素,则将获得更多的输出张量。
更新2:
关于您的新示例:
import tensorflow as tf
import numpy as np
elems = (tf.constant([1,2,3],dtype=tf.int64),tf.constant([1,2,3],dtype=tf.int64))
alternates = tf.map_fn(lambda x: x, elems, dtype=(tf.int64, tf.int64))
with tf.Session() as sess:
print(sess.run(alternates))
Run Code Online (Sandbox Code Playgroud)
该文件说:
此方法还允许多元素元素和fn的输出。如果elems是张量的(可能是嵌套的)列表或元组,则每个张量必须具有匹配的第一(解包)维。fn的签名可以匹配元素的结构。也就是说,如果elems为(t1,[t2,t3,[t4,t5]]),则fn的适当签名为:fn = lambda(t1,[t2,t3,[t4,t5]]):。
根据需要,这elems是两个张量的元组,它们在第一维中的大小相同。tf.map_fn一次获取每个输入张量的一个元素(因此是两个元素的元组)并对其应用给定的函数,后者应返回您传入的相同结构dtypes(也就是两个元素的元组);如果不给出dtypes,则预期输出与输入相同(同样,两个元素的元组,因此在您的情况下dtypes是可选的)。无论如何,它是这样的:
f((1, 1)) -> (1, 1)
f((2, 2)) -> (2, 2)
f((3, 3)) -> (3, 3)
Run Code Online (Sandbox Code Playgroud)
将这些结果组合在一起,将结构中的所有相应元素连接在一起;在这种情况下,第一个位置中的所有数字都产生第一输出,第二个位置中的所有数字都产生第二输出。最后,结果是所请求的结构(由两个元素组成的元组)充满了以下串联:
([1, 2, 3], [1, 2, 3])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9084 次 |
| 最近记录: |