Python 计算tensorflow中两个张量行的所有对组合

Python 计算tensorflow中两个张量行的所有对组合,python,numpy,tensorflow,Python,Numpy,Tensorflow,我试图在tensorflow中定义一个自定义op,其中有一点我需要构造一个矩阵(z),该矩阵将包含两个矩阵(x和y)行对的所有组合的总和。通常,x和y的行数是动态的 在numpy中,它相当简单: import numpy as np from itertools import product rows_x = 4 rows_y = 2 dim = 2 x = np.arange(dim*rows_x).reshape(rows_x, dim) y = np.arange(dim*rows_y

我试图在tensorflow中定义一个自定义op,其中有一点我需要构造一个矩阵(
z
),该矩阵将包含两个矩阵(
x
y
)行对的所有组合的总和。通常,
x
y
的行数是动态的

在numpy中,它相当简单:

import numpy as np
from itertools import product

rows_x = 4
rows_y = 2
dim = 2

x = np.arange(dim*rows_x).reshape(rows_x, dim)
y = np.arange(dim*rows_y).reshape(rows_y, dim)

print('x:\n{},\ny:\n{}\n'.format(x, y))

z = np.zeros((rows_x*rows_y, dim))
print('for loop:')
for i, (x_id, y_id) in enumerate(product(range(rows_x), range(rows_y))):
    print('row {}: {} + {}'.format(i, x[x_id, ], y[y_id, ]))
    z[i, ] = x[x_id, ] + y[y_id, ]

print('\nz:\n{}'.format(z))
返回:

x:
[[0 1]
 [2 3]
 [4 5]
 [6 7]],
y:
[[0 1]
 [2 3]]

for loop:
row 0: [0 1] + [0 1]
row 1: [0 1] + [2 3]
row 2: [2 3] + [0 1]
row 3: [2 3] + [2 3]
row 4: [4 5] + [0 1]
row 5: [4 5] + [2 3]
row 6: [6 7] + [0 1]
row 7: [6 7] + [2 3]

z:
[[  0.   2.]
 [  2.   4.]
 [  2.   4.]
 [  4.   6.]
 [  4.   6.]
 [  6.   8.]
 [  6.   8.]
 [  8.  10.]]
然而,我不知道如何在tensorflow中实现类似的东西

import tensorflow as tf

x = tf.constant([[0, 1],[2, 3],[4, 5],[6, 7]], dtype=tf.float32)
y = tf.constant([[0, 1],[2, 3]], dtype=tf.float32)

x_ = tf.expand_dims(x, 0)
y_ = tf.expand_dims(y, 1)
z = tf.reshape(tf.add(x_, y_), [-1, 2])
# or more succinctly 
z = tf.reshape(x[None] + y[:, None], [-1, 2])

sess = tf.Session()
sess.run(z)
我主要是通过SO和tensorflow API,希望找到一个函数,可以产生两个张量元素的组合,或者一个函数,可以给出张量元素的排列,但是没有用


欢迎提出任何建议。

选项1

z
定义为变量并更新其行:

import tensorflow as tf
from itertools import product


x = tf.constant([[0, 1],[2, 3],[4, 5],[6, 7]],dtype=tf.float32)
y = tf.constant([[0, 1],[2, 3]],dtype=tf.float32)

rows_x,dim=x.get_shape()
rows_y=y.get_shape()[0]

z=tf.Variable(initial_value=tf.zeros([rows_x*rows_y,dim]),dtype=tf.float32)
for i, (x_id, y_id) in enumerate(product(range(rows_x), range(rows_y))):
    z=tf.scatter_update(z,i,x[x_id]+y[y_id])

with tf.Session() as sess:
    tf.global_variables_initializer().run()
    z_val=sess.run(z)
    print(z_val)
这张照片

[[  0.   2.]
 [  2.   4.]
 [  2.   4.]
 [  4.   6.]
 [  4.   6.]
 [  6.   8.]
 [  6.   8.]
 [  8.  10.]]
选项2

创建
z
throw列表理解:

import tensorflow as tf
from itertools import product


x = tf.constant([[0, 1],[2, 3],[4, 5],[6, 7]],dtype=tf.float32)
y = tf.constant([[0, 1],[2, 3]],dtype=tf.float32)

rows_x,dim=x.get_shape().as_list()
rows_y=y.get_shape().as_list()[0]


z=[x[x_id]+y[y_id] for x_id in range(rows_x) for y_id in range(rows_y)]
z=tf.reshape(z,(rows_x*rows_y,dim))

with tf.Session() as sess:
    z_val=sess.run(z)
    print(z_val)
比较:第二种解决方案的速度大约快两倍(仅测量两种解决方案中
z
的结构)。具体而言,时间安排如下:
第一种解决方案:0.211秒,第二种解决方案:0.137秒。

您可以简单地使用tensorflow的广播功能

import tensorflow as tf

x = tf.constant([[0, 1],[2, 3],[4, 5],[6, 7]], dtype=tf.float32)
y = tf.constant([[0, 1],[2, 3]], dtype=tf.float32)

x_ = tf.expand_dims(x, 0)
y_ = tf.expand_dims(y, 1)
z = tf.reshape(tf.add(x_, y_), [-1, 2])
# or more succinctly 
z = tf.reshape(x[None] + y[:, None], [-1, 2])

sess = tf.Session()
sess.run(z)

这是魔法。。。所以,为了正确地理解这一点:首先展开
x
y
,这样
x_
具有形状[1,4,2],而
y_
具有形状[3,1,2]。然后,
tf.add
的广播功能“弄清楚”如何将维度填充到[3,4,2](这是
tf.add(x,y)
的形状),最后,
tf.reformate
确保我们在
z
中有两列。“弄清楚”是关键部分,正如我所读的:。。。。。。“当遇到两个兼容的数组时,结果形状在每个维度索引的两个输入中具有最大值。”,然后:“出现一种特殊情况,并且也支持这种情况,其中每个输入数组在不同索引处具有退化维度。在这种情况下,结果是一个“外部操作”“这很微妙。谢谢你的回答!施工时间通常是一个无效的性能指标,因为它只发生一次;没有人关心这两个方面的差异