评估张量流中两个张量行的所有对组合

问题描述:

我想在张量流中定义一个自定义操作,其中在一个点上我需要构造一个矩阵(z),该矩阵将包含所有行对组合的总和两个矩阵(xy)。通常,xy的行数是动态的。评估张量流中两个张量行的所有对组合

在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类似的事情。

我主要是通过SO和张量流API来找到一个函数,该函数可以产生两个张量元素的组合,或者一个函数可以给出张量元素的排列,但是无济于事。

任何建议是最受欢迎的。

您可以简单地使用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]) 

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

这是神奇的...所以,为了得到这个正确的结果:首先扩展'x'和'y',以便'x_'具有形状[1,4,2],'y_'具有形状[3, 1,2]。然后,'tf.add'的广播能力“计算出”如何将尺寸填充到[3,4,2](这是'tf.add(x_,y_)''的形状),最后,'tf.reshape'确保'z'中有2列。 “解决”是关键部分,正如我在阅读[这里](https://www.tensorflow.org/performance/xla/broadcasting):... – ponadto

+0

...“当两个兼容的数组是遇到的情况,结果形状在每个维度索引处的两个输入中具有最大值“,然后:”出现特殊情况,并且也支持这种情况,其中每个输入数组在不同索引处具有退化维度。情况下,结果是一个“外部操作”。这是微妙的。谢谢你的答案! – ponadto

选项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抛列表理解:

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秒。

+0

构建时间通常是一个无效的性能指标,因为它只发生一次;没有人关心 Multihunter