将张量数据裁剪到包围体

Posted

技术标签:

【中文标题】将张量数据裁剪到包围体【英文标题】:Clipping tensor data to a bounding volume 【发布时间】:2021-03-25 12:07:35 【问题描述】:

我有 2 个关于 tensorflow 2.0 的问题,重点是 tensorflow 如何在其操作图中处理组合条件测试。

任务:将大量数据点切割成块,并将索引存储到属于该卷的样本(而不是样本本身)。

我最初的方法:循环所有元素并收集“边界体积”内的数据点的索引。这非常慢,无论我如何重新排序坐标上的比较。

    # X.shape == [elements,features]
    # xmin.shape == xmax.shape == [features]

    def getIndices(X, xmin, xmax):
        i = 0
        indices = tf.zero(shape[0], dtype = tf.int32)
        for x in X:
            if (x[0] > xmin[0]):
                if (x[1] > xmin[1]):
                    if (x[2] <= xmax[2]):

                        # ...and so on...

                        indices = tf.concat([indices, i], axis = 0)
            i = i + 1
        return indices

然后我想出了生成布尔张量并在逻辑上“和”它们以获得我需要的元素的indices 的想法。快了很多,如下一个示例所示:

    # X.shape == [elements,features]
    # xmin.shape == xmax.shape == [features]

    def getIndices(X, xmin, xmax):
        # example of 3 different conditions to clip to (a part of) the bounding volume 
        # X is the data and xmin and xmax are tensors containing the bounding volume

        c0 = (X[:,0] >   xmin[0])
        c1 = (X[:,1] >   xmin[1]) # processing all elements
        c2 = (X[:,2] <=  xmax[2]) # idem

        # ... there could be many more conditions, you get the idea..

        indices = tf.where(tf.math.logical_and(c1, tf.math.logical_and(c2, c3) )

        return indices

    #    ...

    indices = getIndices(X, xmin, xmax)
    trimmedX = tf.gather(X, indices)

这段代码产生了正确的结果,但我想知道它是否是最优的

第一个问题是关于调度的:

将保存操作的张量流图剔除(块) 条件测试,如果它知道一些(块)元素已经测试过 False。因为logical_and 结合了逻辑 条件,不会对这些元素进行后续条件测试 永远产生True

确实,在上面的示例中,c1c2 正在询问可能 c0 已从集合中排除的元素。尤其是当您有大量元素要测试时,这可能是浪费时间,即使在并行硬件平台上也是如此

那么,如果我们根据之前的测试结果级联测试呢?虽然看起来像是一个已解决的问题,但这个解决方案是不正确的,因为最终的 indices 张量将引用一个子集 _X,而不是总集 X

    # X.shape == [elements,features]
    # xmin.shape == xmax.shape == [features]

    def getIndices(X, xmin, xmax):
        c0 = (X[:,0] >   xmin[0])
        indices = tf.where(c0)
        _X = tf.gather(X, indices)

        c1 = (_X[:,1] >   xmin[1]) # processing only trimmed elements
        indices = tf.where(c1)
        _X = tf.gather(_X, indices)

        c2 = (_X[:,2] <=  xmax[2]) # idem
        indices = tf.where(c2)
        return indices

    ...
    indices = getIndices(X, xmin, xmax)
    trimmedX = tf.gather(X, indices)  # fails: indices refer to a trimmed subset, not X

我当然可以通过简单地扩展 X 来“解决”这个问题,这样每个元素也可以在原始列表中包含自身的索引,然后像以前一样继续。

所以我的第二个问题是关于功能的:

tf 是否有方法让 GPU/张量基础设施提供 簿记没有花费内存/时间在这看似 简单的问题?

【问题讨论】:

我很确定我可以提供一个解决方案,但老实说,我读了三遍,无法理解你真正想要做什么 好吧,也许我应该提到 X 具有形状 [元素、特征],而 xmin 和 xmax 都具有形状 [特征]。我要做的是获取位于边界体积内的元素的索引,其中体积由某些特征值的限制(最小值和/或最大值)定义。 我用更多的结构更新了这个问题,并重新措辞了一下。我不是以英语为母语的人,所以我希望现在更清楚。 【参考方案1】:

这将返回大于minimum 和小于maximum 的所有索引,当这两个索引与X 具有相同数量的特征时

import tensorflow as tf

minimum = tf.random.uniform((1, 5), 0., 0.5)
maximum = tf.random.uniform((1, 5), 0.5, 1.)

x = tf.random.uniform((10, 5))

indices = tf.where(
    tf.logical_and(
        tf.greater(x, minimum),
        tf.less(x, maximum)
        )
    )
<tf.Tensor: shape=(22, 2), dtype=int64, numpy=
array([[0, 3],
       [0, 4],
       [1, 1],
       [1, 2],
       [1, 3],
       [1, 4],
       [3, 1],
       [3, 3],
       [3, 4],
       [4, 0],
       [4, 4],
       [5, 3],
       [6, 2],
       [6, 3],
       [7, 1],
       [7, 4],
       [8, 2],
       [8, 3],
       [8, 4],
       [9, 1],
       [9, 3],
       [9, 4]], dtype=int64)>

【讨论】:

您的解决方案类似于我的 OP 的第二个列表。那行得通!但是这两个条件测试与logical_and 结合在一起并存在于一个图中,对,所以假设您期望tf.greater(x, minimum) 中的大多数连续元素将返回False,对于其他条件类似,(对于不同的元素) .如果x 很大,图表是否足够聪明,可以剔除不必要的二次测试?因为logical_and,理论上,应该可以丢弃正在测试第二个条件的warps/gpublocks,这些元素已经通过第一次测试。

以上是关于将张量数据裁剪到包围体的主要内容,如果未能解决你的问题,请参考以下文章

python 张量流中的梯度裁剪

使用张量流进行文本识别

tflearn/张量流 |多流/多尺度/集成模型定义

Numpy 将矩阵附加到张量

OpenCV Python实现旋转矩形的裁剪

将张量变量(非常数)转换为 numpy 数组? [复制]