Skip to main content
 首页 » 编程设计

python之tensorflow :如何交错两个张量的列(例如使用 tf.scatter_nd)

2024年09月07日27cyq1162

我读过 tf.scatter_nd documentation并运行 1D 和 3D 张量的示例代码......现在我正在尝试为 2D 张量执行此操作。我想“交错”两个张量的列。对于一维张量,可以通过

''' 
We want to interleave elements of 1D tensors arr1 and arr2, where 
arr1 = [10, 11, 12] 
arr2 = [1, 2, 3, 4, 5, 6] 
such that 
desired result = [1, 2, 10, 3, 4, 11, 5, 6, 12] 
''' 
 
import tensorflow as tf 
 
with tf.Session() as sess: 
 
    updates1 = tf.constant([1,2,3,4,5,6]) 
    indices1 = tf.constant([[0], [1], [3], [4], [6], [7]]) 
    shape = tf.constant([9]) 
    scatter1 = tf.scatter_nd(indices1, updates1, shape) 
 
    updates2 = tf.constant([10,11,12]) 
    indices2 = tf.constant([[2], [5], [8]]) 
    scatter2 = tf.scatter_nd(indices2, updates2, shape) 
 
    result = scatter1 + scatter2 
 
    print(sess.run(result)) 

(旁白:是否有更好的方法来做到这一点?我洗耳恭听。)

这给出了输出

[1 2 10 3 4 11 5 6 12]

耶!成功了!

现在让我们尝试将其扩展到 2D。

    ''' 
    We want to interleave the *columns* (not rows; rows would be easy!) of 
 
    arr1 = [[1,2,3,4,5,6],[1,2,3,4,5,6],[1,2,3,4,5,6]] 
    arr2 = [[10 11 12], [10 11 12], [10 11 12]] 
    such that 
    desired result = [[1,2,10,3,4,11,5,6,12],[1,2,10,3,4,11,5,6,12],[1,2,10,3,4,11,5,6,12]] 
    ''' 
 
    updates1 = tf.constant([[1,2,3,4,5,6],[1,2,3,4,5,6],[1,2,3,4,5,6]]) 
    indices1 = tf.constant([[0], [1], [3], [4], [6], [7]]) 
    shape = tf.constant([3, 9]) 
    scatter1 = tf.scatter_nd(indices1, updates1, shape) 

这给出了错误 ValueError:indices.shape=[6,1] 的外 1 维必须匹配外 1 updates.shape=[3,6] 的维度:两个形状中的维度 0 必须相等,但是 是 6 和 3。形状是 [6] 和 [3]。对于'ScatterNd_2'(操作:'ScatterNd')与 输入形状:[6,1]、[3,6]、[2]。

似乎我的 indices 正在指定行索引而不是列索引,并且考虑到数组在 numpy 和 tensorflow 中“连接”的方式(即行优先顺序),这是否意味着 我需要明确为 updates1 中的每个元素指定每一对索引吗? 或者是否有某种我可以用于行的“通配符”规范? (注意 indices1 = tf.constant([[:,0], [:,1], [:,3], [:,4], [:,6], [:,7]]) 给出语法错误,因为它可能应该。)

只做一个转置,交错行,然后转回去会更容易吗? 因为我试过了...

scatter1 = tf.scatter_nd(indices1, tf.transpose(updates1), tf.transpose(shape)) 
print(sess.run(tf.transpose(scatter1))) 

...并收到一条长得多 的错误消息,除非有人要求,否则我不想发布。

PS- 我进行了搜索以确保这不是重复的——我发现很难想象其他人以前没有问过这个问题——但一无所获。

请您参考如下方法:

这是纯粹的切片,但我不知道像 arr1[0:,:][:,:2] 这样的语法实际上有效。似乎是这样,但不确定是否更好。

这可能是您正在寻找的通配符切片机制。

arr1 = tf.constant([[1,2,3,4,5,6],[1,2,3,4,5,7],[1,2,3,4,5,8]]) 
arr2 = tf.constant([[10, 11, 12], [10, 11, 12], [10, 11, 12]]) 
 
with tf.Session() as sess : 
    sess.run( tf.global_variables_initializer() ) 
    print(sess.run(tf.concat([arr1[0:,:][:,:2], arr2[0:,:] [:,:1], 
                              arr1[0:,:][:,2:4],arr2[0:, :][:, 1:2], 
                              arr1[0:,:][:,4:6],arr2[0:, :][:, 2:3]],axis=1))) 

输出是

[[ 1  2 10  3  4 11  5  6 12] 
 [ 1  2 10  3  4 11  5  7 12] 
 [ 1  2 10  3  4 11  5  8 12]] 

例如,

arr1[0:,:] 返回

[[1 2 3 4 5 6] 
 [1 2 3 4 5 7] 
 [1 2 3 4 5 8]] 

和arr1[0:,:][:,:2]返回前两列

[[1 2] 
 [1 2] 
 [1 2]] 

轴为 1。