通过Tensorflow中段的长度计算tf.math.segment_sum中所需的段ID

时间:2019-02-20 15:37:39

标签: python python-3.x tensorflow tensorflow-datasets

我正在处理大小可变的顺序数据。 让我们考虑像

这样的数据
Y = [ [.01,.02], [.03,.04], [.05,.06], [.07,.08], [.09,.1] ]
l = [ 3, 2 ]

其中Y是对我的数据执行的一些辅助计算的结果,而l存储原始序列的长度。因此,在此示例中,[.01,.02], [.03,.04], [.05,.06]是对批次的第一序列执行的计算结果,[.07,.08], [.09,.1]是对长度为3的批次的第二序列执行的计算结果和2。 现在,我想对Y的条目做一些进一步的计算,但是要按顺序分组。在Tensorflow中,有tf.math.segment_sum的功能,可以按组执行。

让我们说我想用tf.math.segment_sum来总结。我会对

感兴趣
seq_ids = [ 0, 0, 0, 1, 1 ]
tf.math.segment_sum(Y, segment_ids=seq_ids) #returns [ [0.09 0.12], [0.16 0.18] ]

我现在面临的问题是从seq_ids获取l。 在numpy中,可以很容易地通过以下方式检索到该信息:

seq_ids = np.digitize( np.arange(np.sum(l)), np.cumsum(l) )

在Tensorflow中,digitize似乎有bucketize的一个隐藏的(从python api)等效的digitize,如this search所述。 但是似乎所引用的hidden_ops.txt已从Tensorflow中删除,并且我不清楚在python api中是否(并将继续)支持函数tensorflow::ops::Bucketize。 我必须得到类似结果的另一个想法是使用tf.train.piecewise_constant函数。但是此尝试失败了,因为

seq_ids = tf.train.piecewise_constant(tf.range(tf.math.reduce_sum(l)), tf.math.cumsum(l), tf.range(BATCH_SIZE-1))

失败,object of type 'Tensor' has no len()。 似乎没有以最通用的方式实现tf.train.piecewise_constant,因为参数boundariesvalues需要是列表而不是张量。在我的情况下,l是我的tf.data.Dataset

的小批量中聚集的一维张量

1 个答案:

答案 0 :(得分:1)

这是一种实现方法:

import tensorflow as tf

def make_seq_ids(lens):
    # Get accumulated sums (e.g. [2, 3, 1] -> [2, 5, 6])
    c = tf.cumsum(lens)
    # Take all but the last accumulated sum value as indices
    idx = c[:-1]
    # Put ones on every index
    s = tf.scatter_nd(tf.expand_dims(idx, 1), tf.ones_like(idx), [c[-1]])
    # Use accumulated sums to generate ids for every segment
    return tf.cumsum(s)

with tf.Graph().as_default(), tf.Session() as sess:
    print(sess.run(make_seq_ids([2, 3, 1])))
    # [0 0 1 1 1 2]

编辑:

您还可以使用tf.searchsorted来实现相同的功能,其方式与您为NumPy建议的方式更相似:

import tensorflow as tf

def make_seq_ids(lens):
    c = tf.cumsum(lens)
    return tf.searchsorted(c, tf.range(c[-1]), side='right')

这两个实现都不应该是TensorFlow模型中的瓶颈,因此对于任何实际目的,选择哪个都不重要。但是,有趣的是,在我的特定机器(Win 10,TF 1.12,Core i7 7700K,Titan V)上,第二种实现在CPU上运行时慢约1.5倍,在GPU上运行时快约3.5倍。