Tensorflow 中的笛卡尔积
Posted
技术标签:
【中文标题】Tensorflow 中的笛卡尔积【英文标题】:Cartesian Product in Tensorflow 【发布时间】:2018-04-18 08:43:19 【问题描述】:有没有像 itertools.product 这样在 Tensorflow 中做笛卡尔积的简单方法?我想获得两个张量(a
和 b
)的元素的组合,在 Python 中,可以通过 itertools 作为list(product(a, b))
。我正在寻找 Tensorflow 中的替代方案。
【问题讨论】:
【参考方案1】:我在这里假设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
的元素的每个组合都在最后一个维度中表示。
【讨论】:
【参考方案2】: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 或 b 为空,这将不起作用,但您可以通过使用a.shape[-1] + b.shape[-1]
而不是 [N * M, -1]
中的 -1 来修复它【参考方案3】:
一个更短的解决方案,使用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]]]
【讨论】:
这个答案太棒了!虽然可能不太可读,但它更通用。似乎适用于维度 1 之后的任意维度的张量。例如,它仍然会返回您对a = tf.constant([[[1,2,3],[4,5,6]],[[1,1,1],[1,1,1]]])
b = tf.constant([[[7,8,9],[10,11,12]]])
的期望。【参考方案4】:
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
【讨论】:
【参考方案5】: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)
【讨论】:
以上是关于Tensorflow 中的笛卡尔积的主要内容,如果未能解决你的问题,请参考以下文章