Tensorflow 中的笛卡尔积

Posted

技术标签:

【中文标题】Tensorflow 中的笛卡尔积【英文标题】:Cartesian Product in Tensorflow 【发布时间】:2018-04-18 08:43:19 【问题描述】:

有没有像 itertools.product 这样在 Tensorflow 中做笛卡尔积的简单方法?我想获得两个张量(ab)的元素的组合,在 Python 中,可以通过 itertools 作为list(product(a, b))。我正在寻找 Tensorflow 中的替代方案。

【问题讨论】:

【参考方案1】:

我在这里假设ab 都是一维张量。

要获得两者的笛卡尔积,我会使用tf.expand_dimstf.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 张量,其中 ab 的元素的每个组合都在最后一个维度中表示。

【讨论】:

【参考方案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 中的笛卡尔积的主要内容,如果未能解决你的问题,请参考以下文章

笛卡尔积

什么是笛卡尔积?

sql中的笛卡尔积

pandas 中的笛卡尔积

笛卡尔积

一组python的幂集和笛卡尔积