首页 > 解决方案 > 使用 Tensorflow 根据索引数组将元素插入张量

问题描述

使用 Tensorflow,我想根据索引数组 (idx) 的值将值插入到数组 (X) 中,以便索引表示的每个实体在结果数组中具有相同数量的元素。

例如,假设初始数组 X 和索引如下

X = tf.range(6) # [0, 1, 2, 3, 4, 5]
idx = tf.constant([0, 0, 1, 1, 1, 2]) 
fill_value = -999 # value to insert

idx中,值 1 出现的次数最多 (3),因此我想在 X 中填充其他索引值的缺失条目以匹配 3。这意味着插入值 0,因为它出现 2次,以及 idx 值 2 的两次插入。

结果应该是[0, 1, -999, 2, 3, 4, 5, -999, -999]

我已经能够通过使用参差不齐的张量来做到这一点,但是在我的应用程序中,不支持参差不齐的张量。作为参考,这就是我的做法:

# solution using ragged arrays
X_ragged = tf.RaggedTensor.from_value_rowids(X, idx)
result = x_ragged.to_tensor(default_value=fill_value)
tf.reshape(result, -1)
# <tf.Tensor: shape=(9,), dtype=int32, numpy=array([ 0, 1, -999, 2, 3, 4, 5, -999, -999], # dtype=int32)>

标签: tensorflowtensorflow2.0

解决方案


有很多方法可以编码,但如果你从

elements, index, count = tf.unique_with_counts([0, 0, 0, 0, 1, 1, 2])
print('Elements ',elements)

它提供了您需要的所有数据,然后以下代码用“填充物”填充“参差不齐”的张量

注意:我if( slice.shape[0] < 4):对此进行了硬编码。这是最长重复值的长度,但您可以从中获取 tf.unique_with_counts并传递它。我也不考虑缺失值 - [0, 0, 0, 0, 2]。但是elements在上面的代码中给了你现在的东西。因此,当您发现缺少值时,您可以使用简单的循环添加一行“填充”。

import tensorflow as tf

fill_value = tf.constant([-999]) # value to insert
elements, index, count = tf.unique_with_counts([0, 0, 0, 0, 1, 1, 2])
print('Elements ',elements)
values = [3, 1, 4, 1, 5, 9, 2]

ta = tf.TensorArray(dtype=tf.int32,size=1, dynamic_size=True,clear_after_read=False)

def fill_values(slice,i):
    slices = slice
    if( slice.shape[0] < 4):
        for j in range( 4 - slice.shape[0] ):
            slices = tf.concat([slices,fill_value],0)
            tf.print('Fill ',slices)
    return ta.write(i,slices)

def slices( begin, c, i, filler ):
    slice = tf.slice(  values,
                       begin=[ begin ],
                       size=[ c[i] ])
    begin = begin + c[i]
    tf.print('Slice' , slice)
    ta = fill_values(slice,i) # If I don't use the return value this warning is shown
    print('TensorArray ', ta.stack()) # So I print it
    # Note: The output of this function should be used.
    # If it is not, a warning will be logged or an error may be raised.
    # To mark the output as used, call its .mark_used() method.
    return [begin , c, tf.add(i, 1), filler]

def condition( begin, c, i, _ ):
    return tf.less(i, tf.size(c))

i = tf.constant(0)
filler = tf.constant(-999)
r = tf.while_loop(  condition,slices,[0, count, i, filler ])
print('TensorArray ', ta.stack())

输出是

TensorArray  tf.Tensor(
[[   3    1    4    1]
 [   5    9 -999 -999]
 [   2 -999 -999 -999]], shape=(3, 4), dtype=int32)

但是tf.RaggedTensor比较容易。不知道为什么你不能使用它。


推荐阅读