在TensorFlow中应用布尔掩码以持续张量的两个维度

时间:2018-02-15 23:12:49

标签: python numpy tensorflow

我正在将一堆Numpy计算移植到TensorFlow。在我计算的一个阶段,我使用布尔掩码从大数组中提取和展平值的子集。数组可以有许多维度,但布尔掩码仅作用于最后两个维度。在Numpy中,它看起来像这样:

mask = np.array([
    [False, True , True , True ],
    [True , False, True , True ],
    [True , True , False, False],
    [True , True , False, False]]

large_array_masked = large_array[..., mask]

我无法弄清楚如何在TensorFlow中完成相同的操作。我试过了:

tf.boolean_mask(large_array, mask, axis = -2)

这不起作用,因为tf.boolean_mask()似乎没有采用负轴参数。

作为一个丑陋的黑客,我试图强制mask使用以下内容广播到与large_array相同的形状:

mask_broadcast = tf.logical_and(tf.fill(tf.shape(large_array), True), mask)
large_array_masked = tf.boolean_mask(large_array, mask_broadcast)

似乎mask_broadcast具有我想要的形状和值,但我收到错误:

ValueError: Number of mask dimensions must be specified, even if some dimensions are None

推测会发生这种情况,因为large_array是根据输入计算的,因此其形状不是静态的。

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

一般来说,我发现在tensorflow中你需要知名的形状。这是因为大多数操作都是矩阵乘法,矩阵是固定的形状。

如果你真的想这样做,你需要转换为稀疏张量,然后应用tf.sparse_retain

等同于"我通常在tensorflow中使用的是将掩码与large_array乘以False值(large_array_masked = large_array * mask)。这保持了原始形状,因此更容易传递到密集层等...

答案 1 :(得分:1)

我想出了一个解决我的狭隘问题的黑客,所以我在这里发帖,但是我接受了@Sorin的回答,因为它可能更普遍适用。

为了解决tf.boolean_mask()只能对初始索引起作用的事实,我只是向前滚动索引,应用掩码,然后将它们回滚。以简化形式,它看起来像这样:

indices = tf.range(tf.rank(large_array))
large_array_rolled_forward = tf.transpose(
    large_array,
    tf.concat([indices[-2:], indices[:-2]], axis=0))
large_array_rolled_forward_masked = tf.boolean_mask(
    large_array_rolled_forward,
    mask)
new_indices = tf.range(tf.rank(large_array_rolled_forward_masked))
large_array_masked = tf.transpose(
    large_array_rolled_forward_masked,
    tf.concat([new_indices[1:], [0]], axis=0))