Tensorflow:从张量堆叠所有行对

时间:2018-05-25 20:54:46

标签: python tensorflow machine-learning

给定张量t=[[1,2], [3,4]],我需要生成ts=[[1,2,1,2], [1,2,3,4], [3,4,1,2], [3,4,3,4]]。也就是说,我需要将所有行对堆叠在一起。 重要:张量具有维度[无,2],即。第一个维度是可变的。

我试过了:

  • 使用tf.while_loop生成索引列表idx=[[0, 0], [0, 1], [1, 0], [1, 1]],然后tf.gather(ts, idx)。这有效,但很乱,我不知道如何处理渐变。
  • 2 for循环遍历tf.unstack(t),将堆叠的行添加到缓冲区,然后tf.stack(buffer)。如果第一个维度是可变的,这不起作用。
  • 寻找广播的灵感。例如,给定x=t.expand_dims(t, 0), y=t.expand_dims(t, 1), s=tf.reshape(tf.add(x, y), [-1, 2]) s将是[[2,4],[4,6],[4,6],[6,8]],即。每行组合的总和。但是我怎样才能进行堆叠而不是求和?我已经失败了2天:)

2 个答案:

答案 0 :(得分:3)

tf.meshgrid()的解决方案和一些重塑:

import tensorflow as tf
import numpy as np

t = tf.placeholder(tf.int32, [None, 2])
num_rows, size_row = tf.shape(t)[0], tf.shape(t)[1] # actual dynamic dimensions

# Getting pair indices using tf.meshgrid:
idx_range = tf.range(num_rows)
pair_indices = tf.stack(tf.meshgrid(*[idx_range, idx_range]))
pair_indices = tf.transpose(pair_indices, perm=[1, 2, 0])

# Finally gathering the rows accordingly:
res = tf.reshape(tf.gather(t, pair_indices), (-1, size_row * 2))

with tf.Session() as sess:
    print(sess.run(res, feed_dict={t: np.array([[1,2], [3,4], [5,6]])}))
    # [[1 2 1 2]
    #  [3 4 1 2]
    #  [5 6 1 2]
    #  [1 2 3 4]
    #  [3 4 3 4]
    #  [5 6 3 4]
    #  [1 2 5 6]
    #  [3 4 5 6]
    #  [5 6 5 6]]

使用笛卡尔积的解决方案:

import tensorflow as tf
import numpy as np

t = tf.placeholder(tf.int32, [None, 2])
num_rows, size_row = tf.shape(t)[0], tf.shape(t)[1] # actual dynamic dimensions

# Getting pair indices by computing the indices cartesian product:
row_idx = tf.range(num_rows)
row_idx_a = tf.expand_dims(tf.tile(tf.expand_dims(row_idx, 1), [1, num_rows]), 2)
row_idx_b = tf.expand_dims(tf.tile(tf.expand_dims(row_idx, 0), [num_rows, 1]), 2)
pair_indices = tf.concat([row_idx_a, row_idx_b], axis=2)

# Finally gathering the rows accordingly:
res = tf.reshape(tf.gather(t, pair_indices), (-1, size_row * 2))

with tf.Session() as sess:
    print(sess.run(res, feed_dict={t: np.array([[1,2], [3,4], [5,6]])}))
    # [[1 2 1 2]
    #  [1 2 3 4]
    #  [1 2 5 6]
    #  [3 4 1 2]
    #  [3 4 3 4]
    #  [3 4 5 6]
    #  [5 6 1 2]
    #  [5 6 3 4]
    #  [5 6 5 6]]

答案 1 :(得分:1)

可以通过以下方式实现:

tf.concat([tf.tile(tf.expand_dims(t,1), [1, tf.shape(t)[0], 1]), tf.tile(tf.expand_dims(t,0), [tf.shape(t)[0], 1, 1])], axis=2)

详细步骤:

t = tf.placeholder(tf.int32, shape=[None, 2])
#repeat each row of t
d = tf.tile(tf.expand_dims(t,1), [1, tf.shape(t)[0], 1])
#Output:
#[[[1 2] [1 2]]
# [[3 4] [3 4]]]

#repeat the entire input t
e = tf.tile(tf.expand_dims(t,0), [tf.shape(t)[0], 1, 1])
#Output:
#[[[1 2] [3 4]]
# [[1 2] [3 4]]]

#concat
f = tf.concat([d, e], axis=2)

with tf.Session() as sess:
   print(sess.run(f, {t:np.asarray([[1,2],[3,4]])}))  
#Output
#[[[1 2 1 2]
#[1 2 3 4]]
#[[3 4 1 2]
#[3 4 3 4]]]