【发布时间】:2018-04-18 08:43:19
【问题描述】:
有没有像 itertools.product 这样在 Tensorflow 中做笛卡尔积的简单方法?我想获得两个张量(a 和 b)的元素的组合,在 Python 中,可以通过 itertools 作为list(product(a, b))。我正在寻找 Tensorflow 中的替代方案。
【问题讨论】:
标签: python tensorflow
有没有像 itertools.product 这样在 Tensorflow 中做笛卡尔积的简单方法?我想获得两个张量(a 和 b)的元素的组合,在 Python 中,可以通过 itertools 作为list(product(a, b))。我正在寻找 Tensorflow 中的替代方案。
【问题讨论】:
标签: python tensorflow
我在这里假设a 和b 都是一维张量。
要获得两者的笛卡尔积,我会使用tf.expand_dims 和tf.tile 的组合:
a = tf.constant([1,2,3])
b = tf.constant([4,5,6,7])
tile_a = tf.tile(tf.expand_dims(a, 1), [1, tf.shape(b)[0]])
tile_a = tf.expand_dims(tile_a, 2)
tile_b = tf.tile(tf.expand_dims(b, 0), [tf.shape(a)[0], 1])
tile_b = tf.expand_dims(tile_b, 2)
cartesian_product = tf.concat([tile_a, tile_b], axis=2)
cart = tf.Session().run(cartesian_product)
print(cart.shape)
print(cart)
您最终得到一个 len(a) * len(b) * 2 张量,其中 a 和 b 的元素的每个组合都在最后一个维度中表示。
【讨论】:
Jaba 的回答让我深受启发。如果你想得到两个二维张量的笛卡尔积,你可以这样做:
输入a:[N,L]和b:[M,L],得到一个[N*M,L]的concat张量
tile_a = tf.tile(tf.expand_dims(a, 1), [1, M, 1])
tile_b = tf.tile(tf.expand_dims(b, 0), [N, 1, 1])
cartesian_product = tf.concat([tile_a, tile_b], axis=2)
cartesian = tf.reshape(cartesian_product, [N*M, -1])
cart = tf.Session().run(cartesian)
print(cart.shape)
print(cart)
【讨论】:
a.shape[-1] + b.shape[-1] 而不是 [N * M, -1] 中的 -1 来修复它
一个更短的解决方案,使用tf.add() 进行广播(测试):
import tensorflow as tf
a = tf.constant([1,2,3])
b = tf.constant([4,5,6,7])
a, b = a[ None, :, None ], b[ :, None, None ]
cartesian_product = tf.concat( [ a + tf.zeros_like( b ),
tf.zeros_like( a ) + b ], axis = 2 )
with tf.Session() as sess:
print( sess.run( cartesian_product ) )
将输出:
[[[1 4]
[2 4]
[3 4]][[1 5]
[2 5]
[3 5]][[1 6]
[2 6]
[3 6]][[1 7]
[2 7]
[3 7]]]
【讨论】:
a = tf.constant([[[1,2,3],[4,5,6]],[[1,1,1],[1,1,1]]]) b = tf.constant([[[7,8,9],[10,11,12]]]) 的期望。
import tensorflow as tf
a = tf.constant([0, 1, 2])
b = tf.constant([2, 3])
c = tf.stack(tf.meshgrid(a, b, indexing='ij'), axis=-1)
c = tf.reshape(c, (-1, 2))
with tf.Session() as sess:
print(sess.run(c))
输出:
[[0 2]
[0 3]
[1 2]
[1 3]
[2 2]
[2 3]]
感谢 jdehesa:link
【讨论】:
Sunreef 的答案更简洁的版本使用 tf.stack 而不是 tf.concat
a = tf.constant([1,2,3])
b = tf.constant([4,5,6,7])
tile_a = tf.tile(tf.expand_dims(a, 1), [1, tf.shape(b)[0]])
tile_b = tf.tile(tf.expand_dims(b, 0), [tf.shape(a)[0], 1])
ans = tf.stack([tile_a, tile_b], -1)
【讨论】: